はじめに
マージ前に、まず確認。そのひと手間にも闘魂を込めます。
今日の Tips
git merge-tree --write-tree なら、作業ファイルやブランチを変更せずにコンフリクトの有無を確認できます。
最近は worktree でブランチが大量に切られ、作業は生成AIくんたちが進めてくれます。ありがたい話ですが、ふと「これ、ちゃんとマージできるのかな」と気になりました。
コンフリクトが起きないように作業を分けてくれているのでしょうし、仮に起きても調停してくれるので、私が介入する場面はなさそうです。それでも、昔から抱えていた疑問がよみがえりました。積年の宿題、と言えば聞こえはいいのですが、その正体は、思い出した次の瞬間には興味をなくし、調べないまま何年も抱え続けてきた疑問です。
GitHubのプルリクエストには、マージできるかどうかが表示されます。でも、私がコンフリクトを知るのは、いつも実際に git merge したときです。出たとこ勝負です。GitHubは、プルリクエストのたびにmergeを試しているのでしょうか? まあ、そんなわけはないだろうと思って、AIに聞いてみました。
調べてみると、少なくとも2022年の時点では、GitHubは試していたと考えられます。その年のChangelogに、プルリクエストがきれいにマージできるかを確かめるため、テスト用のマージコミットを merge-ort 戦略で作っている、と書かれています。
Merge commits now created using the merge-ort strategy - GitHub Changelog
merge-ort は、add や commit のようなサブコマンドではありません。git merge が内部で使うマージのアルゴリズム(マージ戦略)の名前です。
では、手元で同じように確かめるには、どうすればいいのか。AIに教えてもらったのが git merge-tree です。
これを私だけのものにしておくのは、もったいない。AIくんたちはすでに知っているようですが、私と同じ疑問を感じている人もいるかもしれません。それで、やむにやまれずこの記事を書きました。
コンフリクトの確かめ方
対象のリポジトリで実行します。
git merge-tree --write-tree main feature-branch
echo $?
この例では、main と feature-branch のマージでコンフリクトが発生するかを確認します。ブランチ名は、確認したいものに置き換えてください。
echo $? は、直前のコマンドの終了コードを表示します。git merge-tree の直後に実行してください。
終了コードの読み方
| 終了コード | 意味 |
|---|---|
0 |
コンフリクトなし |
1 |
コンフリクトあり |
| それ以外 | エラー。表示内容を確認する |
echo $? の表示例は次のとおりです。
コンフリクトがない場合:
$ echo $?
0
コンフリクトがある場合:
$ echo $?
1
コンフリクトがなければ、git merge-tree は計算結果のツリーのハッシュを表示します。コンフリクトがある場合は、ツリーのハッシュに加えてコンフリクトの情報も表示します。
mainへの取り込みは行われません
git merge-tree --write-tree はマージ結果を計算しますが、新しいコミットは作成せず、作業ファイルやインデックスも変更しません。ブランチの参照も更新しないため、このコマンドでmainへの取り込みは行われません。
おわりに
マージ前にコンフリクトの有無を確認したいときは、git merge-tree --write-tree と、直後の echo $? を使えます。
0 ならコンフリクトなし、1 ならコンフリクトあり。それ以外はエラーです。
確認してから、次の一手へ。今日も闘魂を込めて進めましょう。

