マガジン

Gitの競合マーカーの読み方:AIに解決を頼む前に両方の変更を理解する

AIを使いこなす

Claudeで執筆し、GPTで自動校閲・修正しています。

ノートのコード行の一部を鉛筆で二つに分けて囲んだ机上の静物
記事の内容をもとに制作したAI生成イメージです。実際の製品画面や検証結果の写真ではありません。

結論から言うと、<<<<<<< から ======= までが「自分側(今いるブランチ)の内容」、======= から >>>>>>> までが「取り込む相手側の内容」です。ただし標準の表示には「もともとどうだったか」が出ません。そのため、どちらが何を変えたのかが判別しにくくなります。merge.conflictStyle を diff3 にすると、共通の元の内容が ||||||| の下に加わり、双方の変更の意図を読み取りやすくなります。 AIにそのまま「競合を直して」と頼むと、片方の変更が黙って消えることがあります。先にマーカーを読み、両側の意図を一文ずつ言えるようにしてから頼みましょう。この記事では、読み解きの例、diff3への切り替え手順、AIへの依頼文、確認表を示します。

この記事の目次
  1. マーカーの3つの区切りが示すもの
  2. 読み解きの例(説明用の例)
  3. diff3形式で共通の元を表示する
  4. AIに頼む前の依頼文
  5. 人が確認する判断表

マーカーの3つの区切りが示すもの

Gitの公式ドキュメント(git merge)では、<<<<<<< と >>>>>>> が競合する変更箇所を囲み、======= が両側を区切ると説明されています。

  • <<<<<<<、意味:競合部分の始まり。直後から現在の版(マージなら通常は HEAD)の内容
  • =======、意味:現在の版と取り込む側の区切り
  • >>>>>>>、意味:競合部分の終わり。直前までが取り込む側の内容

<<<<<<< や >>>>>>> の後ろにはラベルが付きます。公式の例では yours:sample.txt や theirs:sample.txt と書かれており、実際の画面では場面によって異なる名前が表示されます。ラベルは「どちらの側か」を見分ける手がかりです。なお、この説明でいう「自分側」「相手側」は通常のマージにおける呼び方です。

注意したいのはリベースです。git checkout のドキュメントによると、git rebase や git pull --rebase の最中は --ours と --theirs の指す側が入れ替わって見えます。--ours は「リベース先」の版、--theirs は「リベースされる側(自分が書いた変更)」の版です。この説明は --ours と --theirs の指定についてで、競合マーカーの並びそのものを説明するものではありません。マージのつもりで「自分側」を決め打ちせず、実行中の操作を確認してから読んでください。

読み解きの例(説明用の例)

次は、説明のために作った架空のコードです。実際のリポジトリで実行した結果ではありません。まず標準表示のままだとこう見えます。

text
<<<<<<< HEAD
const TAX_RATE = 0.10;
function price(base) {
  return Math.round(base * (1 + TAX_RATE));
}
=======
function price(base, coupon = 0) {
  return base * 1.08 - coupon;
}
>>>>>>> feature/coupon

自分側は税率を定数にして四捨五入を入れたようです。相手側はクーポン引数を足したようです。ただし、「元は何だったのか」が分からないので、税率が 1.08 から 0.10 に変わったのか、相手側が別の値に変えたのかを断定できません。

diff3形式で共通の元を表示する

diff3 にすると、同じ競合が次のように表示されます(これも説明用の例です)。

text
<<<<<<< HEAD
const TAX_RATE = 0.10;
function price(base) {
  return Math.round(base * (1 + TAX_RATE));
}
||||||| 3f2a1bc
function price(base) {
  return base * 1.08;
}
=======
function price(base, coupon = 0) {
  return base * 1.08 - coupon;
}
>>>>>>> feature/coupon

公式ドキュメントでは、||||||| の区間が共通の祖先(base)の版だと説明されています。ここを軸に、元と自分側、元と相手側を別々に比べます。

  • 元 → 自分側:税率を 1.08 から 0.10 ベースの定数に変更し、四捨五入を追加
  • 元 → 相手側:coupon 引数を追加し、金額から引く。税率は元のまま

2つの変更は目的が別なので、両方を残せそうです。ただし「四捨五入はクーポンを引く前か後か」はコードからは決まりません。仕様を知っている人が決める点です。たとえば次のような案になります。

js
const TAX_RATE = 0.10;
function price(base, coupon = 0) {
  return Math.round(base * (1 + TAX_RATE)) - coupon;
}

これは例の一案で、四捨五入をクーポン適用前にするかどうかは仕様次第です。

切り替え手順

  1. 設定を変更します。すべてのリポジトリに適用する場合は次のコマンドです。
bash
   git config --global merge.conflictStyle diff3

git config のドキュメントでは、値は merge(既定)、diff3、zdiff3 が使えるとされています。特定のリポジトリだけなら --global を外して、そのリポジトリ内で実行します。

  1. すでに競合が出ている場合は、そのファイルの印を作り直します。git checkout のドキュメントでは、パスを指定した --merge(-m)でインデックスから競合状態を再作成でき、--conflict=<style> で形式を指定できます。
bash
   git checkout --merge --conflict=diff3 -- path/to/file.js

このコマンドは対象ファイルをインデックスに記録された競合状態から再作成するため、未保存の手動編集は失われることがあります。手で直した内容を残したい場合は、実行前に別の場所へ控えてください。

  1. zdiff3 は、公式ドキュメントによると diff3 に似ていて、競合部分の先頭や末尾にある共通の行を外して簡潔にする形式です。表示が長くて読みにくいときの選択肢ですが、まずは元の内容がそのまま出る diff3 で慣れるほうが読み違えにくいはずです。

AIに頼む前の依頼文

AIに最初から解決を求めず、「読み解き」と「解決案」を分けます。次の依頼文は、そのままコピーして使えます。ファイルに機密情報(キー、顧客データなど)が含まれる場合は、ダミーに置き換えてから貼ってください。

text
次はdiff3形式のGit競合マーカーです。まだ解決はしないでください。
1. 「|||||||」より上を自分側、「|||||||」から「=======」までを共通の元、
   「=======」から「>>>>>>>」までを相手側として扱ってください。
2. 元→自分側、元→相手側の変更をそれぞれ1〜2文で説明してください。
3. 2つの変更が衝突している点と、コードだけでは決められない仕様上の疑問を挙げてください。

(ここに競合部分を貼る)

回答に納得したら、次の依頼で解決案を出させます。

text
上の理解をもとに、両方の変更意図を残す解決案を出してください。
消えてしまう変更があれば、その内容を明記してください。
マーカー行(<<<<<<< など)は含めないでください。

人が確認する判断表

AIの解決案を受け取ったら、次の表で確認します。

  • 自分側の変更が残っているか、見る場所:元→自分側の説明と解決案、問題があるときの対応:消えた行をAIに指摘し、再提案させる
  • 相手側の変更が残っているか、見る場所:元→相手側の説明と解決案、問題があるときの対応:同上
  • マーカーの行が残っていないか、見る場所:ファイル内で <<<<<<<、=======、>>>>>>> を検索、問題があるときの対応:該当行を削除する
  • 仕様上の選択が勝手に決まっていないか、見る場所:AIが挙げた疑問点、問題があるときの対応:人が決めて、決めた内容を伝え直す
  • 動作するか、見る場所:テストや実行、問題があるときの対応:失敗したらエラー出力を添えて相談する

確認後は、公式ドキュメントにあるとおり、解決したファイルを git add し、git commit または git merge --continue で完了します。収拾がつかなくなったら、マージ中であれば git merge --abort でマージ前の状態に戻せます。ただし、マージ開始時に未コミットの変更があった場合は元に戻せないことがある、と公式ドキュメントにも書かれています。マージ前に作業をコミットしておくと安全です。

出典・参考資料