Resolving Conflicts
Resolving conflicts is a small skill that pays back forever. The first one feels intimidating; the tenth one takes a minute. The recipe is always the same: identify what conflicts, edit each file, mark them resolved, finish the merge. This page walks you through a complete resolution from start to finish with realistic examples.
Step-by-step recipe
git status— see which files conflict.Open each conflicted file.
Pick the correct content; delete the
<<<,===,>>>markers.git add <file>to mark each one resolved.git commit(orgit merge --continue) to complete the merge.
A worked example
Suppose main and feature-x both edited a function:
src/login.js — on main
function greet(name) {
return `Hello, ${name}!`;
}src/login.js — on feature-x
function greet(name) {
return `Hi there, ${name}.`;
}The merge
git switch main git merge feature-x # CONFLICT (content): Merge conflict in src/login.js # Automatic merge failed; fix conflicts and then commit the result.
src/login.js after Git's mark-up
function greet(name) {
<<<<<<< HEAD
return `Hello, ${name}!`;
=======
return `Hi there, ${name}.`;
>>>>>>> feature-x
}Decide what to keep
Read both versions. Pick the right answer for the project:
Keep only
Hello, ${name}!— keep the current branch’s version.Keep only
Hi there, ${name}.— take the incoming branch’s version.Combine them — e.g., greet differently based on locale.
Rewrite — sometimes both are wrong and you start over.
The final version
function greet(name) {
return `Hello, ${name}!`;
}Save the file. Remove all three conflict markers and everything you don’t want.
Mark resolved and commit
git add src/login.js git status # All conflicts fixed but you are still merging. # (use "git commit" to conclude merge) git commit # (default message: "Merge branch 'feature-x'" — edit if you like)
If there are many conflicts
Tackle them one file at a time
git status # see the list git diff --name-only --diff-filter=U # just the names git mergetool # open them in your visual tool # or open them yourself in your editor and edit each
Helpful inspection commands
What did each side change?
# Show the common ancestor's version git show :1:src/login.js # "stage 1" — base git show :2:src/login.js # "stage 2" — our side git show :3:src/login.js # "stage 3" — their side # Diff against the merge base (Git's view of the conflict) git log --merge -p -- src/login.js git log --merge --oneline -- src/login.js
Picking one side without editing
# Take our version verbatim git checkout --ours src/login.js git add src/login.js # Take their version verbatim git checkout --theirs src/login.js git add src/login.js
Verifying resolution
Catch leftover markers
git diff --check # Reports any line still containing <<< === or >>> # Run tests after every merge — conflicts that LOOK resolved can still # break behaviour npm test pytest go test ./...
Continuing a merge
# Equivalent to 'git commit' when no further conflicts remain git merge --continue
Bailing out
git merge --abort # Restores everything to pre-merge state
Tips that experienced developers use
Use a 3-way diff view. Tools like VS Code or Beyond Compare show base / ours / theirs side by side — much easier than reading conflict markers in text.
Enable rerere (
git config rerere.enabled true). Git remembers your resolutions and replays them automatically if the same conflict happens again (common during long rebases).Take small bites. If you have 20 conflicting files, resolve and stage one at a time. Long resolution sessions invite mistakes.
Talk to the original author. Sometimes the right answer requires context only they have — ping them in chat.
Run tests immediately. A compilable resolution is not the same as a correct one.