RebaseとMergeでのコンフリクト解決の違い

git mergeとgit rebaseでのコンフリクトの違いを理解します。リベース中にours/theirsが入れ替わる理由と、連続コンフリクトの処理方法を学びます。

Best Practices

詳細な説明

Rebase vs Merge: コンフリクトの違い

git mergegit rebase中のコンフリクトの違いを理解することは極めて重要です。同じファイルでも使用する操作によって異なるコンフリクトパターンが生じる可能性があるためです。さらに重要なのは、リベース中は「ours」と「theirs」の意味が逆転することです。

git merge中

git checkout main
git merge feature
  • Ours = main(現在いるブランチ)
  • Theirs = feature(マージされるブランチ)
  • マージ全体で1回だけコンフリクトを解決します。

git rebase中

git checkout feature
git rebase main
  • Ours = main(リベース先のブランチ)— これが入れ替わり!
  • Theirs = feature(リプレイされる自分のコミット)
  • コンフリクトを複数回解決する必要がある場合があります — リプレイされるコミットごとに1回。

入れ替わりが起きる理由

リベース中、Gitは各コミットをターゲットブランチの上にリプレイします。各リプレイにおいて、ターゲットブランチを「現在の」状態(ours)として、自分のコミットを取り込み変更(theirs)として扱います。これはほとんどの開発者が直感的に期待するものと正反対です。

リベースの連続コンフリクト

ブランチに5つのコミットがあり、そのうち3つがコンフリクトする場合、リベース中に3回別々にコンフリクトを解決します。各解決後、git rebase --continueを実行して次のコミットに進みます。

実践的な考慮事項

シナリオ 推奨アプローチ
短期間のfeatureブランチ、コミット少数 クリーンな履歴のためにmainにリベース
長期間のブランチ、多くのコンフリクトが予想される 繰り返しの解決を避けるためにマージ
複数の貢献者がいる共有ブランチ マージ(共有ブランチを絶対にリベースしない)
PRレビュー前のクリーンアップ インタラクティブリベース、その後マージ

中止とリトライ

リベース中に混乱した場合、いつでもgit rebase --abortで元の状態に戻してやり直すことができます。マージ中はgit merge --abortを使用してください。

ユースケース

10コミットのfeatureブランチを更新されたmainブランチにリベースしていて、複数のコミットでコンフリクトに遭遇します。ours/theirsの入れ替わりを理解することで、各コンフリクトを正しく解決できます。

試してみる — Git Conflict Resolver

フルツールを開く