git merge-tree は、ワーキングツリーやインデックスを一切変更せずに、マージ結果をシミュレートするコマンドです。
通常、マージコンフリクトを確認するには実際に git merge を実行する必要がありますが、git merge-tree を使えばブランチを切り替えることなく、コンフリクトの有無だけを確認できます。
git merge-tree --write-tree <マージ先ブランチ> <マージ元ブランチ>
--write-treeオプションは Git 2.38(2022年10月)以降で利用可能です。
ツリーオブジェクトのハッシュ値のみが返ってきます。
5ca9e9373f7c1da936d7c58bbc234b813eee1dcf
ハッシュ値の後に、コンフリクトしているファイルの情報が続けて出力されます。
7c73f231e812001c8cf394116df9fa8a9d3c3522
100644 6c44ca8ef44e81a73024125dba83ecb7d5f2d43f 1 src/foo.ts
100644 1da432c6755c4dc5bb78f0f24d9fe900bcfa6513 2 src/foo.ts
100644 bbf0f36345100a420804d1a7e56d8fd87c693315 3 src/foo.ts
CONFLICT (content): Merge conflict in src/foo.ts
ファイルごとに3行出力されます。数字の意味は以下の通りです。
| 数字 | 意味 |
|---|---|
1 | 共通祖先(マージベース)のファイル |
2 | マージ先ブランチのファイル |
3 | マージ元ブランチのファイル |
以下のようなブランチ構成を例に説明します。
master
↑
feature-top
↑
feature-sub
feature-sub を作業しているエンジニアが、最終的に master にマージされるまでの全段階を確認するには、以下のコマンドを実行します。
# まず最新の状態を取得
git fetch origin
# 段階1: 直接の親ブランチとのコンフリクト確認
git merge-tree --write-tree origin/feature-top origin/feature-sub
# 段階2: 最上位ブランチとのコンフリクト確認
git merge-tree --write-tree origin/master origin/feature-sub
各コマンドでハッシュ値のみが返ってきた場合はコンフリクトなし、ファイル情報と CONFLICT の文字が続く場合はコンフリクトありと判断します。
コンフリクトが検出された場合、出力に含まれるハッシュ値を使って差分を確認できます。
100644 aaa... 1 src/foo.ts ← 共通祖先
100644 bbb... 2 src/foo.ts ← マージ先の変更
100644 ccc... 3 src/foo.ts ← マージ元の変更
# マージ先が共通祖先からどう変わったか
git diff aaa... bbb...
# マージ元が共通祖先からどう変わったか
git diff aaa... ccc...
# マージ先 vs マージ元の直接比較
git diff bbb... ccc...
コンフリクトが確認できたら、feature-sub ブランチ上で上位ブランチを取り込んで手動解消します。
# feature-sub ブランチ上で
git fetch origin
git merge origin/feature-top # 直接の親を取り込む
# ← コンフリクトを手動解消してコミット
# 再度確認
git merge-tree --write-tree origin/master origin/feature-sub
解消後に再度 git merge-tree を実行してハッシュ値のみが返ってくれば、コンフリクトなしと確認できます。