hiyoko-programingの日記

プログラミングを勉強したてのひよっ子。   エンジニア目指して勉強中。

複数人で開発する方法

1. 事前準備

 git-app というアプリケーションを作成し、作業を進めていく。

アプリケーションを新たに立ち上げる

git-app というアプリケーションを新たに作成

以下の手順で操作をしていく。

ターミナル
1
2
3
4
$  pwd  #現在のディレクトリがprojectsであることを確認
$  rails new git-app -d mysql
$  cd git-app
$  rails db:create

これでアプリケーションのベースは作成できた。

ローカルリポジトリを作成してコミットする

git-app をローカルリポジトリにする

以下の手順で作業していく。

GItHub Desktop から git-app のローカルリポジトリを作成。左上の「Current Repository」→「Add」→「Add Existing Repository」を選択

https://tech-master.s3.amazonaws.com/uploads/curriculums//6e9e48ee48f7e39bf1a6edbe1a5b97a2.png

projects にある git-app を選択し「Add Repository」をクリック

https://tech-master.s3.amazonaws.com/uploads/curriculums//fa51fee80cc1f7482c25eb82781b1ff0.png

 「Add Repository」がクリックできない場合、以下の作業を行う。
該当するアプリケーションのディレクトリで以下の作業を行った後に、「ローカルリポジトリを作成」の作業を行う。

ターミナル
1
2
$ cd ~/projects/git-app
$ git init

rails のバージョンによっては rails new 時に git init がされないケースがある。

 コミットする

ローカルリポジトリにある全てのファイルを選択してコミットする。その際のコミットメッセージは、最初のコミットなので「Initial commit」としておく。

https://tech-master.s3.amazonaws.com/uploads/curriculums//4d16b65a8bda6fc71e4351fa81b6b129.png

リモートリポジトリを作成

リモートリポジトリを作成する。今回はローカルリポジトリをプッシュする方法でリモートリポジトリを作成していく。

 リモートリポジトリを作成

コミットしたので、リモートリポジトリに反映させる。
まだリモートリポジトリを作っていないが、GitHub Desktop では、Publish ボタンを押すとリモートリポジトリが作られていない場合にリモートリポジトリも作ってくれる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//1120b331da61141f132ceea9676f1bab.png

すると、以下のようなモーダルが表示され、リモートリポジトリを作成できる。リポジトリ名はそのままで構わない。
リポジトリを非公開にする必要はないので、今回は[Keep this code private]のチェックは外しておく。

https://tech-master.s3.amazonaws.com/uploads/curriculums//d65473e6a01b3c39c6bad3ae84b53144.png

[Publish repository]ボタンをクリックすると GitHub のリモートリポジトリが作成できる。

ここで GitHub のトップページに移動する。
GitHub の Your repositories の欄に git-app があれば上手く行っている。

https://tech-master.s3.amazonaws.com/uploads/curriculums//37950640da27c1c56a503404805307d0.png

以上で事前準備は完了。

2. ブランチを作成する

ブランチについて

ブランチとは、リポジトリで管理しているプロジェクトの流れを記録していく場である。リポジトリは必ずブランチを持っている。これはリポジトリのバージョン管理がブランチの上で行われているためである。

Git でリポジトリを作成した時点で、開発者はmaster ブランチという履歴上で開発をする状態となる。そこからトピックブランチを作成し、機能別に並行作業していく。ブランチ(branch)は「枝」という意味。1つの主流から枝の様に別れてプロジェクトが管理できるとイメージ。

https://tech-master.s3.amazonaws.com/uploads/curriculums//0053e92f1840864d64e8325409a610e3.png

master ブランチ

master ブランチとは、リポジトリに最初のコミットを行うと自動で作成されるブランチ。master ブランチがリポジトリの大元のブランチとなることが多い。これまで行ってきたコミットはすべて master ブランチの履歴上で管理されていた。

トピックブランチ

ブランチは複数作ることが出来る。そして、ブランチを作るにはすでにあるブランチをコピーしなくてはいけない。最初のブランチは master ブランチなので、次に作るブランチは master ブランチをコピーしたブランチになり、それをトピックブランチと言う。

実際の開発では下図の様に、機能ごとにトピックブランチを作成して、完成したら master ブランチに結合していく。

ブランチを作成する

ブランチは実装機能ごとに作成すると良い。今回はアプリケーションのメイン機能である、記事を投稿する機能を実装する。

 記事投稿機能についてのブランチを作成

以下から新しいブランチを作成できる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//1718148729740f975e4271686c679ef3.png

master ブランチから新しいブランチを作成する。ブランチ名は記事の投稿機能を実装するブランチなので、add-posting-article-functionとする。
https://tech-master.s3.amazonaws.com/uploads/curriculums//89da902eece5d666d89d65cf75c2f13b.png

ブランチ作成後に、add-posting-article-functionブランチに切り替わっているか確認する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//ab4db5d6a08542eb4804ad9b621ded96.png

上図の様になっていれば、新しいブランチを作成し、作業場をそのブランチへ移動出来ていることになる。

3. プルリクエストを作成

ブランチを用いた開発を行う上で、プルリクエストについても並行で学ぶ必要がある。

プルリクエストについて

機能実装のためにコードを追記したり、保守のために修正したりするときにブランチは作成される。そのため、そのコードは誰かにチェックをしてもらう必要がある。そこで役立つのがプルリクエスト。

プルリクエストとは

ブランチでのコミット履歴を残すと共に、各コミットにおける変更修正にコメントをつけることができる GitHub の機能のことを言う。以下の図のような形で、1つのブランチでの作業について、コミュニケーションが取れる掲示板のようなものがプルリクエスト。

https://tech-master.s3.amazonaws.com/uploads/curriculums//cd968fb7a434300c67e11c130ac6dda4.png

 

プルリクエストを作成

プルリクエストの作成は以下の流れ。

  • 空のコミットを作成する
  • プッシュする
  • プルリクエストを作成する
  • 同じブランチで変更修正を加えていく

順番にこれらの作業を追っていく。

空のコミットを作成してプッシュ

プルリクエストを作成するには対象のブランチで少なくとも1つのコミットを新たにしなくてはならない。しかし、現状このブランチではまだ作業をしていないのでコミットできるものがない。

この場合、 空のコミット をすることでプルリクエストは作成できる。

ターミナル
1
$ git commit --allow-empty -m 'create pull request' # --allow-emptyオプションで何も作業が無くても(git statusで何も表示されていなくても)コミットできる

GitHub Desktop で add-posting-article-function ブランチで空のコミットができていることを確認。

https://tech-master.s3.amazonaws.com/uploads/curriculums//d5d55555c96e74bf34346b879d26fc2e.png

[Publish branch] をクリックしてプッシュ。

プルリクエストを作成

まず、プッシュをしたら GitHub Desktop 上の [Create Pull Request] をクリック。

https://tech-master.s3.amazonaws.com/uploads/curriculums//b355eb5d63261794d1e3c68a17018ac1.png

すると以下の画像のようにブラウザが起動して、プルリクエスト作成画面が表示される。以下のように情報を入力してプルリクエストを作成する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//929c338fdf0941c1f3730c17afb938a9.png

プルリクエスト作成時のポイント

プルリクエストのタイトルには[WIP]をつける

WIP とは、Work In Progress の略で作業中の意味。反対に作業が終わっている場合には WIP を外します。「実装途中の機能には WIP をつける」「実装が一旦完了したプルリクエストからは WIP を外す」と考える。上記のアプリケーションではまだ投稿機能は実装途中であるため、この時点では WIP を付けておく。

プルリクエストの詳細には、What(何を)と Why(なぜ)を書く

What(どのような実装をしているのか)と Why(なぜこの実装が必要なのか)を書くことで、このブランチは何を実装していて、なぜその実装を行ったのかが他の人に伝えることができる。What をしっかり書くことで、他者にコードを見てもらう際に、スムーズな理解を促すことができる。アプリケーションの機能が複雑になればなるほど、コードを読んだだけでは、何をしているのか把握することは難しくなるからである。また、Why をしっかり書くことで、本来の目的に沿ったコミュニケーションが可能となる。実装目的が伝わっていないと、欲しい意見をもらうことはできない。
 Pull Request に最初に書き込むメッセージは会社やチームによって異なる。

マークダウン表記で書くこと

マークダウンとは記法の一種。マークダウンを使うことでシンプルな記法で HTML 文書を書くことができる。

4. 作成したブランチで実装

add-posting-article-function ブランチで実際に投稿機能を作成する。今回は一から投稿機能を実装するのではなく、Rails が備えている scaffold というジェネレーターを使用する。scaffold を使えば、アプリケーションの雛形のソースコードを自動で生成してくれる。

 scaffold でコードを生成

ターミナル
1
$ rails g scaffold article title:string author:string text:text

このコマンドによって article に関する、コントローラーやモデル、マイグレーションファイルなどが一括で生成された。生成されたマイグレーションファイルを実行する。

ターミナル
1
$ rails db:migrate

以上でアプリケーションの雛形が完成したのでサーバーを起動してlocalhost:3000/articlesに接続してみる。

 作業内容をコミット・プッシュする

投稿機能を実装できたので、ここまでの作業内容をコミット、プッシュ。GitHub Desktop で全てのファイルを選択してコミットする。コミット名は「generated files by scaffold」にし、コミットができたら、プッシュする。

https://tech-master.s3.amazonaws.com/uploads/curriculums//b02b743e5c495e6f4a25033d164d75e0.png

 コミットを確認

ブラウザで先程作成したプルリクエストのページを確認すると、generated files by scaffoldのコミットが反映されている。

https://tech-master.s3.amazonaws.com/uploads/curriculums//f7c9f0c2392bc3e0727f1fadcd95d8d7.png

5. コードレビュー依頼をする

複数人での開発においては、コードの記述内容に問題が無いか、他の開発メンバー等にレビューを依頼する。それをコードレビューと言う。

コードレビューを依頼

投稿機能の作業が終わったので、次はレビューを依頼する。プルリクエストの URL(https://github.com/<ユーザー名>/git-app/pull/1のような形になっているはずです)を共有することで、他者にレビューを依頼することができる。

 WIP を外す

レビューを行う前に WIP を外す。というのも、今回のプルリクエストでは投稿機能の実装が目的だったので、現時点で目的の機能実装は完了しているため、WIP を外す。以下のようにするとプルリクエストのタイトルを修正できる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//b6030be110653ed3ccd0f9f44cc31e79.png

 URL を確認

共有すべき URL の確認をしておく。以下の様になっているはず。

https://tech-master.s3.amazonaws.com/uploads/curriculums//af1788177fbbafe82703f381d054c2a8.png

上記以外の URL(例えばリポジトリの URL)を共有しても、レビューする人はどのプルリクエストをレビューすべきなのかわからず、無駄な時間が発生してしまう。間違えないように注意。

 コードレビュー依頼

レビュー依頼の方法は様々。Slack 等で URL 共有する方法もあれば、プルリクエスト上で Slack の様に username にメンションをつけることで本人にレビュー依頼の通知が行くようにすることもある。

 

(レビュアー側の場合)コードレビューをする

自分がレビュアーになった場合、プルリクエストにコメントする。

 プルリクエストにコメント

Files changed をクリックすると、変更修正されたコードが一覧できる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//0ab9481bccf8face48847b3d81107f6b.png

コードを見てみると、articles.coffee というファイルが生成されていた。今回の場合はこのファイルは必要ない。消すように指示を出す。

特定のファイルのコメントを残したい行にカーソルを当てると、青色の+ボタンが現れる。このボタンを押すとコメント用のフィールドが現れるのでコメントを書く。以下のように記述して Add single comment をクリックする。

https://tech-master.s3.amazonaws.com/uploads/curriculums//e83fcd4d89a57a82e3e9b28eb60c2933.png

また、特定のファイルではなく、プルリクエスト全体に対してのコメントを残すこともできる。
今回は、プルリクエスト Conversation タブの最下部からプルリクエスト全体に対して、画像と同じようにコメントする。

https://tech-master.s3.amazonaws.com/uploads/curriculums//82fc264bcab2b8fd363cc3d8df6f0afb.png

指摘点を修正して、再度コードレビューを依頼

レビューを元にコードを修正していく。今回は例なので自身で書いたレビューを修正。レビューについてわからない点があればコメントに返信する形で質問することもできる。

 コードを修正

今回のコメントの例では、いくつかのレビューをもらったが、指摘された箇所をまとめて修正してコミットをしてしまうとコミットが大きくなってしまう。コミットが大きくなるとレビュアーの負担が大きくなってしまうので、修正の内容ごとにコミットをしていく。

以下の作業を2つのコミットに分けて修正をしていく。

不要なファイルの削除

テキストエディタで articles.coffee を削除。

https://tech-master.s3.amazonaws.com/uploads/curriculums//0a6396b3c8640d8da4e7ba0ea900d9d0.png

不要なコメントアウトの削除

articles_controller.rb の不要なコメントアウトを削除。

https://tech-master.s3.amazonaws.com/uploads/curriculums//78e9a3b4405d880600215094f3dd218e.png

指摘された箇所を修正したら、そのたびに該当のコメントに返信をする。該当のコメントに返信することで、レビュアーは自分のコメントがちゃんと読まれているかの確認できる。レビューをもらった側としては修正に抜け漏れがないかのチェックになる。

プルリクエスト全体に対してのコメントに「修正しました」と返信する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//579195e46a2e1e241390f96fc3c4539e.png

(レビュアー側の場合)LGTM を出す

修正依頼は間違いなく修正されているような場合は、「これ以上修正箇所は無いと判断した」というメッセージを伝える必要がある。その際によく使われるのが LGTM という表現である。

 LGTM を出す

LGTM とは、Looks good to me の略で、「コードに問題がないのでマージしていいよ!」というプログラマー慣習。
レビュアーであれば、プルリクエストのトップページのコメントに LGTM の旨を書く。LGTM を伝えるための画像を貼り付けたりすることもある。

https://tech-master.s3.amazonaws.com/uploads/curriculums//333b3b3d79bf95ba092ca31213dd20f1.png

6. プルリクエストのマージ

これでコメント投稿機能の実装は完了。ただこれまでは copy ブランチでの操作である。ブランチは最終的に master ブランチへ結合する必要がある。これからその操作を行う。

プルリクエストをマージする

 マージ

マージ(merge)は統合するという意味。機能実装のために作成したブランチを、master ブランチに統合する作業を言う。今回の場合では、このタイミングでブランチをマージすれば、次に作成するブランチにはコメント投稿機能が備わっていることになる。

 マージする

LGTM をもらったら、add-posting-article-function ブランチを master ブランチにマージする。[Merge pull request]→[Confirm merge]でマージできる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//871a565a10bab053eee1b5d8e6314468.png

 マージしたブランチを削除

マージが完了すると、GitHub 上のブランチを削除することができるようになる。これ以降 add-posting-article-function ブランチは不要なので、「Delete branch」ボタンを押して削除する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//69ea8bd7880716d98c5e4a32cc6679cc.png

プルする

リモートリポジトリでは copy ブランチの情報を、master ブランチにマージすることができた。次にローカルリポジトリにマージした情報を反映する必要がある。

 プル

リモートリポジトリの変更をローカルリポジトリに取り込む操作のことを言う。リモートリポジトリはマージ後の情報になっているが、ローカルリポジトリではマージ前の情報のままなので、次のブランチを作成する前にプルをして情報を反映させる必要がある。

 プルする

GitHbub Desktop で master ブランチに切り替え、[Fetch origin]ボタンをクリックすると、リモートリポジトリとの差分を確認する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//6939bc1a28cfc20495ef871940609dc2.png

[Pull origin]ボタンに切り替わるので、ボタンをクリックしプルする。

https://tech-master.s3.amazonaws.com/uploads/curriculums//acc51e844dd2fc19331f168951a0eb7d.png

これでローカルリポジトリも作業ブランチをマージした状態が反映された。以上でブランチを用いた開発の流れについて一通りである。

なお、コマンドで上記の操作を行う場合は以下の流れになる。

ターミナル
1
2
$ git checkout master #masterブランチに移動する
$ git pull origin master #リモートリポジトリ(origin)のmasterブランチを反映させる

補足事項

上記の流れの中で説明をしなかった、重要な点について。

他人のアプリケーションを自分の環境に反映する

複数人でアプリケーションを開発する際は誰か 1 名がアプリケーションを作成し、他のメンバーがそのアプリケーションを共有してもらう必要がある。その時に役立つのがgit clone。

 git clone

以下のようにオリジンの URL を指定することで、アプリケーションのローカルリポジトリとしてダウンロードすることができる。

ターミナル
1

この上記には.gitディレクトリが含まれており、clone 元のオリジンが指定されている。したがって、このディレクトリでプッシュをすれば、clone 元に push がなされる。

当然、赤の他人のリモートリポジトリに勝手にプッシュすることはできない。リポジトリの Collaborators に追加されることで、プッシュが可能になる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//7d819be3568cd41b0dfafcc59b96c30c.png

GitHub が推奨するフロー

様々な使い方ができる GitHub だが、GitHub 自体が推奨する開発フローがある。それをGitHub flowと言う。

 GitHub flow

大まかに列挙すると以下のフローで開発することを GitHub flow と言う。

  • masterブランチのものは何であれデプロイ可能である
  • 新しい何かに取り組む際は、説明的な名前のブランチを master から作成する(例: new-oauth2-scopes
  • 作成したブランチにローカルでコミットし、サーバー上の同じ名前のブランチにも定期的に作業内容を push する
  • フィードバックや助言が欲しい時、ブランチをマージしてもよいと思ったときは、 プルリクエスト を作成する
  • 他の誰かがレビューをして機能に OK を出してくれたら、あなたはコードをmasterへマージすることができる
  • レビューを経てマージをしたら、直ちにデプロイをする

詳細については以下のリンクを確認すると良い。

デプロイ時における GitHub の役割

 デプロイ

端的に説明すると、アプリケーションをサーバー上で利用可能な状態にすること。これまではローカル環境でのアプリケーション開発を経験してきましたが、最終的には外部のサーバーを用意して(契約して)、誰かに見てもらえる形にする必要がある。その作業をデプロイと言う。

 デプロイと GitHub

デプロイをする際には、GitHub を介して行うと便利。GitHub のマスターブランチのみがサーバー側に反映されるようにデプロイする。何か新機能を加えたい時や修正をしたい時は、

  1. ブランチを作成
  2. コード変更修正
  3. 動作確認
  4. マージ
  5. サーバー側に pull デプロイ

と言った流れで実施すると、稼働中のサービスを長時間止めること無くアップデートすることができる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//ffffaebf53c72df85be1de5b0ebfeea2.png