Introduction
When Git cannot automatically combine two changes to the same region of a file, it leaves conflict markers in the working copy and lets you resolve manually. The markers are not magic; they record exactly what each side did relative to a common base.
Anatomy
<<<<<<< HEAD
line as it is on our branch
=======
line as it is on their branch
>>>>>>> feature/login
Section between <<< and === is "ours" (the current branch). Between === and >>> is "theirs". Resolution is to keep the right text, delete the markers, and stage.
Three-way markers (diff3 style)
git config --global merge.conflictStyle diff3
Now markers also include the base version:
<<<<<<< HEAD
our version
||||||| merged common ancestor
base version
=======
their version
>>>>>>> feature/login
Seeing the base often clarifies which side intended what. Even better, since Git 2.35:
git config --global merge.conflictStyle zdiff3
which trims common context.
How Git produces them
For each pair of conflicting hunks, Git runs a three-way diff between base, ours, and theirs. If both sides changed the same region differently, Git writes both versions surrounded by markers. Otherwise the side that changed wins automatically.
Resolving
git status # list conflicted paths
edit each file
git add <file> # mark as resolved
git commit # uses prepared message
Or use a merge tool:
git mergetool
git config --global merge.tool meld
Inspecting each side
git show :1:path # base
git show :2:path # ours
git show :3:path # theirs
git checkout --ours path
git checkout --theirs path
The colon syntax reads from the conflicted index stages directly.
Aborting
git merge --abort
git rebase --abort
git cherry-pick --abort
rerere
"Reuse recorded resolution" remembers your conflict resolutions and reapplies them next time the same conflict appears:
git config --global rerere.enabled true
Indispensable for long-running rebase chains.
Renames and binary conflicts
Not all conflicts produce text markers. Rename/rename, rename/delete, and modify/delete conflicts leave the index in a state with multiple stages but no <<< markers in the file. Binary files cannot be merged textually at all; both versions are written to disk and the index records the conflict:
git status
# both modified: image.png
# deleted by us: old.txt
# added by them: new.txt
git checkout --ours image.png # keep our version
git checkout --theirs new.txt
git add image.png new.txt
Always read git status at conflict time; it explicitly labels these less common conflict types.
Common mistakes
Resolving by deleting the markers without reading the contents, accidentally dropping one side. Always read both halves and the base. Forgetting to git add after editing; git commit will refuse with "unmerged paths". Treating --ours and --theirs as identical to -X ours and -X theirs; the former replaces an entire conflicted file, the latter is a hint to the merge strategy. Finally, copying a partially resolved file from elsewhere and bypassing Git; the index still has stage 1/2/3 entries until you git add.