Skip to content
blog.kenichikat.me
Go back

GitHubのPRマージ戦略:Squash and merge・Merge commit・Rebase mergeの違い

DependabotのPRを何件かトリアージしてマージしていて、そういえばGitHubのマージボタンには3つの選択肢があるけど、それぞれ何がどう違うのか改めて整理したことがなかったので書いておく。PRブランチ側をrebaseかmergeで最新化する話とは別で、こちらは「PRをmainに取り込むときにどの方式を使うか」の話。

3つのマージ方法

PRブランチに A, B, C という3つのコミットがあり、それを main にマージする場面を考える。

Merge commit

PRブランチの A, B, C をそのまま残しつつ、それらをまとめる「マージコミット」を1つ追加する。

main:    o---o---o---------M
                  \        /
feature:           A---B---C

Squash and merge

PRブランチの A, B, C を1つのコミットにまとめて main に追加する。マージコミットは作られない。

main:    o---o---o---S

Rebase merge

PRブランチの A, B, C を個別のまま main の先端に積み直す。マージコミットは作らない。

main:    o---o---o---A'---B'---C'

比較

Merge commitSquash and mergeRebase merge
mainに残るコミット数PRのコミット数+1(マージコミット)1個PRのコミット数
個々のコミットの意味保たれる失われる(1つに統合)保たれる
mainの履歴の形分岐・合流が残る一直線一直線
PR単位でrevertしやすいかマージコミットをrevertすれば一括で戻せるコミット1個をrevertすれば戻せるコミットが複数残るので個別に戻す必要がある
ブランチ内の雑なコミット(fixupなど)そのまま残る消えるそのまま残る

どう使い分けるか

正解が1つあるわけではなく、GitHubのリポジトリ設定(Settings → Pull Requests)でどの方式を許可するか、通常はチームやプロジェクトの方針として決めておくものだと思う。判断軸としては次のあたりになりそう。

このブログのリポジトリは今のところMerge commit運用にしている。DependabotのPRのようにPR=ほぼ1コミットという場合が多く、Squash and mergeとの差はほとんどないが、「PRがマージされた」という区切りが履歴に残る方が読みやすいと感じたのでこちらにしている。

PRブランチ側の更新方法との関係

ここで整理した「PRをmainに取り込む方法」と、「PRブランチを最新のmainに追従させる方法(rebase / merge)」は別の話だけど、考え方の軸は同じところに行き着く。

rebaseは対象のコミットを書き換える操作なので、「まだ誰にも共有していないコミットは自由にrebaseしてよいが、共有済みのコミットは書き換えない」という原則がある。この原則に沿うなら、

という使い分けになる。実際、Dependabotが作るPRブランチはすでにpush・オープン済みの共有状態なので、これを最新化するときはrebaseではなくmergeを使うようにしている。


Share this post on:

Previous Post
Claude Codeに破壊的なgit操作の前に確認させるhookを作った
Next Post
コンフリクトしたPRの解消方法:rebaseとmergeの比較