自由気ままに書いちゃおう

好きなことをつらつらと・・・

【Github】プルリクエストのマージ戦略(merge commit/squash/rebase)について

GitHubでのプルリクエストをマージする際のマージ戦略について纏めた記事です。

マージ戦略の種類

  1. Merge Commit(マージコミット):

    • これは最も一般的なマージ方法で、プルリクエストの全てのコミットをメインブランチにマージします。
    • このプロセスはマージコミットを生成し、プルリクエストのコミット履歴がそのままメインブランチに追加されます。
  2. Squash and Merge(スカッシュマージ):

    • この方法では、プルリクエスト内の全てのコミットが1つのコミットに統合されてからメインブランチにマージされます。
    • これにより、履歴が綺麗に保たれ、不要な中間コミットが除去されますが、個々のコミットの詳細は失われます。
  3. Rebase and Merge(リベースマージ):

    • この方法では、プルリクエストのコミットがメインブランチの最新コミットの上に再配置(リベース)されてからマージされます。
    • これにより、リニアなコミット履歴が保たれますが、リベースの過程でコンフリクトが発生する可能性があります。

まとめ

先にまとめです。

Squash MergeMerge Commit、およびRebase and Mergeの違いです。

特徴 / マージ戦略 Squash Merge Merge Commit Rebase and Merge
コミット履歴 1つのコミットに統合されます。 全てのコミットが履歴に含まれます。 フィーチャーブランチのコミットがリベースされます。
マージコミット 生成されません。 マージコミットが生成されます。 生成されません。
履歴の線形性 線形。 非線形(ブランチの分岐と統合が可視化されます)。 線形。
適用シナリオ 多くの小さなコミットを1つにまとめたい時。 ブランチの完全な履歴を保持したい時。 リニアな履歴を保ちたい時。
履歴の保持 個々のコミットの詳細は失われる。 ブランチの全てのコミットの詳細が保持される。 元のコミット順序は保持されるが、タイムスタンプが変更されることがある。
主な用途 プロジェクト履歴をシンプルに保ちたい時。 ブランチの分岐と統合の履歴を残したい時。 プロジェクト履歴をリニアに保ちたい時。

以降、各マージ戦略の詳細です。

Merge Commit(マージコミット)

基本概念: - メインブランチ(例えばmain)とフィーチャーブランチ(例えばfeature)の間で、新しい「マージコミット」を作成します。 - このマージコミットは両方のブランチの履歴を保持しています。

具体例: - あるプロジェクトで、mainブランチからfeatureブランチが分岐しました。 - featureブランチで3つのコミット(C1, C2, C3)が作成されました。 - 同時に、mainブランチでも新しいコミット(C4)が作成されました。 - featureブランチをmainにマージするとき、新しいマージコミット(M)が生成され、mainにはC1, C2, C3, C4, そしてMが含まれます。

結果の履歴:

main:      A -- B -- C4 -- M
                   \       /
feature:    C1 -- C2 -- C3
  • ここで、AとBは元々mainにあったコミットです。
  • Mはマージコミットで、featureブランチの変更をmainに統合します。

Rebase and Merge(リベースマージ)

基本概念: - フィーチャーブランチのコミットを、メインブランチの最新コミットの上に「再配置」(リベース)します。 - これにより、リニアな履歴が作成され、マージコミットは生成されません。

具体例: - 同じシナリオを考えます:mainからfeatureが分岐し、featureにはC1, C2, C3、mainにはC4のコミットがあります。 - リベースすると、C1, C2, C3はC4の後に配置されます。 - その後、featureブランチの変更がmainにマージされます。

結果の履歴:

main:      A -- B -- C4 -- C1' -- C2' -- C3'
  • C1', C2', C3'はリベースされたC1, C2, C3のコミットです。
  • リベースにより、featureブランチのコミットは、mainブランチの最新コミットの後に直接追加されます。

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

基本概念: - フィーチャーブランチ上の全てのコミットが1つのコミットに統合されます。 - この単一のコミットがメインブランチにマージされます。 - 元のフィーチャーブランチの個々のコミットの履歴は失われますが、その内容は保持されます。

具体例: - mainブランチからfeatureブランチが分岐し、featureブランチには3つのコミット(C1, C2, C3)があります。 - 同時に、mainブランチには新しいコミット(C4)が作成されています。 - featureブランチをスカッシュマージすると、C1, C2, C3が1つの新しいコミット(S)に統合され、その後mainにマージされます。

結果の履歴:

main:      A -- B -- C4 -- S
  • ここで、AとBは元々mainにあったコミットです。
  • Sはスカッシュされた新しいコミットで、featureブランチの変更(C1, C2, C3)がすべて含まれています。
  • mainブランチの履歴はリニアに保たれ、featureブランチの個別のコミットはmainの履歴には現れません。

結論

  • Merge Commitはマージコミットを生成し、ブランチの分岐と統合の履歴が残ります。
  • Rebase and Mergeはリニアな履歴を作成し、分岐したブランチのコミットをメインブランチのコミットの後に直接配置します。これにより、履歴が綺麗になりますが、元のコミットのタイムスタンプや順序が変わることがあります。
  • Squash and Mergeでは、フィーチャーブランチの全ての変更が1つのコミットに統合され、メインブランチの履歴が綺麗に保たれます。

以上です。