GitHubの「Squash and merge」の使い所とは?

エキサイトの武藤です。

GitHubのプルリクエスト(PR)のマージ機能の一つである Squash and mergeの使い方と注意点について紹介します。

マージの種類

PRのマージには3つの種類があります。

  • Create a merge commit
  • Squash and merge
  • Rebase and merge

デフォルトでは Create a merge commit になっており、マージコミットを作成して、マージします。 マージコミットとは、gitが差分を探す際に基点となるコミットです。

Squash and merge は、PRに含まれるコミットを1つにまとめます。その後、そのコミットをマージ先のbaseブランチへマージします。

Rebase and merge は、PRに含まれるコミットをマージ先ブランチに追加します。このとき、マージコミットは作られず、コミットが個々に追加されます。

基本的には、デフォルトの Create a merge commit を使うことが多いと思います。

Squash and merge のメリット

例えば、featureブランチからdevelopブランチへマージするPRの場合に、個別のコミットをまとめてしまえばコミット履歴がシンプルになります。 中規模以上の開発の場合、全てのコミットが履歴に残るよりも、ある程度まとめてある方が見やすくなります。

下記がSquashをしていないコミット履歴のイメージです。

aaaaaa view の実装 (#15)
bbbbbb ファイル末尾に改行を追加
cccccc タイポ修正
dddddd デザイン修正
eeeeee 処理を共通化
ffffff viewの仮実装
gggggg controller の実装 (#14)
hhhhhh Docs更新
iiiiii controller の追加
jjjjjj repository の実装 (#13)

次に、Squashでまとめた場合の履歴のイメージです。

aaaaaa view の実装 (#15)
gggggg controller の実装 (#14)
jjjjjj repository の実装 (#13)

コミット履歴から大まかな内容を把握したい場合、タイポ修正 のような些細な情報はノイズになり得ます。ある程度の粒度でまとまっていることで、視認性がよくなります。

https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits

Squash and merge の注意点

Squash and merge では、baseブランチにマージコミットを作りません。 これにより、再びheadブランチから新しくPRを作る際に、以前の差分が出てしまいます。

例えば、developブランチからmainブランチへ Squash and merge をしてしまうと、次にdevelopからmasterへPRを作成する際に、以前のPRに含まれた変更も差分となります。

GitHubのドキュメントにもこの内容について書いてあります。

https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges

Squash and merge の使い所

Squash and merge は、先述したようにマージコミットを作りません。 developやmainブランチのような基幹となるブランチは、トピックブランチに最新の変更を反映させることも考えられるため、不整合が起きうる Squash and mergeは避けたほうが良いです。

それを踏まえて、Squash and merge の使い所を考えると、featureブランチから更に細かくブランチを作成し、それを元のfeatureにマージさせるケースだと思います。

例えば、記事のブックマーク機能を開発する場合、下記のブランチ作成を考えます。

  • develop (基幹となるブランチ)
    • feature/develop-bookmark (ブックマーク機能の開発ブランチ)
      • feature/bookmark-ui (UIの実装)
      • feature/bookmark-repository (repository層の実装)

feature/bookmark-uiをfeature/develop-bookmarkにマージするPRでは、Squash and merge が有効です。 最終的にfeature/develop-bookmarkは、コミット履歴がシンプルな状態でdevelopにマージされるイメージです。

headブランチ baseブランチ マージ方法
feature/bookmark-ui feature/develop-bookmark Squash and merge
feature/bookmark-repository feature/develop-bookmark Squash and merge
feature/develop-bookmark develop Create a merge commit

まとめ

GitHubSquash and merge について紹介しました。 コミット履歴をシンプルにできる点は個人的にメリットだと思いますが、使い所に注意が必要です。

コミットをまとめる操作は、git squash コマンドでもできます。 予めローカルで整理した状態でPRを作成するのも一つの手だと思います。

参考になれば幸いです。

参考文献

https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request

karukichi-blog.netlify.app

mmiyauchi.com