前回の「Git実践・応用編」では、スタッシュ、リベース、スカッシュマージ、リバートなど、実務で役立つ操作を学びました。本記事では、複数人での開発でよく遭遇するGitのコンフリクトについて解説します。コンフリクトが起きる仕組みから、マーカーの読み方、解消の手順までを図で確認していきましょう。
シリーズの全体像

このGit学習シリーズは、全部で4つの章に分かれています。
- 基礎編:Gitの考え方
- 基本操作編:毎日使う操作
- 実践・応用編:実務で使う操作
- コンフリクト編:競合への対応
第1章ではGitの考え方を、第2章では毎日使う基本操作を、第3章では実務で役立つ操作を学びました。本記事では、最終章となる第4章の「コンフリクト編」として、競合への対応を学びます。
コンフリクトとは

コンフリクトとは、Gitが変更を自動で統合できず、人の判断が必要になっている状態のことです。日本語では「競合」と呼ばれます。
コンフリクトは、エラーや故障ではありません。Gitが「どちらの変更を採用すればよいか判断できないので、決めてください」と、人に判断を求めています。
つまり、コンフリクトは「Gitからの相談ごと」と考えるとイメージしやすくなります。
コンフリクトが起きる原因

コンフリクトが起きる典型的な例は、同じファイルの同じ行を、それぞれのブランチで別の内容に変更したケースです。
図では、main ブランチ側と作業ブランチ側で、greeting.txt の2行目を次のように変更しています。
mainブランチ側:Hello, World- 作業ブランチ側:
Hello, Everyone
同じ2行目に対して、2つの異なる変更が行われています。
マージでコンフリクトが発生する流れ

この2つのブランチをマージすると、Gitは変更を自動で統合しようとします。しかし、同じ行に Hello, World と Hello, Everyone という異なる変更があるため、どちらを採用すべきか判断できません。
そこでGitは、勝手にどちらかを選ばず、コンフリクトという形で人に判断を委ねます。
コンフリクトマーカーの読み方

コンフリクトが起きると、Gitは競合している場所に「コンフリクトマーカー」と呼ばれる目印を書き込みます。
おはよう
<<<<<<< HEAD
Hello, World
=======
Hello, Everyone
>>>>>>> feature
またね
今回のマージでは、<<<<<<< HEAD から ======= までが、いまのブランチ側の内容です。======= から >>>>>>> feature までが、取り込もうとしたブランチ側の内容です。
Gitは両方の内容を並べることで、どちらを残すか判断するように伝えています。コンフリクトマーカーは壊れた表示ではありません。
コンフリクトを解消する4つのステップ

マージで発生したコンフリクトは、次の4つのステップで解消します。
- 残す内容を判断する
どちらの変更を残すかを決めます。必要であれば、両方の変更を組み合わせることもあります。 - ファイルを修正する
判断した内容に合わせてファイルを修正し、コンフリクトマーカーを削除します。 addを実行する
修正したファイルをaddして、このファイルのコンフリクトを解消したことをGitに伝えます。commitを実行するcommitすると、マージが完了します。
第2章で学んだ add と commit は、コンフリクトの解消でも使います。基本操作の延長として流れを覚えておきましょう。
mergeとrebaseで発生するコンフリクトの違い

コンフリクトは、merge のときだけでなく、第3章で学んだ rebase のときにも発生します。
mergeの場合
発生したコンフリクトをまとめて解消し、最後にcommitして統合を完了します。rebaseの場合
コミットを1つずつ積み直すため、その途中でコンフリクトが複数回起きることがあります。コンフリクトを解消してaddしたあと、rebase --continueで処理を続けます。
どちらの場合も、内容を判断し、ファイルを修正して add するまでの基本的な対応は同じです。
コンフリクトは怖くない

コンフリクトを怖がる必要がない理由は、次の3つです。
- Gitが壊れたわけではない
勝手に統合せず、人の判断を待っているGitの正常な動作です。データが消えたわけでもありません。 - どの変更を採用するか決めればよい
コンフリクトはGitからの相談ごとです。内容を確認して、残す変更を決めます。 - 原因と手順を知っていれば対応できる
「判断、修正、add」が、コンフリクトを解消するときの基本の流れです。
最初は戸惑うかもしれませんが、仕組みと手順が分かっていれば落ち着いて対応できます。
まとめ

コンフリクトは、Gitが壊れた状態ではなく、人の判断が必要になっている正常な状態です。エラーや故障ではなく、「どの変更を採用するか決めてください」というGitからの相談ごとです。
対応の流れは、次のとおりです。
- 残す内容を判断する
- ファイルを正しい形に修正する
addで解消したことをGitに伝えるcommitまたはrebase --continueで統合を完了する
コンフリクトが起きたときは、まず競合している内容を確認し、この流れに沿って対応しましょう。


