コミットをならべかえたりまとめたり

本投稿は TECOTEC Advent Calendar 2021 の10日目の記事です。

初めまして。決済認証開発システム事業部の柴田です。

PHPエンジニアをやっていますが、最近は設計業務等が多く、コーディングする機会は少なめです。
そこでGitのコミットについて、自分がよく使っている小技(?)を、備忘録も兼ねて書こうと思います。
目新しいとかトリッキーなものではないので知ってる人も多く、元々は色々なところから得た知識なので、他所の技術記事と内容が被ってる箇所があると思いますが、ご了承ください。

内容

  • コミットの並べ替え
  • コミットの集約

自分が普段使っているTortoiseGitを使ったやり方と、コンソール上でのやり方の2つを記載します。

環境・ツール

OS:Windows 10
Git:2.28.0.windows.1
Gitクライアントツール:TortoiseGit Version 2.7.0

コミットの並べ替え

並べ替えだけを使う機会はあまりないですが、
後半で紹介するコミットの集約では、連続したコミット同士の方が集約しやすいので、まずこちらから紹介いたします。

1つ注意点として、順番を入れ替えるコミット間で同じファイルを修正していると競合が起きる場合があり、別途それを解決する必要があります。
競合の解決方法はケースバイケースだと思うので、競合が起きないような条件下で行います。
個人的に、競合が起きると事故りやすいので、競合が起きた場合は並べ替えは控えています。

TortoiseGit

対象プロジェクトを開いたエクスプローラー上で右クリックし、「TortoiseGit」>「ログを表示」を選択します。

f:id:teco_shibata:20211209141317p:plain:w400

ログメッセージウィンドウが表示されます。
順番を入れ替えたいコミットの1つ前のコミットを選び右クリックし、「“[ブランチ名]”をここへリベース」を選択します。
例として、下の画像の2番目と3番目のコミットを入れ替えようと思います。なので、4番目(一番下)のコミットを選びリベースを行います。

f:id:teco_shibata:20211209141523p:plain:w500

リベースウィンドウが表示されます。
「強制リベース」にチェックを入れると、画面上部にコミットログが表示されます。 任意のコミットを選択して、「上へ」や「下へ」を押下すると、コミットの順番を並べ替えられます。
並べ替え後、順番に問題がなければ「リベース開始」を押下します。

今回は、2番目と3番目のコミットを入れ替えるので、すなわち3番目のコミットを2番目のコミットの上に持っていきます。
(画像は順番入れ替え後の状態です。 )

f:id:teco_shibata:20211209141929p:plain:w400

リベースが正常終了すると、画面下部に「リベースが終了しました。」と表示されます。
f:id:teco_shibata:20211209142350p:plain:w400
「終了」を押下して、ウィンドウを閉じます。
以上で並べ替えは終了です。

コマンドライン(Git Bash)

まず、git logでコミットIDを確認します。(コミットIDと簡単な内容が分かれば良いので、--onelineオプションで1行で表示させています。)
並べ替えたいコミットの中で、1番下にあるコミットの1つ前のコミットIDを確認します。今回は並べ替えたいのが 2c12cc1 と 06b45db なので、その1つ前の 0f90924 が該当します。

$ git log --oneline
5c03c19 (HEAD -> feature1, feature2) [fix]対応Aの修正
2c12cc1 [add]対応B
06b45db [add]対応A
0f90924 initial commit

続いて、git rebase -i [コミットID]でコミットの順番を並べ替えます。1つ前に確認したコミットIDを入力します。

$ git rebase -i 0f90924

実行するとテキストエディタが表示され、コミットが古い順に表示されます。

pick 06b45db [add]対応A
pick 2c12cc1 [add]対応B
pick 5c03c19 [fix]対応Aの修正

06b45db と 2c12cc1を入れ替えて上書き保存します。
実行後、Successfully rebased and updated refs/heads/fearture1 というように表示されれば成功です。

以上で並べ替えは終わりです。

コミットの集約

こちらの内容がメインになります。

TortoiseGit

※TortoiseGitの場合、連続したコミットでないと集約は行えないのでご注意ください。

並べ替えの時と同様に、「TortoiseGit」>「ログを表示」を選択し、ログログメッセージウィンドウを表示します。

ログメッセージウィンドウで、集約したいコミットを複数選択した後、右クリックし「1つのコミットに集約」を選択します。 例として画像のように、上2つのコミットをまとめようと思います。

f:id:teco_shibata:20211209144958p:plain:w400

コミット画面が表示されます。
画面上部で集約後のコミットメッセージを編集します。デフォルトでは集約元のコメントが記載されています。 また、画面下部では集約後のファイルが表示されるので、ダブルクリックで中身が確認できます。 メッセージの編集が終わったら「コミット」を押下します。

f:id:teco_shibata:20211209145446p:plain:w400

実行画面が表示され「成功」と表示されると、コミットの集約は完了です。

コマンドライン(Git Bash)

コンソール上でコミットを集約してみます。

こちらも並べ替えと同様に、まずgit logによりコミット一覧を表示します。
そして集約したいコミットの1つ前のコミットIDを確認します。

例として f7048a8 と c724415 を集約する場合、1つ前の edcec81 を使います。

$ git log --oneline
f7048a8 (HEAD -> feature2) [mod]出力文言の変更
c724415 (feature) [add]繰り返し処理追加
edcec81 [add]条件分岐追加
4b564bd initial commit

確認後、リベースします。

$ git rebase -i edcec81

テキストエディタが表示されます。

pick c724415 [add]繰り返し処理追加
pick f7048a8 [mod]出力文言の変更

c724415(古い方)に f7048a8(新しい方、修正分)を取り込むため、下記のように修正します。

pick c724415 [add]繰り返し処理追加
s f7048a8 [mod]出力文言の変更

sはsquashを意味します。この状態で上書き保存します。

すると、続けてコミットメッセージを編集するテキストエディタが表示されます。

# This is a combination of 2 commits.
# This is the 1st commit message:

[add]繰り返し処理追加

# This is the commit message #2:

[mod]出力文言の変更

集約後は[mod]コメントは不要なので、1st commitの[add]のコメントだけ残して保存します。

以上でコミットの集約は完了です。git logを使用すると、コミットが集約されていることが確認できます。

$ git log --oneline
4a53177 (HEAD -> feature2) [add]繰り返し処理追加
edcec81 [add]条件分岐追加
4b564bd initial commit

今回は2コミットだけを集約しましたが、3つ以上を集約することも可能です。

コミットに対する所感

コミットについて

レビュー後に修正を繰り返した結果、大量にコミットが出来上がることがあります。 少量ならまだ良いですが、1つの対応で大量にコミットがあると、後々差分を確認するのが大変です。
また、コミットを基にリリース対象を選別する場合は、リリース漏れが起こる可能性も高くなります。

逆に、全く関連性のない複数の対応を、1つのコミットにしてしまうのも厄介です。
「この対応は不要になったからRevertしよう」と思っても、複数対応が1コミットに集約されているとRevertは使えません。 そのコミットを細く確認する必要が出てきまし、削除漏れも発生して「使われていないけど、よく分からないメソッドや変数が残っている」という状況が発生し得ます。

集約について

①作業Aを一旦コミット→②全く別の作業Bをコミット→③作業Aの続きをコミット、みたいな対応を行った際に、 作業Aと作業Bで競合が発生しなさそうな場合において、①と③を集約するときによく使っています。
また、好みや慣れの問題ですが、自分は コンソールで並べ替え→TortoiseGitで集約 という流れで行っています。

まとめ

コミットの並べ替えと集約について紹介いたしました。
上でも書いたように、なんでも集約するのもよろしくないですが、適度に意味のある単位でコミットをまとめると、後世の人らがコミットログを確認しやすくなると思います。

コミットの粒度に関しては、個人やプロジェクトで色々な考えがあると思いますが、一つの意見としてご参考にして頂ければと思います。

www.tecotec.co.jp