非常に大きなfeatureブランチをフォルダ毎にレビューする

#背景
大きな機能の実装が完了し、数ヶ月前に切ったfeatureブランチをdevelopに取り込む時が来ました。しかし、そのままGitHubでPull Requestを出すと...変更が多すぎて表示に非常に時間がかかり、とてもレビューしづらい状態でした。あまりにも差分が大きい場合は一部しかコードが表示されないこともありますよね（※）。そもそもこんな大きな差分はレビューの粒度としても不適切ですし、分割してレビューしてもらうことにしました。

（※上限については[GitHub公式サイト](https://help.github.com/articles/limits-for-viewing-content-and-diffs-in-a-repository/)にまとまっています。）

具体的には今回作業を行ったのはiOSアプリのリポジトリで、変更内容は以下のような感じでした。

- CocoaPodsでのライブラリ追加
- 画像や音声などのリソースファイルの追加
- Embedded Frameworkの作成と追加
- アプリ本体のコードの変更

これらは、例えばCocoaPodsでのライブラリ追加だったらPodsフォルダの下、という風にフォルダで別れていたので、フォルダごとにPull Requestを作成できないか考えました。

#フォルダ毎にPull Requestを出す

前提として機能開発ブランチを `featureA` とし、コンフリクトは解消されているとします。

### **STEP 0:** featureAにタグをつける
作業開始地点にタグをつけておきます。（必須ではありませんが、featureAで微調整が続いているような場合に分かりやすくなります。）

```shell
git checkout featureA
git tag featureA_alpa
```
![out-1.png](https://qiita-image-store.s3.amazonaws.com/0/5217/891a09aa-253e-c1a9-bb79-1b5e0aae7f53.png)

### **STEP 1:** developからbaseブランチを切る

```shell
git checkout develop
git branch base
```

### **STEP 2:** developからcompareブランチを切る

```shell
git checkout -b compare
```
![out-3.png](https://qiita-image-store.s3.amazonaws.com/0/5217/21191919-7744-4574-28fd-2db4c3d588e5.png)

### **STEP 3:** compareブランチにfeatureAをマージ

```shell
git merge featureA_alpa
```
![out-4.png](https://qiita-image-store.s3.amazonaws.com/0/5217/8024a4d0-5d43-3d2b-9029-0fb8a2c51c92.png)


### **STEP 4:** baseブランチにレビュー対象フォルダ**以外**を取り込む

ここがポイントです！
例えば `Sources` 以下がレビューしてもらいたい対象の場合は次のようにします。

```shell
git checkout base
git checkout compare ":(exclude)Sources"
git commit
```

checkout時にパス（複数可）を指定すると、ブランチは切り替わらずに指定したファイル・フォルダの内容のみを持って来れます。 `:(exclude)` をつけるとそのパスを除外するという意味になります。

![out-5.png](https://qiita-image-store.s3.amazonaws.com/0/5217/04e7ad69-f643-c2fa-0001-d638dace10eb.png)

### **STEP 5:** compareブランチにbaseブランチをマージ

これによってSources以下の変更だけが差分として表示されるようになります。

```shell
git checkout compare
git merge base
git tag review_start
```
![out-7.png](https://qiita-image-store.s3.amazonaws.com/0/5217/53d8e696-c95c-9445-1268-d8a28cb8e9f8.png)

### **STEP 6:** pushしてPull Request !

`base` ブランチと `compare`ブランチをpushしてGitHub上でPull Requestを作成します。

```shell
git push origin base
git push origin compare
```

これでSources以下の変更のみがPull Requestに表示されるようになりました！

### **STEP 7:** レビュー & 修正
いつも通りGitHub上でコメントのやりとりやコードレビューを進め、指摘の修正を `compare` ブランチに行っていきます。
![out-9.png](https://qiita-image-store.s3.amazonaws.com/0/5217/61bce148-6b2d-ef10-e3c7-008d350d29d7.png)
チーム開発をしているとこの間にもdevelopやfeatureAも進んで行ったりしますね！（もっともfeatureAに関してはレビュー対象のフォルダへの変更はちょっと待ってもらいました。）

### **STEP 8:** 修正分をfeatureAに取り込む

修正分のコミットを featureAにリベースします。

```shell
git rebase --onto featureA_alpa review_start compare
```

![out-10.png](https://qiita-image-store.s3.amazonaws.com/0/5217/fb0db0fc-1ce8-1aa1-cf10-9cd14df6b023.png)

`compare` ブランチを `featureA` にマージします。（必要ならPull Requestを出しましょう。）

```shell
git checkout featureA
git merge compare
```
![out-12.png](https://qiita-image-store.s3.amazonaws.com/0/5217/21b054b6-63b3-f4be-499f-0edf3766fb38.png)

これでSources以下はレビュー済みの状態になりました！

後はレビューが必要なフォルダについてこれを繰り返し、全て完了したら `featureA`ブランチを `develop` に取り込みましょう！


![foldermarge2](https://user-images.githubusercontent.com/559045/40573866-e0ab012a-6102-11e8-8c76-8a0aac68f3ad.gif)
せっかくなのでGIFアニメにしてみました。

# Pros & Cons

この方法だとレビュー対象のブランチ `compare` は `featureA` の内容を全て含んでいるため、ビルドしての動作確認が可能です。新機能の仕様をよく知らないレビュワーにとって実際に動かせるのは大きなメリットです。

一方、各Pull Requestの結合部分については議論しにくいので、どう分割するかが大切になります。もし新しく作成したモジュールのインターフェースをレビューしてもらいたいなら、モジュールと利用部分の両方が含まれるようにすると良いかもしれません。