コンフリクトとは?なぜ起きるのか
コンフリクトの正体を 3-way マージの仕組みから解説し、発生パターンと減らすコツを学ぶ
コンフリクトとは一言で言うと
コンフリクト(競合)とは、Git が 2 つの変更を自動で統合できなかった状態 のことです。
Git はふだん、変更を行単位で賢く混ぜ合わせてくれます。
しかし「同じ行を双方が別々に書き換えた」ような場合は、どちらを残すべきか人間の判断が必要になります。
このとき Git は作業を一時停止し、該当箇所にマーカーを挿入してユーザーに判断を委ねます。
これがコンフリクトの正体です。
重要なのは、コンフリクトは エラーでも障害でもない という点です。
Git が「ここは自動で決められませんでした」と正直に報告しているだけで、ファイルが壊れているわけでも履歴が失われるわけでもありません。
落ち着いて解消すれば元通り作業を続けられます。
仕組み: 3-way マージで自動統合を試みている
Git は 2 つのブランチを統合するとき、共通祖先(merge base / マージベース) と 自分(HEAD) と 相手(取り込み元) の 3 点を比較します。
これを「3-way マージ(3 点マージ)」と呼び、コンフリクト判定の核心部分です。
- 片方だけが変更した行 → 変更した側を採用(自動)
- 双方が同じ内容に変更した行 → そのまま採用(自動)
- 双方が別々の内容に変更した行 → 判断不能 → コンフリクト
つまりコンフリクトは「どちらかが間違っている」のではなく、「両方が正当な変更をしたが、機械的には決められない」という状況を表しているに過ぎません。
共通祖先が存在しないと Git は差分の起点を見失うため、共通祖先の有無はコンフリクト判定の前提条件でもあります。
コンフリクトが起きる代表的なパターン
同じ行を別々に編集した
もっとも典型的なパターン。A さんが
console.log("Hello")をconsole.log("Hi")に、B さんがconsole.log("こんにちは")に変更したようなケースです。隣接する行を編集した
差分の「ハンク(変更ブロック)」の境界が重なると、文字どおり同じ行でなくてもコンフリクトになることがあります。Git は安全側に倒して人間の判断を求めます。
片方が削除・もう片方が編集
A さんがファイルを削除し、B さんが同じファイルを編集していた場合。Git は「削除すべきか残すべきか」を判断できずコンフリクトにします。
ファイルの改名と編集が衝突
A さんがファイル名を変え、B さんが旧名のまま中身を編集したケース。リネーム追跡に失敗するとコンフリクトになります。
バイナリファイル
画像や Excel などは行単位で統合できないため、双方が変更するとほぼ確実にコンフリクトになり、どちらか一方を選ぶしかありません。
どの操作で起きるのか
コンフリクトはマージのときだけに限りません。
次のような「変更の統合」を伴うあらゆる操作で発生する可能性があります。
| 操作 | 状況 |
|---|---|
git merge |
他のブランチを取り込むとき |
git pull |
内部で fetch + merge(または rebase)を行うため |
git rebase |
コミットを別のベースに再適用するとき。1 回の rebase で複数回起きうる |
git cherry-pick |
特定のコミットだけを別ブランチに適用するとき |
git stash pop / apply |
退避した変更を戻す先の状態が変わっていたとき |
git revert |
取り消す対象の変更が、その後の変更と衝突するとき |
どの操作でも、解消の基本は同じ(マーカーを修正 → git add → 操作を完了または続行)です。
ただし rebase は 1 コミットずつ適用するため、他の操作より発生頻度が高く、繰り返し対応する必要があります。
コンフリクトを減らすコツ
こまめに統合する
feature ブランチが長生きするほど main との差分が広がり、コンフリクトが大規模化します。毎日でも親ブランチを feature に取り込む習慣をつけましょう。
PR を小さく保つ
1 PR で触るファイル・行数が少ないほど、衝突する確率は下がります。大きな変更は複数 PR に分割するのが基本です。
担当範囲を分ける
同じファイルを複数人で同時に触らなくて済むよう、役割分担と早めのコミュニケーションを心がけます。
フォーマッタ・整形ツールをチームで統一する
prettier / editorconfig などを全員で揃えておかないと、インデント違いだけで大量のコンフリクトが発生します。
リネームは単独コミットにする
ファイルの移動・改名と中身の編集を同じコミットに混ぜると、Git がリネーム追跡に失敗しやすくなります。
コンフリクトは完全には避けられませんが、日頃の運用で発生頻度と規模は大きく減らせます。
次に読むページ
仕組みと発生パターンを理解したら、次は実際の解消手順を学びましょう。
-
コンフリクトマーカーの読み方、IDE を使った解消、推奨ワークフローまでステップバイステップで解説しています。
-
rebase 特有の「コミット単位で繰り返し発生する」パターンへの対応と、中断・継続・スキップの判断基準を解説しています。
Git Ready