マージコミット入りのPull Requestで困ったら: git merge --squashでコミットをまとめよう
はじめに
Pull Request(以下、PR)をレビューしてもらう前にコミットを整理しておくことは、レビュワーの負担を減らす上で非常に重要です。一般的に、コミットをまとめる方法としてよく紹介されているのが git rebase -i HEAD~{N}
を使う方法です[1]。この方法は、1つのコマンドで簡単にコミットをまとめられるため、ベストプラクティスとして広く知られています。
ただし、この方法は途中にマージコミットが含まれている場合、扱いが一気に難しくなります。PRのレビューを依頼する前に git rebase -i
を使ってコミットをまとめようとした結果、base branch の変更まで一緒にまとめられてしまい、PR上から見えるファイルの差分が本来よりも大きくなってしまった、という経験がある方もいるのではないでしょうか。
そこで今回は、私が普段からよく使っている git merge --squash
を使ったコミットのまとめ方をご紹介します。Gitに慣れたエンジニアにとっては当たり前のテクニックかもしれませんが、ネット上であまり紹介されていないため、誰かの助けになるのではと思って記事にすることにしました。
手順
たとえば、以下のようなPull Requestがあるとします。レビューを依頼する前に、このPRの複数のコミットを1つにまとめたいと考えます。
このとき、コミットツリーは以下のようになっています。途中でマージコミットが入っているのが特徴です。
このような場合に、きれいにコミットをまとめる手順を以下に示します。前準備として、ローカルのブランチをリモートと同じ状態にしておきます。
- まず、ローカルで
main
から新たに適当なブランチ(ここではchore/sqhash-commit
とする)を切ります。
git checkout main
git checkout -b chore/sqhash-commit
- 次に、
chore/squash-commit
ブランチ上で、feature1
ブランチをsquash merge
します。これにより、feature1
の変更内容がすべてステージされた状態になりますので、それをコミットします。
git merge --squash feature1
git commit -m "feature1"
- 最後に、作成した1つのコミットを、元の
feature1
ブランチにforce pushします。
git push -f origin HEAD:feature1
これにより、PRのコミットを1つにまとめることができました。PRの差分(Files changed)は元のPRと変わりません。
補足
- もちろん、途中にマージコミットが入っていない場合でも、今回紹介した方法でコミットをまとめることができます。
- 今回は、すべてのコミットを1つにまとめる例を紹介しましたが、
git reset --hard {commit_hash}
などと組み合わせることで、任意の連続したコミットだけをまとめることも可能です。
最後に
基本的には、git rebase -i HEAD~{N}
をこまめに使って整理していくのが王道です。ただし、途中にマージコミットが入ってしまった場合でも、今回紹介した git merge --squash
を使えば、安全にコミットまとめることができます。
Discussion