Merge Conflicts
A conflict happens when two branches change the same lines, or when one edits a file the other deleted, and Git cannot decide which version should win. So it stops and asks you. Nothing is resolved automatically here — the entire point is to produce the correct result without silently throwing away either side's work.
Conflicts are not a failure state; they are Git refusing to guess. The mistakes that hurt are the ones where you guess for it — keeping one side without reading the other, or committing the markers themselves.
When Conflicts Occur
Git auto-merges anything it can reconcile unambiguously: changes to different files, or different regions of the same file, merge silently. A conflict is what is left over. The common cases are overlapping line edits (both sides changed the same region), add/add (both branches created a file at the same path with different content), and modify/delete (one side edited a file the other removed). The last one has no "lines" to merge at all — you must decide whether the file lives or dies.
Reading Conflict Markers
Git writes the conflicting region inline between markers. Everything between <<<<<<< and ======= is "ours"; everything between ======= and >>>>>>> is "theirs." The catch is that "ours" and "theirs" are defined by the operation, not by intuition. In a merge, "ours" is the branch you are sitting on and "theirs" is the branch being merged in. That mapping inverts during a rebase, which the comparison box below covers.
Resolving Step by Step
Open the file, delete the markers, and edit the region down to the result you actually want — which may be one side, the other, or a hand-written combination of both. Then git add the resolved file to mark it settled, and finish with git commit (or git merge --continue). The git add step is what tells Git the conflict is handled; skip it and Git still thinks the file is in conflict.
Tooling
git mergetool launches a configured visual three-way tool. git checkout --ours <file> and git checkout --theirs <file> take one whole side of a file when you are certain — but remember the side names depend on whether you are merging or rebasing. Setting git config merge.conflictstyle zdiff3 adds the common ancestor to the markers, so you can see what each side changed from, which usually makes the intended resolution obvious.
Aborting and Retrying
If a merge is going wrong, git merge --abort returns the repository to its exact pre-merge state, cleanly. That is almost always better than hand-unwinding a half-resolved tree or running a destructive reset, and it lets you re-approach the merge after updating a branch or reading more carefully.
During a merge — "ours" is the branch you are currently on (the merge target), and "theirs" is the branch being merged in. This matches intuition: your branch is "ours."
During a rebase — the roles invert. Rebase replays your commits one at a time onto the other branch, so at each step "ours" is the branch you are rebasing onto (the new base) and "theirs" is your own commit being replayed. Reach for --theirs thinking in merge terms during a rebase and you take the exact opposite side from what you meant.
- Leaving conflict markers like
<<<<<<<in a file and committing them, shipping broken syntax to the remote. - Resolving by deleting the side you did not understand instead of reading both, silently losing another developer's change.
- Running
git checkout --theirs <file>during a rebase while thinking in merge terms, taking the opposite side from what you intended. - Forgetting to
git addthe resolved file, so the commit either still reports the conflict as unresolved or records a stale version. - Re-running a long merge from scratch after a wrong resolution instead of using
git merge --abortto reset cleanly first.
- Read both sides fully before resolving; never reflexively keep "ours" or "theirs" without understanding what each changed.
- Set
git config merge.conflictstyle zdiff3so markers also show the common ancestor, which clarifies each side's intent. - After editing,
git addeach resolved file and rungit statusto confirm no conflicts remain before committing. - Use
git merge --abortto bail out cleanly when a merge is going sideways, instead of hand-unwinding it. - Reduce conflict frequency by merging or rebasing
mainoften and keeping branches short.
hg resolve --mark / --list with configured toolsSubversion writes .mine / .r<rev> files, resolved with svn resolvePerforce resolves interactively via p4 resolveFossil uses standard markers and a configured merge commandKnowledge Check
During a rebase, which side is "theirs" at a conflict?
- Your own commit being replayed onto the new base — the roles invert from a merge
- The branch you are currently sitting on, exactly as the mapping works in a merge
- Always the
mainbranch, no matter which operation produced the conflict - Whichever side carries the more recent commit timestamps
What is a modify/delete conflict?
- One branch edited a file the other branch deleted, so Git asks whether the file should live or be removed
- Both branches edited the very same line in incompatible ways that Git cannot reconcile, so it stops and asks you to pick which version wins
- A single file was renamed on both sides to two different paths at once, leaving Git unsure which of the two destination names to keep
- The exact same file was committed twice within a single branch's history, so the merge cannot tell which of the duplicate copies to keep
Why is committing a file that still contains conflict markers a real failure?
- The
<<<<<<<lines are literal text in the file, so the committed code is syntactically broken and ships to the remote - Git strips the marker lines automatically at commit time and keeps only your chosen side, so nothing ever actually reaches the remote broken
- The markers are stored in a separate side channel of the commit and only ever appear in
git logoutput, never in the actual working file - It silently reverts the whole file back to the common ancestor version, discarding both sides' edits so the broken markers never persist
A merge is going badly and you want a clean slate. What is the right move?
git merge --abortto restore the exact pre-merge stategit reset --hard HEAD~1to drop the last commit- Manually delete every changed file and re-clone
git committhe markers and fix them in a follow-up
You got correct