Git のコンフリクト(競合)は、マージなどで、同じ場所に別々の変更があり、Git がどちらを残すか決められないときに起きます。Git はそこで止まり、ぶつかった所に印(マーカー)を書き込みます。あとは、人が残す中身を決めて直し、git add で「解いた」と伝えて続けるか、--abort でやめて、始める前の状態に戻すかのどちらかです(戻らないものもあります。あとで説明します)。
ただし、同じ印でも、merge・rebase・cherry-pick・stash pop・pull で、起き方・やめ方・「どちらが自分の側か」が違います。とくに印の上半分は、いつも自分の側とは限りません。この記事は、初心者の方に向けて、公式の文書に沿って、その違いと、GitHub の画面で解く方法をまとめたものです。
コマンドの出力は git 2.39.3(Apple Git-145・macOS)のものです(2026年10月時点の最新は 2.56.0 です)。Git の表示は英語で出ます。ハッシュ(コミットの名前になる英数字)は例で、読者の手元では違う値になります。
- コンフリクトとは何か、どんなときに起きるか(merge 以外でも起きる)
- ぶつかったファイルの見つけ方と、マーカーの読み方(
HEADがどちらの側か) - merge でのコンフリクトの解消の手順と、マーカーを消し忘れたときの確かめ方
--abortでやめて元に戻す方法と、戻らないもの- 片方の側を丸ごと選ぶ
--ours・--theirsと、rebase で向きが逆になること - GitHub の画面で解く手順と、解けないとき
コンフリクトとは?どんなときに起きる?
Git は、ブランチ(作業の枝分かれ)どうしの違いを、たいてい自動でマージ(合流)できます。ふつうは変更が別の行や別のファイルにあるので、多くの場合は人の手は要りません(GitHub の文書)。ただし、手元の git 2.39.3 では、隣り合った行を変えただけでもコンフリクトになりました。人の手が要るのは、競合する変更があるときです。GitHub の文書は、コンフリクトがよく起きる場面として、次の2つを挙げています。
- 同じファイルの同じ行を、別々の人(別々のブランチ)が変えたとき
- 一方がファイルを書き換え、もう一方が同じファイルを消したとき
共通の元から、片方だけが変えた所は、そのまま結果に入ります。止まるのは、両方が同じ所を変えたときです。Git はどちらかを勝手に選べないので、人に解いてもらいます。コンフリクトを解くとは、マージのあとに残す最終の中身を決めることです。
コンフリクトは、merge だけでなく、rebase・cherry-pick・revert・stash pop(apply)でも起きます。
- merge: 別のブランチの変更を、いまのブランチに合流させる。違いは Git MergeとRebaseの違いの記事でも説明しています
- rebase: 自分のコミットを、別のブランチの先に載せ直す
- cherry-pick: 指定したコミットの変更だけを、いまのブランチに当てる
- stash pop: しまっておいた変更(stash)を戻す。git stash の使い方の記事で説明しています
git pull は、リモートの変更を取ってくる(fetch)あとで、merge か rebase を動かします。なので、pull のコンフリクトは、merge か rebase のコンフリクトです。
GitHub のプルリクエスト(変更を取り込んでもらう依頼)では、コンフリクトを全部解くまでマージできません。コンフリクトがある間は、Merge pull request のボタンが押せなくなります。コマンドで merge したときも、解いてコミットするまで、マージの結果は push できません。プルリクエストの基本はプルリクエストとは?の記事にあります。
コンフリクトが起きたら?ぶつかったファイルとマーカーの読み方
起きたときの表示
例として、a.txt(3行)があり、feature ブランチと main ブランチで、2行目を別々に変えてコミットした場面を使います。main にいる状態で、git merge feature を流しました(git 2.39.3 の出力)。
$ git log --oneline --graph --all
* e18383c feature: change line2
| * 2f798fd main: change line2
|/
* 3652f75 first
$ git merge feature
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.
「CONFLICT」の行が、どのファイルでぶつかったかを教えてくれます。終了コードは 1 で、マージのコミットはまだ作られていません。Pro Git(英語)は、Git がマージのコミットを自動では作らず、コンフリクトを解く間、処理を止めている、と説明しています。
止まっている間の状態は、git-merge の文書によると、次のとおりです。
HEAD(いま作業しているブランチを指す名前。ふつうはそのブランチの最新のコミットを指す。rebase の途中などは、ブランチではなくコミットを直接指す。detached HEAD と呼ぶ)は動かないMERGE_HEADが、取り込もうとした相手のブランチの先を指す- ぶつからなかったファイルは、もうインデックス(
git addした状態を置く場所)と作業ツリー(手元のファイル)に入っている - マージの前の、いまのブランチの先は
ORIG_HEADに入る
どのファイルがぶつかったか(git status)
git status で、ぶつかったファイルが分かります。「Unmerged paths:」(まだマージできていないファイル)の下に「both modified:」と出ます。git 2.39.3 の status は、やめ方(git merge --abort)と、解いたあとの印の付け方(git add <file>...)も案内してくれます。
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
短い表示の git status --short では、ぶつかったファイルに2文字の印が付きます。この例では UU a.txt(両方が変えた)です。公式の文書にある印は、次の7つです。
| 印 | 意味 |
|---|---|
UU | 両方が変えた |
AA | 両方が足した |
DD | 両方が消した |
AU | 自分の側が足した |
UA | 相手の側が足した |
DU | 自分の側が消した |
UD | 相手の側が消した |
ぶつかったファイルは、インデックスに最大3つの版が入ります。1番が共通の元、2番が HEAD(自分)、3番が MERGE_HEAD(相手)です。git ls-files -u で一覧でき、git show :1:a.txt(元)・git show :2:a.txt(HEAD)・git show :3:a.txt(MERGE_HEAD)で、それぞれの中身を出せます。
$ git ls-files -u
100644 83db48f84ec878fbfb30b46d16630e944e34f205 1 a.txt
100644 b0db2f82cef62b2e887c2bb1df77bf8d389d1de7 2 a.txt
100644 a31402d24bb009cbe8402609ef57a471a5736d82 3 a.txt
$ git show :2:a.txt
line1
main line2
line3
マーカーの読み方:HEAD はどちらの側?
ぶつかったファイルを開くと、ぶつかった所が <<<<<<<・=======・>>>>>>> の3つの印(マーカー)で囲まれています。
line1
<<<<<<< HEAD
main line2
=======
feature line2
>>>>>>> feature
line3
git-merge の文書では、======= より上がふつうは自分の側、下が相手の側です。merge のときは、<<<<<<< HEAD から ======= までが、HEAD、つまり merge を実行したときにいたブランチ(この例では main)の中身です。======= から >>>>>>> feature までが、取り込もうとしたブランチ(feature)の中身です。
注意: 「上半分がいつも自分の側」ではありません。rebase と git pull --rebase では、<<<<<<< HEAD の側は、自分のブランチではなく、上に載せる先(たとえば main)です。>>>>>>> の側が、載せ直している自分のコミットです。merge と上下の意味が逆に見えるので、あとの「rebase でコンフリクトしたら」で説明します。
>>>>>>> のうしろの名前も、場面で変わります(git 2.39.3 の出力)。
| 場面 | 上の印のうしろ | 下の印のうしろ |
|---|---|---|
| merge | HEAD | ブランチの名前(例 feature) |
| pull(merge) | HEAD | コミットの40桁の名前 |
| rebase・cherry-pick | HEAD | 当てようとしたコミット(例 e18383c (feature: change line2)) |
| stash pop | Updated upstream | Stashed changes |
git restore --merge で作り直したとき | ours | theirs |
元の中身も出したいとき(diff3・zdiff3)
既定の書き方は、ぶつかった所の「元の中身」を出しません。設定の merge.conflictStyle を diff3 か zdiff3 にすると、||||||| の印のあとに元の中身も出ます。元を見ると、よい解き方が分かることがあります、と git-merge の文書は書いています。手元では、そのリポジトリだけに設定して流しました(git 2.39.3 の出力)。
$ git config merge.conflictStyle diff3
$ git merge feature
(省略)
$ cat a.txt
line1
<<<<<<< HEAD
main line2
||||||| 3652f75
line2
=======
feature line2
>>>>>>> feature
line3
||||||| の下の line2 が、共通の元の中身です。zdiff3 は diff3 に近く、ぶつかった所の頭と終わりで、両方が同じになっている行を、囲みの外に出します(2.35 で入りました)。この例では頭と終わりに同じ行が無いので、diff3 と同じ表示になりました。Pro Git の例は git config --global merge.conflictstyle diff3 で、--global を付けると、すべてのリポジトリに効きます。
コンフリクトを解くには?(merge の手順)
コンフリクトを見たら、できることは2つです。マージをやめる(git merge --abort。あとの節で説明します)か、解くかです。解くときは、ファイルを直して git add し、git commit か git merge --continue で終えます。--continue は、途中のマージがあるかを確かめてから git commit を呼ぶ、と git-merge の文書にあります。
手順
git statusで、ぶつかったファイルを確かめる- エディタでファイルを開き、
<<<<<<<を探して直す - 直したファイルを
git addする git commitかgit merge --continueで、マージを終える
直し方は3通りです。自分の側だけ残す、相手の側だけ残す、両方を合わせた新しい中身にする。どれでも、マーカーの3行(<<<<<<<・=======・>>>>>>>)は消します。ここでは、両方を合わせて、2行目を main and feature line2 にしました。
line1
main and feature line2
line3
直したファイルを git add すると、「解いた」印になります。全部 add すると、status は「All conflicts fixed but you are still merging.」と出ます。まだマージの途中で、コミットが残っているという意味です(git 2.39.3 の出力)。
$ git add a.txt
$ git status
On branch main
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: a.txt
$ git merge --continue
[main 0bf5a29] Merge branch 'feature'
$ git log --oneline --graph
* 0bf5a29 Merge branch 'feature'
|\
| * e18383c feature: change line2
* | 2f798fd main: change line2
|/
* 3652f75 first
マージのコミットのメッセージは、何も書かなければ「Merge branch 'feature'」になりました(手元で、エディタを開かない設定で流したときの結果です)。
まだ add していないファイルがあるうちは、git commit も git merge --continue も止まります(終了コード 128)。
$ git commit -m "try"
error: Committing is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
U a.txt
GitHub の文書の手順は、直したあとに git add . と git commit -m "…" です。ただし、git add . のようにフォルダを渡すと、そのフォルダの中の変更(関係ないファイルの書き換えや、新しいファイルも)を全部 add します。この記事の例は、git add a.txt のように、ファイルを名指しにして流しました。
マーカーを消し忘れていないか確かめるには?
注意: マーカーを消し忘れたままでも、手元の git 2.39.3 では、git add も git commit も止まりませんでした。マーカー入りのファイルが、そのままコミットされます。
消し忘れは git diff --check で見つかります。「leftover conflict marker」(消し忘れたマーカー)と知らせてくれます。add の前は git diff --check、add のあとは git diff --cached --check です。見つけると終了コードは 2 になります(git 2.39.3 の出力)。
$ git diff --check
a.txt:2: leftover conflict marker
a.txt:4: leftover conflict marker
a.txt:6: leftover conflict marker
$ git add a.txt
$ git diff --cached --check
a.txt:2: leftover conflict marker
a.txt:4: leftover conflict marker
a.txt:6: leftover conflict marker
新しい版には、消し忘れたファイルを add しないオプションがあります。Git 2.56.0(2026年9月28日公開)の文書によると、git add --resolved は、ぶつかっていたファイルのうち、マーカーが残っていないものだけを「解いた」として add します。マーカーが1つでも残っているファイルがあると、どのファイルも add しません。関係ないローカルの変更は add しません。手元の 2.39.3 にはこのオプションが無いので、流しておらず、止まったときの表示は確かめていません。
解くときに使える道具
git-merge の文書にある道具です。
git diff:HEADとMERGE_HEADの両方からの変更を、3方向で出すgit diff AUTO_MERGE: ここまでに自分が直した分を出す。AUTO_MERGEは、既定の ort(2.34 から既定になったマージのやり方)でマージしたときだけ作られるgit log --merge -p <path>: ぶつかったファイルを触ったコミットの差分を出すgit mergetool: 画面のあるマージの道具を開く。Pro Git によると、道具を選んで開き、ぶつかった所を順に案内する(手元では流していません)
手で解くのが難しいときは、Pro Git が勧めるように、ぶつかった2つの側のコミットを見ると、なぜ同じ所を触ったかを思い出す手がかりになることがあります。
$ git log --merge --oneline --left-right
< 2f798fd main: change line2
> e18383c feature: change line2
片方が消し、片方が書き換えたとき
一方がファイルを書き換え、もう一方が消したときも、コンフリクトになります。feature で a.txt を書き換え、main で a.txt を消してあるとき、main で git merge feature を流すと、次のように出ました(git 2.39.3 の出力)。
$ git merge feature
CONFLICT (modify/delete): a.txt deleted in HEAD and modified in feature. Version feature of a.txt left in tree.
Automatic merge failed; fix conflicts and then commit the result.
$ git status --short
DU a.txt
git status は「deleted by us:」(自分の側が消した)と出し、作業ツリーには書き換えた側のファイルが残ります。マーカーは入りません。ファイルを残すなら git add <ファイル>、消すなら git rm <ファイル> をして、コミットします(GitHub の文書の手順です)。手元では、git rm a.txt ではファイルが消えたマージのコミットになり、git add a.txt では feature の中身で残りました。
やめて元に戻すには?(--abort)
解くのが難しいときや、予想していなかったコンフリクトのときは、いったんやめられます。git merge --abort は、いまのコンフリクトの解きかけをやめて、マージの前の状態に戻そうとします(git-merge の文書)。手元では、status が「nothing to commit, working tree clean」に戻り、HEAD もマージの前のコミットのままでした(git 2.39.3 の出力)。
$ git merge --abort
$ git status
On branch main
nothing to commit, working tree clean
$ git log --oneline -1
2f798fd main: change line2
注意: --abort は、解きかけた中身を捨てます。手で直した分も、git add した分も、マージの前に戻ります。手元でも、直しかけて add しないまま --abort したときも、add したあとに --abort したときも、a.txt は main line2 の元の中身に戻りました。VS Code の文書も「中止すると、コンフリクトを解いた作業は消える。残したい編集は先にコピーする」と注意しています。
もう1つ注意: マージを始めたときに、コミットしていない変更があると、--abort でもその変更を元どおりにできないことがあります、と git-merge の文書は書いています。そのため、merge の前に、変更をコミットするか stash(しまっておく)しておくよう勧めています。文書は「コミットしていない込み入った変更があるまま merge するのは勧めない」とも書いています。手元の git 2.39.3 では、マージと関係ないファイルの未コミットの変更は、--abort のあとも残りました。「できないことがある」場面は流していません。stash は git stash の使い方の記事で説明しています。
そもそも、merge や pull は、コミットしていない変更が、書き換えるファイルと重なると、何もせずに止まります。インデックスに HEAD とちがう変更(git add した変更)があるときも、関係ないファイルでも止まります。手元の git 2.39.3 では、次のように出ました(終了コード 2)。この場合はコンフリクトの前なので、--abort は要りません。変更をコミットするか stash してから、もう一度 merge します。
$ git merge feature
error: Your local changes to the following files would be overwritten by merge:
a.txt
Please commit your changes or stash them before you merge.
Aborting
Merge with strategy ort failed.
マージの途中でないときに git merge --abort を打つと、次のように止まります(終了コード 128)。手元の git 2.39.3 では、stash pop・rebase・cherry-pick のコンフリクトの途中でも、マージではないので、これが出ました。
$ git merge --abort
fatal: There is no merge to abort (MERGE_HEAD missing).
ほかのやめ方もあります。
git merge --quit: マージをやめたことにするが、インデックスと作業ツリーはそのまま残す。--abortと違って、元に戻さないgit reset --hard HEAD: Pro Git によると、これでも最後のコミットの状態に戻り、やり直せる。ただし、コミットしていない作業は全部消えます。resetはGit で取り消すには?の記事で説明しています
git-merge の文書によると、git merge --abort は、MERGE_HEAD があるとき、git reset --merge と同じです(merge の前の自動の stash があるときを除く)。
場面ごとのやめ方
やめ方は、起こした操作ごとに違います。
| 場面 | やめるコマンド |
|---|---|
| merge | git merge --abort |
| rebase | git rebase --abort(ブランチを rebase の前に戻す) |
| cherry-pick | git cherry-pick --abort(始める前の状態に戻す。文書の例では、作業ツリーにあったローカルの変更は残る) |
| revert | git revert --abort(Git で取り消すには?の記事) |
| pull | pull の中で動いたほうに合わせて、git merge --abort か git rebase --abort |
| stash pop | --abort は無い(あとの節で説明します) |
なお、VS Code の「中止」のコマンド(Git: Abort Merge など)は、stash を戻した操作は取り消しません。
片方の側を丸ごと選ぶには?(--ours・--theirs)
ぶつかったファイルを、片方の側の中身で丸ごと置き換えることもできます。git checkout --ours <ファイル> は自分の側(インデックスの2番)、git checkout --theirs <ファイル> は相手の側(3番)の中身にします。git restore --ours と --theirs も同じです。Pro Git は、片方を選ぶだけでよいときにすばやい方法で、とくに画像などのバイナリのファイルのコンフリクトで役に立つ、と書いています。
merge のときは、ours がいまのブランチ(HEAD の側)、theirs が取り込むブランチです。この例では、--ours で main の行、--theirs で feature の行になりました(git 2.39.3 の出力)。
$ git checkout --ours a.txt
Updated 1 path from the index
$ cat a.txt
line1
main line2
line3
$ git checkout --theirs a.txt
Updated 1 path from the index
$ cat a.txt
line1
feature line2
line3
注意: --ours と --theirs は、ファイルの中身を置き換えるだけで、「解いた」印は付きません。手元の git 2.39.3 では、--ours のあとも、git status --short は UU のままでした。選んだら、git add <ファイル> をして、git commit で終えます。
$ git checkout --theirs a.txt
Updated 1 path from the index
$ git add a.txt
$ git commit --no-edit
[main ab1e108] Merge branch 'feature'
ぶつかったファイルは、何も付けない git checkout <ファイル> や git restore <ファイル> では戻せません。「error: path 'a.txt' is unmerged」と出て、終了コード 1 で止まります。文書によると、add して解いた印を付けるまでは失敗します。-f で無視するか、--ours・--theirs で片方を採るか、-m で元のコンフリクトの結果に戻します。
バイナリのファイルがぶつかったとき
画像などのバイナリのファイルがぶつかると、手元の git 2.39.3 では「warning: Cannot merge binary files: img.bin (HEAD vs. feature)」と出ました。作業ツリーには HEAD の側の中身が残り、マーカーは入りません。git checkout --theirs img.bin で、相手の中身になりました。
選び直したいとき
git restore --merge <ファイル>(git checkout -m <ファイル> でも同じ)で、マーカーの入ったコンフリクトの状態を作り直せます。--conflict=diff3 や --conflict=zdiff3 を付けると、元の中身も出る形で作り直します。作り直したマーカーは、HEAD や feature ではなく ours と theirs の名前になります(git 2.39.3 の出力)。
$ git restore --merge a.txt
$ cat a.txt
line1
<<<<<<< ours
main line2
=======
feature line2
>>>>>>> theirs
line3
手元の git 2.39.3 では、--theirs を選んで git add したあと(コミットの前)でも、git restore --merge で UU のコンフリクトの状態に戻せました。コミットのあとは試していません。
-X ours と -s ours はまったく別もの
マージのときに、ぶつかった所だけを自動で片方に寄せるオプションもあります。-X ours(-X theirs)です。ぶつからない相手の変更は、そのまま入ります。
注意: -X ours と、-s ours を取り違えないでください。-s ours は、相手のしたことを全部捨てる、別のやり方です。git-merge の文書は、相手の中身を一切見ず、「自分の履歴に、相手で起きたことのすべてが含まれている」と宣言する、と説明しています。-s theirs というやり方は、ありません。
| 書き方 | 起きること |
|---|---|
git merge -X ours feature | ぶつかった所だけ、自分の側にする。ぶつからない相手の変更は入る |
git merge -X theirs feature | ぶつかった所だけ、相手の側にする。ぶつからない相手の変更は入る |
git merge -s ours feature | 相手の変更は、ぶつからないものも含めて全部入らない |
手元では、feature に、ぶつからない b.txt を足すコミットを1つ足して比べました(git 2.39.3)。-X theirs では a.txt が feature の行になり、b.txt も入りました。-X ours では a.txt は main の行のままで、b.txt は入りました。-s ours では、「Merge made by the 'ours' strategy.」と出て、b.txt は入りませんでした。
注意: rebase の途中では、ours と theirs が逆になります。次の節で説明します。
rebase・cherry-pick・stash pop・pull でコンフリクトしたら?
ここまでは merge の話でした。rebase・cherry-pick・stash pop・pull では、起き方、やめ方、そして ours と theirs の向きが違います。
rebase でコンフリクトしたら(ours と theirs が逆になる)
rebase は、自分のコミットを1つずつ載せ直します。ぶつかった最初のコミットで止まり、マーカーを残します。feature にいて git rebase main を流すと、次のようになりました(git 2.39.3 の出力)。端末では進み具合の表示(Rebasing (1/1))が別の行に上書きされて見えないので、この表示と、その前後の空の行は、ここでは省いています。
$ git rebase main
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
error: could not apply e18383c... feature: change line2
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply e18383c... feature: change line2
$ git status
interactive rebase in progress; onto 2f798fd
Last command done (1 command done):
pick e18383c feature: change line2
No commands remaining.
You are currently rebasing branch 'feature' on '2f798fd'.
(fix conflicts and then run "git rebase --continue")
(use "git rebase --skip" to skip this patch)
(use "git rebase --abort" to check out the original branch)
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
手元の git 2.39.3 の status は、ふつうの git rebase main でも「interactive rebase in progress」と出ました。やめ方(--abort)、飛ばし方(--skip)、続け方(--continue)も案内してくれます。
ファイルを開くと、マーカーは次のようになっています。
line1
<<<<<<< HEAD
main line2
=======
feature line2
>>>>>>> e18383c (feature: change line2)
line3
注意: <<<<<<< HEAD の下にあるのは、自分のブランチ(feature)ではなく、載せる先の main の行です。>>>>>>> の側が、載せ直している自分のコミット(feature の行)です。git-rebase の文書は、「ours と報告される側は、<upstream> から始まる、ここまでに載せ直した列で、theirs は作業中のブランチ。つまり、両者は入れ替わっている」と説明しています。
--ours と --theirs も同じ向きで入れ替わります。git rebase と git pull --rebase の途中では、--ours は載せる先(例: main、リモートの側)、--theirs は載せ直している自分の作業です(git-checkout の文書)。手元でも、--ours で main の行、--theirs で feature の行になりました。
$ git checkout --ours a.txt
Updated 1 path from the index
$ cat a.txt
line1
main line2
line3
$ git checkout --theirs a.txt
Updated 1 path from the index
$ cat a.txt
line1
feature line2
line3
git-checkout の文書は、逆になる理由を、こう説明しています。rebase は、リモートの履歴をみんなの正本とみなし、rebase する自分のブランチの作業を、そこへ取り込む「他の人の作業」として扱う。rebase の間は、自分が正本の番人の役になるため、という説明です。rebase の -X ours・-X theirs も、同じように逆になります(手元では流していません)。VS Code の文書も、名前で選ばず、中身を見て選ぶよう勧めています。
直し方は merge と同じです。ファイルを直して git add し、全部解いたら git rebase --continue です。add する前に --continue を打つと、「a.txt: needs merge」と出て止まります(終了コード 1)。
$ git rebase --continue
a.txt: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add
$ git add a.txt
$ git rebase --continue
[detached HEAD bd1ab56] feature: change line2
1 file changed, 1 insertion(+), 1 deletion(-)
Successfully rebased and updated refs/heads/feature.
rebase はコミットを1つずつ載せ直すので、コミットが複数あると、--continue のあとにまた別のコミットで止まることがあります(VS Code の文書)。止まったら、また直して、rebase が終わるまで繰り返します。手元では1コミットだけで流したので、複数で止まる場面は流していません。
やめるなら git rebase --abort です。手元では、--abort のあと、git log が rebase の前と同じになりました。そのコミットを飛ばすなら git rebase --skip です。飛ばしたコミットの変更は入りません。 手元では、--skip のあと、feature: change line2 のコミットは消え、feature は main と同じ位置になりました。
rebase をしたあと、もう push してあったブランチを push し直すと、強制 push が要ります。強制 push の注意はGit で取り消すには?の記事に、GitHub の Rebase and merge の前に手元で rebase して強制 push することがある話はプルリクエストとは?の記事にあります。
cherry-pick でコンフリクトしたら
git cherry-pick は、指定したコミットの変更を、いまのブランチに当てます。作業ツリーがきれい(HEAD から変更が無い)なことが要ります。当てられないときは、ブランチと HEAD は最後にうまくいったコミットのままで、CHERRY_PICK_HEAD が当てようとしたコミットを指し、ぶつかったファイルにマーカーが入ります。main で git cherry-pick feature を流しました(git 2.39.3 の出力)。
$ git cherry-pick feature
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
error: could not apply e18383c... feature: change line2
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
マーカーは、<<<<<<< HEAD の下がいまのブランチ、>>>>>>> e18383c (feature: change line2) の上が当てるコミットの中身でした。直して git add し、git cherry-pick --continue で新しいコミットができます。飛ばすなら --skip、やめるなら --abort で、--abort のあとは始める前の状態に戻りました。--quit は、進行中の状態を忘れるだけです。
stash pop でコンフリクトしたら(--abort は無い)
git stash pop で戻す変更が、いまの変更とぶつかると、コンフリクトになります。git-stash の文書によると、このとき stash は一覧から消えません。手で直したあと、自分で git stash drop します。終了コードは 1 です。マーカーは <<<<<<< Updated upstream(いまのブランチの側)と >>>>>>> Stashed changes(stash の側)です(git 2.39.3 の出力)。
$ git stash pop
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
On branch main
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
The stash entry is kept in case you need it again.
$ cat a.txt
line1
<<<<<<< Updated upstream
main line2 v2
=======
stash line2
>>>>>>> Stashed changes
line3
stash のコンフリクトは、解いてもマージのコミットは要りません(VS Code の文書)。手元の status にも、merge のときの「fix conflicts and run "git commit"」や --abort の案内は出ませんでした。
stash pop には --abort がありません。 手元の git 2.39.3 では、git stash pop --abort は「error: unknown option」で始まるエラーになり(終了コード 129)、git merge --abort も前に見た「MERGE_HEAD missing」で止まります。stash は一覧に残るので、中身はなくなりません。
$ git stash pop --abort
error: unknown option `abort'
usage: git stash pop [--index] [-q | --quiet] [<stash>]
-q, --quiet be quiet, only report errors
--index attempt to recreate the index
$ git stash list
stash@{0}: On main: wip
pop する前の状態に戻したいときは、手元の git 2.39.3 では、git restore --source=HEAD --staged --worktree a.txt で、そのファイルを pop の前(HEAD)の中身に戻せました。stash は残ったままです。これは公式の文書の手順ではなく、手元で出た結果です。 戻るのは、名指ししたファイルだけです。stash にぶつからないファイル(b.txt)も入っていると、pop でそのまま入った b.txt の変更は、add された状態(M b.txt)で残りました。pop の前から stash の外にあった、コミットしていない変更が無事かどうかは試していません。stash の使い方はgit stash の使い方の記事にあります。
pull でコンフリクトしたら
git pull は、リモートから取ってきたあとで、merge か rebase で取り込みます。手元とリモートが分かれていて、同じ行を変えていると、そこでコンフリクトします。git pull --no-rebase なら merge の、git pull --rebase なら rebase のコンフリクトです。
手元の git 2.39.3 では、分かれたブランチで、設定も付けずに git pull すると、コンフリクトの前に「fatal: Need to specify how to reconcile divergent branches.」で止まりました(終了コード 128。取ってくる処理は済んでいます)。最新の文書は、--ff-only(fast-forward だけ。ブランチの先を進めるだけで済む取り込みのことで、分かれていると失敗する)が既定と書いています。どう取り込むかの設定は、git pull と fetch の記事で説明しています。
--no-rebase のときは、merge のコンフリクトです。<<<<<<< HEAD の下が手元の行、>>>>>>> のうしろはリモートのコミットの40桁の名前でした。
$ git pull --no-rebase
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.
$ cat a.txt
line1
<<<<<<< HEAD
alice line2
=======
bob line2
>>>>>>> 5f7812292ce04aae9ce9764e81ba8652f1ba3c7e
line3
--rebase のときは、rebase のコンフリクトで、向きが逆です。この例では、<<<<<<< HEAD の下がリモート(bob)の行で、>>>>>>> の側が自分(alice)のコミットでした。
$ git pull --rebase
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
error: could not apply 18897dd... alice: line2
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 18897dd... alice: line2
$ cat a.txt
line1
<<<<<<< HEAD
bob line2
=======
alice line2
>>>>>>> 18897dd (alice: line2)
line3
pull のコンフリクトをやめるときは、pull の中で動いたほうに合わせて、git merge --abort か git rebase --abort です。手元でも、どちらも pull の前に戻りました。
早見:場面ごとの違い
| 場面 | <<<<<<< の側(上) | >>>>>>> の側(下) | --ours / --theirs | 解いたあと | やめるとき |
|---|---|---|---|---|---|
| merge | HEAD=いまいるブランチ | 取り込むブランチ | ours=いまのブランチ、theirs=取り込むブランチ | git add のあと git commit か git merge --continue | git merge --abort |
| pull(merge) | 手元のブランチ | リモートのコミット(名前は40桁) | merge と同じ | merge と同じ | git merge --abort |
| rebase・pull --rebase | 載せる先(main・リモート) | 載せ直している自分のコミット | 逆: ours=載せる先、theirs=自分の作業 | git add のあと git rebase --continue。また止まることがある | git rebase --abort(飛ばすなら --skip) |
| cherry-pick | HEAD=いまのブランチ | 当てるコミット | 調べていない | git add のあと git cherry-pick --continue | git cherry-pick --abort |
| stash pop | Updated upstream=いまの側 | Stashed changes=stash の側 | 調べていない | 直して git add、git stash drop。マージのコミットは要らない | --abort は無い。stash は残る |
GitHub の画面や VS Code で解くには?
手元のコマンドのほかに、GitHub の画面(ブラウザー)や、エディターの VS Code でも解けます。ここは、公式の文書の範囲です。GitHub の画面と VS Code は、この記事を書くときに手元で開いていないので、画面の見た目は確かめていません。ボタンの名前は、文書の表記(英語)のままです。
GitHub のプルリクエストの画面で解く
GitHub の画面で解けるのは、同じ行を別々に変えた、単純なコンフリクトだけです。それ以外のコンフリクトは、手元のコマンドで解きます。
注意: 画面で解くと、base branch(取り込み先のブランチ)全体が、head branch(プルリクエストのブランチ)にマージされます。head branch が既定のブランチや保護されたブランチなら、新しい head branch を作るよう求められることがあります。
手順は、GitHub の文書では次のとおりです。
- リポジトリ名の下の Pull requests を押す
- 一覧から、コンフリクトのあるプルリクエストを開く
- 下のほうの Resolve conflicts を押す
- 自分の側だけ・相手の側だけ・両方を合わせた新しい中身のどれにするか決める
- マーカー(
<<<<<<<・=======・>>>>>>>)を消して、残したい中身にする。1つのファイルに何か所もあれば、次のマーカーまで下へ動いて繰り返す - そのファイルを全部解いたら、Mark as resolved を押す
- ほかのファイルにもコンフリクトがあれば、左の「conflicting files」の下で次のファイルを選び、4〜7を全部のコンフリクトが解けるまで繰り返す
- 全部解いたら Commit merge を押す(base branch 全体が head branch にマージされます)
- 聞かれたら、コミットする先のブランチを確かめる。head branch を更新するか、新しいブランチを作れるとき(文書の「if available」)は新しいブランチを作る。head branch が保護されていれば、新しいブランチを作らなければならない。Create branch and update my pull request か I understand, continue updating BRANCH を押す(BRANCH のところには、実際のブランチ名が入ると読めます)
- マージするには Merge pull request を押す
Resolve conflicts が押せない(deactivated)ときは、別の Git の道具か、コマンドで解きます。ファイルを消したコンフリクト(片方が消し、片方が書き換えた)も、コマンドの文書が別の節にしています。残すなら git add <ファイル>、消すなら git rm <ファイル> をして、コミットします。
手元のコマンドで解いたあとは、手元でマージを終えるか、GitHub に push して、プルリクエストでマージします。プルリクエストを手元に取ってくる方法は、プルリクエストとは?の記事で紹介しています。
文書によると、Copilot cloud agent が有効なリポジトリでは、マージの欄の Fix with Copilot で、Copilot にコンフリクトを解かせることもできます。使える条件(プランや料金)は、調べていません。
VS Code で解く
VS Code の文書では、ぶつかった所の上に、次のボタンのような文字(CodeLens)が出ます。
- Accept Current Change: 今の側だけ残す
- Accept Incoming Change: 入ってくる側だけ残す
- Accept Both Changes: 両方を順に残す
- Compare Changes: 見比べる
「Current(今の側)」と「Incoming(入ってくる側)」の意味は、場面で変わります。VS Code の文書は「Current は、いつも元の feature ブランチとは限らない」と注意しています。
| 場面 | Current | Incoming |
|---|---|---|
| merge(pull の merge を含む) | チェックアウトしている取り込み先 | 取り込むブランチ |
| rebase(Pull (Rebase) を含む) | 新しい土台と、載せ直し済みのコミット | いま載せ直している自分のコミット |
| cherry-pick | チェックアウトしているブランチ | 当てるコミット |
| stash を戻す | 戻す先の作業の状態 | stash の変更 |
3方向のマージエディターは、ソース管理の「Merge Changes」の下のファイルを右クリックして Open in Merge Editor を選ぶと開きます。解いたら Complete Merge を押します。Complete Merge はそのファイルを add して閉じるだけで、マージ全体は終わりません。 merge は、ソース管理の画面でメッセージを書いて Commit します。rebase は統合ターミナルで git rebase --continue、cherry-pick は git cherry-pick --continue です。どの操作の途中か分からなければ git status を流します。やめるときは、コマンドパレット(Mac は ⇧⌘P、Windows・Linux は Ctrl+Shift+P)で Git: Abort Merge・Git: Abort Rebase・Git: Abort Cherry Pick を選びます。
よくある質問
マーカーの HEAD は、上と下のどちらが自分の側?
merge では、<<<<<<< HEAD の下(======= まで)が、merge を実行したときにいたブランチ、つまり自分の側です。下が取り込んだ相手の側です。ただし、rebase と git pull --rebase では逆で、HEAD の側は載せる先(main やリモート)、下の側が載せ直している自分のコミットです。stash pop では、Updated upstream がいまのブランチの側、Stashed changes が stash の側です。
git merge --abort で「MERGE_HEAD missing」と出るのは?
マージの途中ではない(MERGE_HEAD が無い)ときに出ます(「There is no merge to abort」)。手元の git 2.39.3 では、次の場面でこの表示になりました。もう --abort をしたあと、「would be overwritten by merge」で merge が始まる前に止まったあと、そして stash pop・rebase・cherry-pick のコンフリクトの途中です。rebase なら git rebase --abort、cherry-pick なら git cherry-pick --abort を使います。stash pop には --abort が無いので、前の節の戻し方になります。
GitHub で「Resolve conflicts」が押せないのは?
GitHub の画面で解けるのは、同じ行を別々に変えた単純なコンフリクトだけで、それ以外はコマンドで解く、というのが文書の説明です。押せないときは、別の Git の道具か、コマンドで解きます。片方がファイルを消し、もう片方が書き換えたコンフリクトも、コマンドで解きます(git add か git rm)。どの場面で押せなくなるかの一覧は、見つかりませんでした。
コンフリクトの解き方を間違えたら、やり直せる?
コミットする前なら、git merge --abort でマージの前に戻して、最初からやり直せます(解きかけた中身は消えます)。ファイルのコンフリクトの状態だけを作り直したいなら、git restore --merge <ファイル> です。手元の git 2.39.3 では、git add したあと(コミットの前)でも、作り直せました。
コミットして push したあとの取り消し方は、この記事では扱いません。Git で取り消すには?の記事のとおり、マージを revert すると、あとで同じブランチをマージし直しても、revert したマージに含まれていた変更は入ってこない、という注意があります。
まとめ
- コンフリクトは、同じ所を別々に変えたとき(と、片方が消し、片方が書き換えたとき)に起きる。merge のほか、rebase・cherry-pick・revert・stash pop・pull でも起きる
- ぶつかったファイルは
git status(短くはUUなど)で分かる。マーカーの上半分は、いつも自分の側ではない。rebase とgit pull --rebaseでは、HEADと--oursは載せる先の側 - 解くには、ファイルを直してマーカーを消し、
git addして、git commitか--continue。消し忘れても add と commit は止まらない(手元の git 2.39.3 では)ので、git diff --checkで確かめる - やめるには
--abort(merge・rebase・cherry-pick)。ただし、解きかけた中身は消える。merge の前の未コミットの変更は、戻らないことがある。stash pop には--abortが無い --ours・--theirsで中身を選んでも、git addが要る。-X ours(ぶつかった所だけ)と-s ours(相手の変更を全部捨てる)は別もの- GitHub の画面で解けるのは、同じ行の単純なコンフリクトだけ。画面で解くと、base branch 全体が head branch に入る
参考資料
- git-merge(Git 公式の文書)
- git-rebase(Git 公式の文書)
- git-cherry-pick(Git 公式の文書)
- git-stash(Git 公式の文書)
- git-pull(Git 公式の文書)
- git-checkout(Git 公式の文書)の --ours
- git-restore(Git 公式の文書)
- git-status(Git 公式の文書)の短い表示
- git-diff(Git 公式の文書)の --check
- git-add(Git 公式の文書)の --resolved
- Pro Git 第2版(英語)Basic Branching and Merging
- Pro Git 第2版(英語)Advanced Merging
- GitHub Docs: About merge conflicts
- GitHub Docs: Resolving a merge conflict on GitHub
- GitHub Docs: Resolving a merge conflict using the command line
- Visual Studio Code Docs: Resolve merge conflicts
- Git 2.56.0 の Release Notes(git add --resolved)
- Git 2.35.0 の Release Notes(zdiff3)
- Git 2.34.0 の Release Notes(ort が既定に)
- Git の公式サイト(最新の版)
※この記事は、公式の資料をもとに AI(Claude)で下書きし、2026年10月14日時点の公式の資料と照らして確かめてから公開しています。誤りに気づいたらお問い合わせからお知らせください。



