Resolving Merge Conflicts

A merge conflict happens when two branches change the same part of the same file in different ways, and Git can't know which version is right. It's a normal part of working with others, not an error. Git pauses the merge, marks the clashing lines, and waits for you to decide.

Causing a conflict

Sam changes the number of servings on a branch, while on main someone else changes the same line. (printf writes several lines at once; \n starts a new line.)

$
git switch -c bigger-batch
printf 'Pancakes\nServes: 8\nMilk: 300 ml\nCook for 2 minutes each side.\n' > pancakes.txt
git commit -am "Double the pancake batch"
git switch main
printf 'Pancakes\nServes: 2\nMilk: 300 ml\nCook for 2 minutes each side.\n' > pancakes.txt
git commit -am "Make pancakes for two"
Output
Switched to a new branch 'bigger-batch'
[bigger-batch f793036] Double the pancake batch
 1 file changed, 1 insertion(+), 1 deletion(-)
Switched to branch 'main'
[main ce25452] Make pancakes for two
 1 file changed, 1 insertion(+), 1 deletion(-)
$
git merge bigger-batch
Output
Auto-merging pancakes.txt
CONFLICT (content): Merge conflict in pancakes.txt
Automatic merge failed; fix conflicts and then commit the result.

Understanding the situation

The merge is paused halfway. git status explains what's going on and lists the files that need attention under "Unmerged paths":

$
git status
Output
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:   pancakes.txt

no changes added to commit (use "git add" and/or "git commit -a")

Look inside the file. Git has written both versions into it, separated by conflict markers:

$
cat pancakes.txt
Output
Pancakes
<<<<<<< HEAD
Serves: 2
=======
Serves: 8
>>>>>>> bigger-batch
Milk: 300 ml
Cook for 2 minutes each side.
MarkerMeaning
<<<<<<< HEADStart of your version — the branch you're on (main)
=======Divider
>>>>>>> bigger-batchEnd of the incoming version from the branch being merged

Only the conflicting lines are marked. Everything else in the file — and any other changes from both branches that didn't overlap — has already been merged automatically.

Resolving it

Edit the file to contain exactly what you want: one side, the other, or a combination. Then delete all three marker lines. Sam decides on 6 servings — and adjusts the milk to match:

$
printf 'Pancakes\nServes: 6\nMilk: 450 ml\nCook for 2 minutes each side.\n' > pancakes.txt

Mark the file as resolved by staging it, then commit to finish the merge:

$
git add pancakes.txt
git status
Output
On branch main
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:
	modified:   pancakes.txt
$
git commit --no-edit
git log --oneline --graph
Output
[main 4689e87] Merge branch 'bigger-batch'
*   4689e87 (HEAD -> main) Merge branch 'bigger-batch'
|\
| * f793036 (bigger-batch) Double the pancake batch
* | ce25452 Make pancakes for two
|/
* 5370c83 Add pancake recipe

Before committing, double-check that no markers are left behind — searching the project for <<<<<<< is a good habit, and git diff --check warns about leftover markers too. If the project has tests, run them: a merge without textual conflicts can still combine two changes that don't work together.

Backing out

If a merge turns out messier than expected, cancel it. git merge --abort returns everything to how it was before you started the merge:

$
git merge weekend
Output
Auto-merging pancakes.txt
CONFLICT (content): Merge conflict in pancakes.txt
Automatic merge failed; fix conflicts and then commit the result.
$
git merge --abort
git status
Output
On branch main
nothing to commit, working tree clean

Taking one side completely

When you know one version is right for a whole file, you don't need to edit it by hand:

$
git checkout --ours pancakes.txt     # keep the version from the current branch
git checkout --theirs pancakes.txt   # keep the version from the branch being merged
git add pancakes.txt

To prefer one side for every conflict in the merge, use git merge -X ours branch or -X theirs. Use these with care — they silently discard the other side's changes to those lines.

Seeing the original too

Sometimes you need to know what the line looked like before either side changed it. Setting merge.conflictStyle to diff3 (or the tidier zdiff3 in Git 2.35+) adds a third section to each conflict showing the common ancestor's version:

$
git config merge.conflictStyle zdiff3
git merge weekend
cat pancakes.txt
Output
Auto-merging pancakes.txt
CONFLICT (content): Merge conflict in pancakes.txt
Automatic merge failed; fix conflicts and then commit the result.
Pancakes
Serves: 6
Milk: 450 ml
<<<<<<< HEAD
Cook for 90 seconds each side.
||||||| 4689e87
Cook for 2 minutes each side.
=======
Cook for 3 minutes each side.
>>>>>>> weekend

Now it's clear that both sides changed "2 minutes" — one to 3 minutes, the other to 90 seconds. Many people turn this on globally.

Tools

Most code editors highlight conflict markers and offer buttons such as "Accept Current", "Accept Incoming" and "Accept Both", and some have a three-pane merge editor. git mergetool opens each conflicted file in a merge tool you configure. They all do the same thing you did by hand: produce the final file, then you stage it.

Avoiding conflicts

  • Keep branches short-lived and merge main into them often.
  • Make small, focused commits and avoid reformatting whole files alongside real changes.
  • Agree on code formatting (an automatic formatter helps) so whitespace changes don't clash.
  • Talk to teammates when you're both about to change the same area.

Try it yourself

Create a file with three lines and commit it. On a branch, change the middle line; on main, change the same line differently. Merge, resolve the conflict by combining both edits, and finish the merge. Then repeat and practise git merge --abort.