DevToolBox

gitマージコンフリクトの解消手順

git pullgit merge の直後にCONFLICT (content): Merge conflict in src/app.js と表示されて作業が止まる—— チーム開発で最も身近なトラブルです。コンフリクトは「壊れた」状態ではなく、gitが判断を保留して人間に委ねている状態です。本記事ではマーカーの読み方、 merge と rebase で ours/theirs の意味が逆転する罠、実践的な解消フローを整理します。

A merge conflict is not a broken state — Git is simply asking you to decide. This guide covers how to read conflict markers, the ours/theirs reversal trap during rebase, one-side resolution with checkout --ours/--theirs, and how to safely abort and retry.

TL;DR

Diff Checker

コンフリクト解消前に「自分の変更」と「相手の変更」を並べて差分確認。どちらに何が含まれるかを把握してから解消すると事故が減ります。ブラウザ完結・外部送信なし。

今すぐ試す →

1. コンフリクトマーカーの読み方 / Reading conflict markers

コンフリクトが起きたファイルには、gitが両方の版を並べて書き込みます。

function greet() {
<<<<<<< HEAD
  return "こんにちは";        // ← 現在のブランチ(自分)の内容
=======
  return "Hello, world";      // ← 取り込む側(相手)の内容
>>>>>>> feature/english
}

解消とは「このブロックを最終的に残したい形に書き換え、マーカー3行 (<<<<<<< / ======= / >>>>>>>)を削除する」ことです。 どちらか一方を選ぶ必要はなく、両方を組み合わせた第三の形にしても構いません。

現在の状況確認には git status が最も確実です。both modified: と表示されているファイルが未解消のコンフリクトです。

$ git status
Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   src/app.js

Edit the block to the final content you want, delete all three marker lines, thengit add the file. git statuslists unresolved files as "both modified".

2. merge と rebase で ours/theirs が逆転する罠 / The ours-theirs reversal

ファイル単位で「全部こっち側を採用」したいときは git checkout --ours /--theirs が便利ですが、merge と rebase で意味が逆転することを知らないと、自分の変更を全部捨てる事故につながります。

操作ourstheirs
git merge feature(main 上で実行)main(自分の現在地)feature(取り込む側)
git rebase main(feature 上で実行)main(適用先)feature(自分のコミット)

rebase は「main の上に自分のコミットを1つずつ再適用する」操作なので、再適用中の HEAD は main 側にあります。そのため --ours = main、--theirs = 自分、と直感の逆になります。rebase 中に「自分の変更を残したい」なら --theirs です。

# ファイル単位で一括採用(merge 中)
git checkout --ours   package-lock.json   # 自分の版を採用
git checkout --theirs package-lock.json   # 相手の版を採用
git add package-lock.json

# rebase 中は意味が逆! 自分の変更を残す場合:
git checkout --theirs src/app.js
git add src/app.js
git rebase --continue

During rebase, HEAD sits on the branch you are rebasing onto, so ours = the base branch and theirs = your own commits. To keep your changes while rebasing, use --theirs.

3. 実践フロー: 発生から解消まで / Step-by-step resolution flow

# 1. 状況確認 — どのファイルが衝突したか
git status

# 2. 各ファイルを開き、マーカーを探して編集
#    (エディタのコンフリクト表示や git grep でも探せる)
git grep -nE '^(<{7}|={7}|>{7})'

# 3. 解消できたファイルをステージ
git add src/app.js

# 4. 全部解消したらコミット(merge ならメッセージは自動生成)
git commit

# rebase の場合は commit ではなく:
git rebase --continue

解消後のコミット前に必ずビルドとテストを実行してください。 マーカーを消しても「自分は関数名を変更、相手はその関数の呼び出しを追加」のような論理的な衝突はgitには検出できません(テキストとしては衝突しないことすらあります)。

やり直したいとき

git merge --abort    # merge を取り消して開始前に戻る
git rebase --abort   # rebase を取り消して開始前に戻る
git checkout --merge src/app.js  # 1ファイルだけマーカー付きの状態に戻す

Resolve, git add each file, then git commit (or git rebase --continue). Always build and test before committing — Git cannot detect logical conflicts. Use --abort to start over safely.

4. コンフリクトを減らす運用 / Preventing conflicts

まとめ

コンフリクトは「gitが人間に判断を委ねている」だけの正常な状態です。 マーカーの構造(HEAD側 / 取り込み側)を理解し、rebase 時の ours/theirs 逆転にだけ注意すれば、 恐れる必要はありません。迷ったら --abort でやり直せることを覚えておくと、 落ち着いて対処できます。

Conflicts are Git deferring a decision to you, not a failure. Understand the marker layout, watch for the ours/theirs flip in rebase, verify with build and tests, and remember you can always --abort and retry.

Diff Checker

解消結果が意図通りか、解消前後のファイルを貼り付けて最終確認。行単位ハイライトで消し込み漏れを発見できます。

今すぐ試す →

関連ガイド・ツール / Related