GitHub FlowとPull Request駆動開発をYWTでふりかえり

最近関わったプロジェクトでは、GitHub FlowとPull Requestベースの開発を行いました。
個人的には、まともにこのスタイルで開発するのは初めてだったということもあり、YWT(やったこと、わかったこと、次にやること)形式でふりかえった結果を紹介していきます*1

モダンな開発現場では当たり前に行われていることなので、「今更?」と思うかもしれませんが、「本やWebを真似しても、小難しいコマンドがたくさん出てくるばかりで、本当に開発効率が上がってるのか分からない゚・(ノД`)・゚・。」みたいな人もいるのではと思います(私がそうでした)。

ちなみに、プロジェクト開始前の自分のGit/GitHubスキルは以下のとおりでした。

  • GitHubは使っていたが、一人でmasterブランチに対して「add->commit->push」を行うだけ
  • 書籍「GitHub実践入門」を通読した

というわけで、「実践」してみて分かった内容として、重箱の隅っぽいところを紹介していきたいと思います。
なお本エントリはGitやGitHubGitHub Flowそのものについての解説記事ではないのであしからず。。

以下、プルリクエストはPRと略します。

Y: やったこと

Y1) ごく普通のGitHub Flow

  • masterブランチとPR用のトピックブランチのみの運用
  • masterに対してpushは厳禁
  • トピックブランチはレビュー後にmasterにマージ

また、hubSourceTreeなどは使わず、Git CLIGitHubのUIのみ使用。

Y2) レビュー依頼はチャットで

PRを誰がレビューするかは、GitHubのAssigneeは使わずに、HipChatでメンションする形式でした。
規模が小さいから可能な運用かもしれないです。

Y3) PullRequestはフォーマットを決めて

テンプレートについては、『Pull Request のフォーマットを決めるとレビューの効率が3倍よくなる(Crocos Engineering Blog)』を参考にしました。

テンプレート自体は社内のWikiにあって、コピペして、PRを送信する、という流れです(記事と同じですね)。

開発当初は、上記の記事で紹介されているフォーマットをほぼそのまま使っていました。
ただ、テンプレートを埋める時間が結構な手間になっていたので、最終的には以下の通り、かなりシンプルなテンプレートになりました。

## 概要
## 詳細(主に技術的変更点)
## 使い方・確認方法(設定変更やコマンドが必要ならばそれも書く)
## 保留した項目・TODOリスト
## その他(レビューで見てもらいたい点、不安な点、参考URLなど)

Y4) レビューする時は git stash で今の作業を退避させる

プロジェクトの特性上、レビューはGitHub上でdiffを眺めるだけでなく、手元で動かして確認することが多かったです。

$ git stash
$ git checkout master
$ git fetch
$ git checkout feature-to-review
  • git stash
    • 作業中ブランチの変更を一時的に退避
  • git checkout master
    • masterブランチに移動(1つ前のブランチに戻るのと同じことなので git checkout - でも可)。
  • git fetch
  • git checkout feature-to-review
    • レビュー対象のブランチ(feature-to-review)に移動

これで手元にレビュー対象のコードが置かれたことになるので、実際に動かして確認します。実際に動かすために、PRのテンプレートにある「使い方・確認方法」の項目が役立ちます。
もちろん、動くだけでなくコードそのもののレビューも一緒に行います。

レビューが終わったら、感謝と賞賛の気持ちを込めて LGTM :+1: し、以下の通り、元の作業に戻ります。

$ git checkout my-feature
$ git stash apply
  • git checkout my-feature
    • 作業中ブランチ(my-feature)に戻る。
  • git stash apply
    • 退避した内容を戻す。

Y5) マージはGitHub画面から

トピックブランチのマージは画面から行います。マージするのはレビュアーでなく依頼者(コード書いた人)。

GitHubの画面からマージできない=コンフリクトが起きている、なので、マージする人の責任でコンフリクトを解消します。

Y6) PullRequestのラベルを活用

なるべくPRがクローズされるまでのサイクルは短くすべきですが、それでも溜まる時は溜まってしまいます。

一覧で見た時に状況がぱっと見で分かるように、ラベルを活用しました。
作ったラベルは以下です。

  • WIP
  • レビュー待ち
  • 緊急・重要
  • 緊急・重要じゃない
  • 緊急じゃない・重要
  • 緊急じゃない・重要じゃない

下4つは「7つの習慣」にある時間管理マトリクスからですね。

Y7) コマンドでGitを使う場合、git-prompt, git-completionが便利

コマンドでGitを操作していると、以下のあたりが作業効率を下げます。

  • git status を何度も使う。
  • 作業ブランチ名を確認するために、 git branch を何度も使う。
  • トピックブランチの名前はなるべく特徴を表す名前にするため、ブランチに移動するのに長いブランチ名を毎回入力する。

git-prompt, git-completionを使うと、この辺の問題を解決できます。 調べるといっぱい出てくるので、手順は割愛しますが、要するに、プロンプトに各種情報・作業ブランチ名を表示させたり、ブランチ名で補完を効かせる仕組みです。

W: わかったこと

W1) レビューする側の心理

なるべく早くレビューしてあげたいというのが人の心理だと思いますが、レビュー依頼を受けてすぐレビューすると、コンテキストスイッチが発生します。
そこで、毎日この時間(昼休み明け)にレビューする、みたいに自分ルールを決めてレビューするのがよいかなと思います。 「☓☓はいついつにレビューします」「△△は急ぎでレビューしてください」などを朝会・夕会で共有するのも重要ですね。

W2) Gitコマンドは意味を確認しながら動かすと理解が深まる

ネットに載っているコマンドをそのまま打っているだけの時はなかなかGitの操作に馴染めなかったですが、一つ一つ調べながら確認していくと理解が深まっていったと思います。

W3) レビュー中のトピックブランチから次のトピックブランチを作ることの是非

レビュー中のトピックブランチ b1 がある時に、b1 の変更を元にしたトピックブランチ b2 を開発していきたい、というケースでどうするのがベストなのか、悩ましい問題でした。

b1 のレビューで指摘が入ると、b2 側でもそれに伴って rebase/merge したり、修正自体が無駄になることがありますよね。

そもそも、 b1のレビューが完了し、 b1 -> master へのマージが行われて b1 がリモートリポジトリから削除されると、b1 から派生した b2 はどうなるんだ?みたいな問題があります。

先に b2 -> master ないしは b2 -> b1 へのPRを作ってレビューしてもらう、というのも変ですしね。

割とよくあるケースな気もするのですが、他のプロジェクトってどうしてるんでしょう?

T: 次にやること(やりたいこと)

T1) PRの状況をHubotで通知

PRの状況を見に行くのに、毎回GitHubの画面にアクセスしなくても済むように、Hubot等で通知してくれるようにしたいと思います。

T2) PRの作成を楽にする

やったことで述べたとおり、PRのフォーマットは社内のWikiからコピペしていたのですが、これが結構面倒でした。

リンククリックなど、ワンステップでテンプレート付きのPRが作成できるようにしたいです。

GitHub Issueの場合、これが可能です。  https://github.com/{account}/{project}/issues/new?title=aaa&body=bbb みたいなURLで、クエリパラメータにタイトルや本文を渡せるので、これをプロジェクトの README.md に書いておけば、そのリンクをクリックしてテンプレート付きのIssueが作成画面に遷移できるようになります。

同じことをPRでもしたいのですが、PRの場合、URLにマージ元ブランチ名が必要であり、そのブランチ名が分からないので、決まったURLを使えないのですよね。

調べた感じだと、ChromeのExtensionや、hubコマンドで使える仕組みがあるみたいですが。。

おわりに

というわけで、実践してみて色々とわかったことがありました。

  • レビュー中のトピックブランチから次のトピックブランチを作りたい場合の運用
  • ワンステップでテンプレートからPRを作成する方法

上記2点をはじめ、今後も改善しながら続けていきたいです。

*1:念のためですが、プロジェクトのふりかえりも開発チーム内で行いました。