イントロダクション
プルリクエスト(Pull Request)については当該記事を参照してください。
本記事では、その次にチーム開発で誰もが必ず一度は直面する「マージコンフリクト(merge conflict)」について、初心者にもわかりやすい手順と背景知識を徹底的に解説します。
マージコンフリクトとは、複数の開発ブランチ間でソースコードを統合する際に、Gitが自動的に差分をマージできなくなってしまう状態を指します。
たとえば、同じファイルに別々の機能追加や修正を行ったり、あるブランチでファイルを削除し、別ブランチで同じファイルを編集したりすると、自動統合時に「どちらを優先すべきか」をGitが判断できずにストップしてしまいます。
初心者のうちは「エラーだ!」「Gitが動かない!」と焦りがちですが、実際にはGitがチームの変更を守るためにブレーキをかけてくれている状態です。
コンフリクトを正しく解消できるようになると、コード品質を落とさずにチーム開発をスムーズに進行できるようになります。
本記事では、まずコンフリクト発生のメカニズムと原因を詳しく理解し、その後に具体的な解消手順、GitHub UIでの対処方法、さらには日頃からできる予防策まで、実践的なナレッジを網羅します。
ぜひステップごとに手を動かしながら読み進めてみてください。

1. マージコンフリクトが起きる原因
マージコンフリクトは、Gitの差分(diff)検出アルゴリズムが、自動的にマージを行うための共通基準が見つからないと判断したときに発生します。
以下のような状況で頻繁に起こるため、まずはその典型例を把握しておきましょう。
- 同一行の編集
例:main
ブランチで行42を「ユーザー名を表示」に変更し、feature
ブランチで同じ行を「ユーザーIDを表示」に変更。
Gitは「行単位」でどちらを正とするか判断できないため矛盾とみなし、コンフリクト状態になります。 - ファイルの削除と編集
例:main
ブランチでfile.txt
を削除、一方feature
ブランチではfile.txt
に新たな関数を追加。
Gitは「存在しないはずのファイルをどう扱うべきか」がわからず、マージを停止します。 - 大規模なリファクタリング
例:共通モジュールを複数ファイルに分割・移動した場合、Gitの自動検出ロジックが追いつかず、変更箇所を特定できないことがあります。 - 長期間の並行開発
例:main
ブランチとfeature
ブランチで数百行単位の変更が蓄積してからマージすると、衝突箇所が多数発生しやすくなります。 - バイナリファイルの同時変更
例:画像やドキュメントファイルなどバイナリ形式のファイルを両ブランチで異なるものに置き換えた場合。
Gitは内容比較ができず、必ず手動マージが必要になります。
2. コンフリクト発生の具体例
以下は、simple.txt
というテキストファイルを両ブランチで編集したケースです。
# --- main ブランチ上のファイル (simple.txt) ---
Welcome toテンファイブITスクール!
Let's learn Git together.
# --- feature/login ブランチで編集後 ---
Welcome toテンファイブITスクール!
Let's implement the user login feature.
この状態でマージすると、Gitは次のようにコンフリクトマーカーを挿入します:
<<<<<<< HEAD
Let's learn Git together.
=======
Let's implement the user login feature.
>>>>>>> feature/login
解説:
<<<<<<< HEAD
:現在のブランチ(ここではmain
)上の内容開始マーカー。=======
:改訂前後の境界を示すマーカー。>>>>>>> feature/login
:マージ対象ブランチ(feature/login
)上の内容開始マーカー。
コンフリクト発生時には、これらのマーカーを含む一連の行を手動で編集し、どちらの内容を採用するか、もしくは両方を融合させるかを決定します。
たとえば「両方を融合」したい場合は、以下のように書き換えます:
Welcome toテンファイブITスクール!
Let's learn Git together and implement the user login feature.
最後にマーカーを除去し、ひとつの完成形にまとめることでコンフリクト解決となります。
3. コンフリクト解消の手順
以下のステップに沿って進めれば、確実に解消できます。各コマンドの役割や注意点も併せてご確認ください。
- 最新状態の取得
git fetch # リモートリポジトリの最新情報をローカルに同期 git status # 現在のブランチとリモートの差分を確認
さらに、git pull --rebase
を使うと、マージコミットを作成せずにコミットを先頭に持って来れるため、履歴が直線的になり管理しやすくなります。 - マージまたはリベース実行
- マージの場合:
git merge main # feature ブランチで main をマージ
- リベースの場合:
git rebase main # feature のコミットを main の先頭に移動
- マージの場合:
- 衝突箇所の編集
マーカー(<<<<<<<
~>>>>>>>
)が挿入されたファイルをエディタで開き、以下のいずれかを実施:- どちらか一方だけを残す
- 両方を組み合わせる
- まったく新しい表現に書き換える
- マーカー削除後の検証
git diff # 変更内容を再確認
不要なスペースや改行ミスがないかチェックし、テストスクリプトやビルドを実行して機能に問題がないか検証します。 - ステージングとコミット
git add [file] # または git add . git commit # マージコミットメッセージを記入
リベース中の場合はgit rebase --continue
を使用して手順を続行します。 - リモートへの反映
git push
履歴が書き換わっている場合はgit push --force-with-lease
を使い、他人の変更を上書きしないよう注意して反映します。
4. GitHub UIでのコンフリクト解消
GitHubのWeb UI上でも「Resolve conflicts」機能を使い、ブラウザ上で手軽に解消できます。
プルリクエスト画面に赤い警告バナーが表示されたら「Resolve conflicts」をクリックすると内蔵エディタが立ち上がり、衝突箇所がハイライトされます。コマンドを覚えていなくても直感的に修正可能です。
手順:
- 「Resolve conflicts」ボタンをクリック
- 差分マーカー間のコードを編集
- 「Mark as resolved」をクリック
- 「Commit merge」をクリックして完了
メリット: 環境構築不要ですぐに解消できる。
デメリット: 複雑な衝突(複数ファイル、大規模リファクタ)には向かず、ローカルでの動作検証が行えない点に注意。
5. コンフリクトを防ぐベストプラクティス
コンフリクトを未然に防ぎ、発生しても影響を最小限に抑えるために、以下の開発習慣を取り入れましょう。
- こまめにマージ/リベース
メインブランチの更新を週1~2回程度で取り込み、差分を少量に保つ。 - 小さな単位でプルリクエスト
1PRが200行以上になる場合は機能やバグ修正を分割し、30~50行程度のレビューしやすい粒度で提出。 - チーム内コミュニケーション
Slackなどで「今からfile.txtを編集します」「〇〇機能をリファクタリング中です」と事前共有。 - 明確なブランチ命名規則
feature/〇〇-説明
、bugfix/チケット番号-説明
など、一目で目的がわかる命名を徹底。 - CIによる自動チェック
GitHub ActionsやJenkinsでPR作成時に自動テスト・Lint・ビルドを実行し、マージ前に問題を検出。 - コードオーナー制度の導入
特定ディレクトリやファイルに対してコードオーナーを指定し、PR承認時に必ずレビュー担当者の確認を得る。 - 定期的なリファクタリング日
月1回などスケジュールを決めて技術的負債を解消し、大規模リファクタを計画的に実施。

まとめ
マージコンフリクトは一見怖いエラーのように見えますが、背景にあるのはGitがチームの成果を守ろうとする仕組みです。
コンフリクトの原因を正しく理解し、手順通りに解消できれば、チーム開発はむしろスムーズに、安全に進行します。
「原因把握→ローカル解消→検証→プッシュ」「GitHub UI利用」「こまめなマージ/リベース」などのベストプラクティスを取り入れ、日常的にコンフリクト対処をトレーニングすることで、エンジニアとしての信頼性と開発スピードが飛躍的に向上します。
まずは身近なリポジトリで意図的にコンフリクトを発生させ、解消手順を繰り返して体得しましょう。