最初から git rebase しやすくするためのコミットの作り方

概要

GitHub 上でレビューしやすい状態にするため、いつも git rebase でコミットの整理を行うようにしているが、時々 rebase 時に conflict を起こして面倒になることがあった。最近思いついた方法で予めコミットを作っておけば git rebase がしやすくなりそうだと思ったのでその方法を書いた。

ルール

以下のルールをブランチを切った時点から意識する。あらかた実装が終わり微調整の段階になった時点で git rebase でコミットの整理を行う。

  1. コンポーネント(クラス、モジュール、React コンポーネントなど)の追加と適用は同じコミットに混ぜない
    • ファイルの追加・削除は、1 ファイルごとに 1 コミット
    • 追加したコンポーネントを別のコンポーネントから利用するためのコミットは、別のコミットとして切り出す
    • 同じコミットに混ぜてしまうとあとで分離したいときに面倒だし、コミット順を変えたりするとよく conflict してうざいので、最初から分けてしまう。
  2. コミット全体の流れを機能やリファクタを完成する一連のストーリーとして作る
    • コンポーネント作成・削除: 機能実現やリファクタに必要な部品を追加、削除を行う
    • コンポーネント統合: 作成したコンポーネント群を利用し、機能が働く状態にする
    • 調整: 本筋とは関係の薄い修正(Linter の警告の抑制や見た目の調整など)を行う
  3. 必要に応じてコミットの本文(body)にコミットの意図や詳細を書く
    • あとで rebase するときの助けになるし、コードレビューもしやすくなる
    • コンポーネント統合のコミットは、時間がないときはどうしても一つにまとめてしまいがちなので、コミットの本文に変更の詳細を書いてごまかす

コミット例

業務中のコミットを一部修正して抜粋した。

1. サーバサイド: コンポーネント作成・削除

デプロイ後に走らせるためのスクリプトの追加と、既存コードへのメソッド追加。

Date:   Mon Aug 13 16:35:19 2018 +0900

    [#4270] Add script to create document
    この機能のデプロイ時に script を実行することで、最新の件数を保存する

A   script/2018/20180813_create_document.rb
Date:   Mon Aug 13 16:58:23 2018 +0900

    [#4270] Add RestClient#update_document

M   app/models/rest_client.rb

2. サーバサイド: コンポーネント統合

1 で追加したコードを利用して、サーバサイドの機能を実現する。

これは好みだが、実装とテストは同じコミットに含めたほうが、レビュー時に実装とテストを見比べやすくなって良いと思う。

Date:   Mon Aug 13 17:07:29 2018 +0900

    [#4270] Implement server-to-client notification

M   app/models/history.rb
M   spec/models/history_spec.rb

3. クライアントサイド: コンポーネント作成・削除

既存の React コンポーネントへの機能追加。

Date:   Mon Aug 13 19:43:04 2018 +0900

    [#4270] Add status badge

M   spa/src/Components/Common/CategoryMenu.tsx
Date:   Tue Aug 14 12:11:01 2018 +0900

    [#4270] Add requestKey props to reload current request

M   spa/src/Components/Common/Query.tsx

4. クライアントサイド: コンポーネント統合

ここまでの変更を統合して、全体の機能を実現する。

ここはもう少しコミットを分けても良かったかもしれない。コミット分割が面倒になったときは、コミット本文に変更の詳細を書いてごまかす。

Date:   Mon Aug 13 21:47:46 2018 +0900

    [#4270] Implement real-time status badge

M   spa/src/Components/List.tsx
M   spa/src/Containers/Common/List.ts
M   spa/src/Containers/XXXList.tsx
M   spa/src/Containers/YYYList.tsx

5. 調整

本筋と関係のない spec や linter まわりの修正を行った。

Date:   Tue Aug 14 18:05:27 2018 +0900

    [#4270] Fix rubocop offences

M   spec/models/history_spec.rb
Date:   Wed Aug 15 11:50:49 2018 +0900

    [#4270] Stub out RestClient

M   spec/models/history_spec.rb
Date:   Wed Aug 15 14:24:36 2018 +0900

    [#4270] Reset mock object

M   spec/models/history_spec.rb
Date:   Wed Aug 15 16:26:33 2018 +0900

    [#4270] Disable model callback in test env

M   app/models/history.rb

最後に

皆さんが普段実践している「git rebase しやすくするためのコミットの作り方」や、それに限らずもっと良さげなコミットの作り方があれば教えてほしいです!