Git のマージ戦略のオプションとサンプル
作業とテストが完了し、開発のメインラインにマージする準備ができたら、チームで検討すべきことがあります。それは、チームにおけるマージ戦略をどうするかということです。この記事では、さまざまなマージ戦略を探りながら、アトラシアンではどのような戦略を採っているかを紹介します。この記事を読み終わるころには、チームに最適な戦略を見つけることができているでしょう。
Git でのマージの進め方
マージとは、2 つのブランチを結合することです。Git では 2 つ以上のコミットポインターを取って、ポインター間で共通するベースコミットを見つけようとします。Git にはベースコミットを見つけるためのさまざまな手法があり、これらの手法は「マージ戦略」と呼ばれます。共通するベースコミットが見つかったら、指定したマージコミットの変更を結合する新しい「マージコミット」が作成されます。技術的な観点から見ると、マージコミットは単に 2 つの親コミットを持つ通常のマージということになります。
明示的に指定しない限り、git merge
は自動でマージ戦略を選択します。git merge
コマンドと git pull
コマンドには -s
(strategy の「s」) オプションを渡せます。-s
オプションでは使用するマージ戦略の名前を追加できます。明示的に指定しなかった場合は、Git は指定したブランチに最適なマージ戦略を自動的に選択します。使用可能なマージ戦略の一覧は以下のとおりです。
関連資料
高度な Git ログ
ソリューションを見る
Bitbucket Cloud での Git の使用方法についてのチュートリアルです。
Recursive
git merge -s recursive branch1 branch2
このマージ戦略では 2 つの HEAD に対応します。Recursive はデフォルトのマージ戦略で、1 つのブランチのプルまたはマージを実行します。また、名前変更に関するマージの検出と操作ができますが、現時点では検出したコピーを活用する方法はありません。こちらが 1 つのブランチのプルまたはマージを実行する際のデフォルトのマージ戦略になります。
解決
git merge -s resolve branch1 branch2
この戦略では三方向マージアルゴリズムを使った、2 つの HEAD の解決のみを実行できます。十字マージの曖昧さを慎重に検出する戦略で、一般的には安全かつ高速だとみなされています。
Octopus
git merge -s octopus branch1 branch2 branch3 branchN
3 つ以上の HEAD に対応する際のデフォルトのマージ戦略です。複数のブランチが渡されると、自動的に Octopus がマージ戦略として選択されます。手動による解決が必要なマージの競合がある場合、マージは却下されます。基本的には類似するフィーチャーブランチ HEAD を結合するときに使用します。
Ours
git merge -s ours branch1 branch2 branchN
Ours 戦略は、複数の任意の数のブランチに対応しています。この戦略のマージ結果は現在のブランチの HEAD
のものになります。「Ours」という単語は、他のすべてのブランチにおけるすべての変更を実質的に無視することを意味しています。類似するフィーチャー ブランチの履歴を結合する際に使用します。
Subtree
git merge -s subtree branchA branchB
Subtree は Recursive 戦略の拡張版です。A と B をマージしようとしていて、B が A の子サブツリーである場合、まず B が更新されて A のツリー構造が反映されます。この更新は A と B で共有されている共通の祖先ツリーにも行われます。
Git マージ戦略のタイプ
明示的なマージ
明示的なマージはデフォルトのマージタイプです。この場合の「明示的」とは、新しいマージコミットが作成されることを意味します。これによってコミット履歴が変更され、マージが実行された箇所が明示的に示されます。マージコミットのコンテンツも明示的で、どのコミットがマージコミットの親かが表示されます。マージコミットではほぼ間違いなくプロジェクト履歴に「ノイズ」が追加されるため、明示的なマージを使わないチームもあります。
リベースマージまたは早送りマージでトリガーされる暗黙のマージ
コミットをまとめてマージする (通常は明示的なマージで使用しない)
Git マージの Recursive 戦略で使えるオプション
さきほど紹介した「Recursive」戦略には他にも独自の操作オプションのサブセットがあります。
ours
このオプションを Ours マージ戦略と混同しないようにしてください。このオプションでは「Ours」の結果を利用することで競合を自動的かつスムーズに解決します。競合がない場合、「Theirs」側の変更は自動的に組み込まれます。
theirs
「Ours」戦略とは反対に、「Theirs」オプションでは競合の解決時に外部のマージ対象ツリーを対象にします。
patience
このオプションではじっくりと時間をかけて、条件に一致する重要ではない行のマージエラーを回避します。マージ対象のブランチの分岐が激しいときにこのオプションを使います。
diff-algorithim
ignore-*
ignore-space-change
ignore-all-space
ignore-space-at-eol
ignore-cr-at-eol
これらは空白文字を対象とするオプションです。渡されたオプションのサブセットに一致するすべての行が無視されます。
renormalize
このオプションではすべての git ツリーでチェックアウトとチェックインが実行されるとともに、三方向マージを解決します。このオプションは、異なるチェックイン
/チェックアウト
状態のマージ対象ブランチで使用します。
no-normalize
このコマンドを実行すると標準化オプションが無効になり、merge.renormalize
の構成変数が上書きされます。
no-renames
このオプションを指定すると、名前を変更したファイルをマージ中に無視します。
find-renames=n
これはデフォルトの動作です。Recursive マージではファイルの名前変更が尊重されます。n
パラメーターを使って名前変更の類似性のしきい値を渡せます。デフォルトの n
値は 100%
です。
subtree
このオプションは Subtree 戦略から流用したものです。マージ戦略を 2 つのツリーで実行し、同じ祖先に一致させる方法を修正する場合、このオプションではツリーのパスメタデータを操作して祖先に一致させます。
アトラシアンの Git マージポリシー
アトラシアンでは明示的なマージの使用が強く推奨されています。理由はいたってシンプルです。明示的なマージは、マージ対象のフィーチャーのトレーサビリティとコンテンツが非常にわかりやすくなっています。レビュー用にフィーチャーブランチを共有する前にローカル履歴のクリーンアップリベースを行うことを強く推奨しますが、これによってポリシーが変更されるようなことは一切なく、単純にポリシーが強化されます。
この記事を共有する
次のトピック
おすすめコンテンツ
次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。