前回の「ブランチで安全に試す」では、別ブランチで変更して main に merge する流れを体験しました。あのとき merge はスムーズに終わりましたが、いつもそうとは限りません。main でもブランチでも同じ行を変更していた場合、Git は「どちらを採用すればいいか分からない」と止まります。この状態がコンフリクト(conflict)です。
conflict をわざと起こし、ファイルに書き込まれる印を読み、手で直して merge を完了するところまでを練習します。
この回の実行環境: VS Code のターミナル(PowerShell)と git-practice フォルダを使います。
この回の成功条件:
- conflict の印を見つけて、ファイルを手で修正できる
git statusで unmerged が消え、git logに merge commit が残る
conflict はどういうときに起きるか
前回は main に何も変更がない状態でブランチを merge しました。Git は main の先端をブランチの先端まで進めるだけで済み、Fast-forward で完了しました。
今回は状況が違います。main とブランチの両方で memo.txt の同じ行を書き換えます。Git は「両方に変更がある。どちらを採用するかは人間が決めてくれ」とファイルに印を残して止まります。これが conflict です。
main: ●───●───● ← 1行目を「main側の変更」に書き換え
↘
edit-memo: ● ← 1行目を「ブランチ側の変更」に書き換え
conflict を起こしてみる
準備 — ブランチを作る
ターミナルで git-practice フォルダにいることを確認します。
Get-Location
C:\Users\yourname\git-practice
この回は、未コミット変更がない状態から始めます。次のコマンドを実行してください。
git status
On branch main
nothing to commit, working tree clean
nothing to commit, working tree clean と表示されれば準備完了です。別の変更が残っている場合は、そのまま進めると今回の conflict と混ざって分かりにくくなります。いったん前回までの状態を整理してから進めてください。
まず新しいブランチ edit-memo を作って切り替えます。
git switch -c edit-memo
Switched to a new branch 'edit-memo'
fatal: a branch named 'edit-memo' already exists と出た場合は、前回の練習が残っています。edit-memo-2 など別の名前で作り、以降の edit-memo をその名前に読み替えて進めてください。
ブランチ側で memo.txt を変更する
VS Code で memo.txt を開き、1行目を次のように書き換えます。
Git の練習メモ(ブランチで編集)
1行目だけ変えます。2行目以降はそのままにしてください。
保存したらコミットします。
git add memo.txt
git commit -m "memo.txtの1行目をブランチで変更"
main 側でも同じ行を変更する
main に戻ります。
git switch main
memo.txt を開くと、1行目はブランチで変更する前の状態に戻っています。ここで main 側でも1行目を書き換えます。
Git の練習メモ(mainで編集)
保存してコミットします。
git add memo.txt
git commit -m "memo.txtの1行目をmainで変更"
これで main とブランチの両方が memo.txt の1行目を変更した状態になりました。
merge して conflict を発生させる
main にいる状態で merge します。
git merge edit-memo
Auto-merging memo.txt
CONFLICT (content): Merge conflict in memo.txt
Automatic merge failed; fix conflicts and then commit the result.
CONFLICT と表示されました。Git は自動で合わせられなかったので、ここで止まっています。
git status で状態を確認する
conflict が起きた直後の状態を確認します。
git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: memo.txt
both modified は「main 側でもブランチ側でも変更がある」という意味です。この状態のファイルは「未解決(unmerged)」として扱われます。
conflict の印を読む
memo.txt を VS Code で開きます。次のような内容が書き込まれています。
<<<<<<< HEAD
Git の練習メモ(mainで編集)
=======
Git の練習メモ(ブランチで編集)
>>>>>>> edit-memo
この3つの印がコンフリクトマーカーです。
| 印 | 意味 |
|---|---|
<<<<<<< HEAD | ここから下が、今いるブランチ(main)の内容 |
======= | 境界線。ここから下が merge しようとしたブランチの内容 |
>>>>>>> edit-memo | ここまでが edit-memo ブランチの内容 |
つまり、<<<<<<< HEAD と ======= の間が main 側、======= と >>>>>>> edit-memo の間がブランチ側です。
手で直して解消する
conflict を直すには、マーカーを含めて「最終的に残したい内容」に書き換えます。
どちらを残すかは自分で判断します。今回は main 側の内容を採用します。マーカー行をすべて消し、残す行だけにします。
修正前:
<<<<<<< HEAD
Git の練習メモ(mainで編集)
=======
Git の練習メモ(ブランチで編集)
>>>>>>> edit-memo
修正後:
Git の練習メモ(mainで編集)
マーカーの3行(<<<<<<<、=======、>>>>>>>)を消し忘れると、そのままファイルに残ってしまいます。全部消えたことを目で確認してください。
両方の内容を組み合わせたい場合は、マーカーを消したうえで好きなように書き直して構いません。たとえば「Git の練習メモ(main とブランチ両方で編集)」にしてもよいです。
ファイルを保存します。
解消を Git に伝える
conflict を直したファイルを git add でステージします。
git add memo.txt
もう一度 git status を確認します。
git status
On branch main
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: memo.txt
All conflicts fixed と表示されていれば、あとはコミットするだけです。
git commit -m "memo.txtのconflictを解消してmerge"
[main xxxxxxx] memo.txtのconflictを解消してmerge
これで merge が完了しました。
merge 後のログを確認する
git log --oneline
xxxxxxx memo.txtのconflictを解消してmerge
xxxxxxx memo.txtの1行目をmainで変更
xxxxxxx memo.txtの1行目をブランチで変更
xxxxxxx ブランチ練習の行を追加
...
conflict を解消した merge commit が先頭に入っています。前回の Fast-forward とは違い、merge 操作自体が1つのコミットとして記録されます。
使い終わったブランチを削除しておきます。
git branch -d edit-memo
詰まったら merge をやり直す — git merge —abort
conflict の印を見て混乱したり、いろいろ書き換えてよく分からなくなったりしたときは、merge 自体をなかったことにできます。
git merge --abort
このコマンドは、merge を開始する前の状態にファイルを戻します。git add や git commit をする前であればいつでも使えます。
やり直したいときの手順:
git merge --abortで merge 前に戻る- 落ち着いてから再度
git merge edit-memoを実行する - 改めてファイルを開いて印を読み、直す
VS Code の conflict 表示
VS Code で conflict が起きたファイルを開くと、マーカーの上に「Accept Current Change」「Accept Incoming Change」「Accept Both Changes」などのボタンが表示されることがあります。
これらのボタンを使うと、手でマーカーを消す代わりにワンクリックでどちらかを選べます。ただし、最初は印を自分で読んで「どこからどこまでが何の内容か」を理解するほうが確実です。慣れてきたらボタンを使っても構いません。
ボタンを使った場合でも、そのあとの git add → git commit は同じです。
この回のまとめ
| 操作 | コマンド |
|---|---|
| merge で conflict を起こす | git merge ブランチ名 |
| 未解決ファイルを確認する | git status |
| 解消したファイルをステージする | git add ファイル名 |
| merge を完了する | git commit |
| merge をやり直す | git merge --abort |
conflict 解消の流れ:
git mergeで conflict が起きるgit statusでboth modifiedのファイルを確認する- ファイルを開き、
<<<<<<< ======= >>>>>>>の印を読む - どちらを残すか決めて、マーカーをすべて消す
git add→git commitで merge を完了する
混乱したら git merge --abort で merge 前に戻れます。
次のステップ
conflict は、Git を使っていると必ず出会います。チーム開発ではもちろん、自分一人でも複数ブランチを使えば起こり得ます。大事なのは「慌てない」ことです。印を読んで、どちらを残すか決めて、マーカーを消す。この手順さえ分かっていれば対処できます。
Java や Spring Boot の学習を進める中で conflict に遭遇したら、この回の手順を見返してください。