GitHub のマージ方法:Merge commit、Squash and merge、Rebase and merge の違い

GitHub のマージ方法:Merge commit、Squash and merge、Rebase and merge の違い

GitHub でプルリクエストをマージする際には下記の通り3つの方法があります。

  1. Merge commit: All commits from this branch wil be added to the base branch via a merge commit.
  2. Squash and merge: The n commits from this branch will be combined into one single commit in the base branch.
  3. Rebase and merge: The n commits from this branch will be rebased and added to the base branch.

では、以下のケースを想定して、それぞれのマージ方法でどのようなコミット履歴になるかを見てみましょう。

  1. ベースブランチ(main ブランチ)で A, B, C のコミットがありました。
  2. C のあとでトピックブランチ(feature ブランチ)を切り出して D, E のコミットをしました。
  3. ベースブランチ(main ブランチ)に PR を出してマージします。

Merge commit(マージコミット) #

マージを実行すると、main ブランチにマージコミット(X)が作成されます。

# マージ実行直前
main   : A---B---C
                  \
feature:           D---E

# マージ実行後
main   : A---B---C---X--->
                    /
               D---E

Squash and merge(スカッシュマージ) #

マージを実行すると、main ブランチに DE をまとめた新しいコミット(X)が作成されます。

# マージ実行直前
main   : A---B---C
                  \
feature:           D---E

# マージ実行後
main   : A---B---C---X--->

Rebase and merge(リベースマージ) #

マージを実行すると、DE が main ブランチの最新のコミットの後ろに追加されます。

# マージ実行直前
main   : A---B---C
                  \
feature:           D---E

# マージ実行後
main   : A---B---C---D'--E'-->

補足

ここで、GitHub でのリベースとマージの動作は、通常の git rebase コマンドの動作とは少し異なっていることには注意が必要です。通常の git rebase では、Fast-forward マージが可能な場合コミット情報(D, E)は変更されませんが、GitHub でのリベースマージでは新しいコミット SHA(D', E')で書き直します。

GitHub でのリベースとマージの動作は、git rebase とは少し異なっています。 GitHub でリベースしてマージすると、常にコミッター情報が更新され、新しいコミット SHA が作成されますが、GitHub 外の git rebase は、先祖コミットの上でリベースが発生した場合、コミッター情報は変更されません。

https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/about-merge-methods-on-github#rebasing-and-merging-your-commits

# マージ実行直前
main   : A---B---C
                  \
feature:           D---E

# 通常の git rebase でのマージ実行後
main   : A---B---C---D---E--->

# GitHub でのリベースマージ実行後
main   : A---B---C---D'--E'-->

参考 #