Programming and IT
How to resolve a merge conflict
A conflict is not a breakage, it is a question. Git merges changes automatically as long as they are in different parts of a file; when two branches edit the same lines, only a person can choose the right version. Your job is to read both versions, build working code out of them and tell Git the question is settled.
In this article
Where a conflict comes from#
A merge compares three states: the common ancestor of the two branches and the tips of both. If only one side changed a line, Git takes that change silently. If both sides changed the same line in different ways, the program has no grounds to prefer one over the other, so it stops.
A conflict can happen even without overlapping lines: one branch edits a file
while the other deletes or renames it. Git describes that case separately, with
words like deleted by them or added by us in the status output.
Important: a conflict does not roll your work back. The merge simply stays unfinished until you complete it or abort it.
What the stop looks like#
;
The first line says part of the changes merged on their own. The second names the file with the question. The full picture is in the status:
()
()
()
To list only the conflicted files and nothing else:
What the file contains#
Open the file and you will see both versions separated by markers:
<<<<<<<
= 0.20
return
=======
=
return *
>>>>>>> -
Between <<<<<<< and ======= is what you had (HEAD, the current branch).
Between ======= and >>>>>>> is what comes in from the branch being merged;
its name is written on the last marker.
Resolving the conflict means leaving the correct code in the file and deleting all three markers. The correct code may be the first version, the second, a mix of both or something new written from scratch:
=
return
A useful setting shows the ancestor's state as well:
Then a third chunk appears between the markers, ||||||| — the original text
before both edits. With it, it is much clearer who changed what: you can see that
one side changed the rate and the other changed the rounding, so you need both
changes.
The resolution routine#
Here git add does not mean "add a file" but "this question is closed". As long
as even one file has not been added, Git will not let you finish the merge. It
suggests the commit message itself — usually you keep it as it is.
When you need one version in full, you do not have to edit markers by hand:
There is a trap here. During a merge, --ours is your branch, which makes
sense. But during a rebase the sides swap: --ours becomes the base you are
replaying onto, and --theirs becomes your own commits. The reason is that a
rebase applies your changes on top of someone else's tip. More on the mechanism
itself in the article on git rebase.
How to get out if you are lost#
Until the merge is finished, one command rolls everything back:
The branch and the working copy return to the state before the merge. For a
rebase, git rebase --abort does the same; for a revert, git revert --abort.
If the merge is already committed and the result is bad, you can move the branch
tip back by one commit — provided the merge commit has not been pushed yet; the
modes and the danger of --hard are covered in the article on
git reset. A merge commit that has been pushed is
undone with git revert -m 1 <hash>, where the 1 says which of the two lines to
treat as the main one.
Common mistakes#
Markers left in the code. A classic: the file is added and committed along
with the <<<<<<< lines. Catch it by reviewing before the commit
(git diff --cached) or by searching the project: grep -rn '<<<<<<<' ..
Picking your version without reading theirs. Fast and almost always wrong:
the other person's edits vanish without a trace and the tests fail a week later.
If you do not understand why a teammate changed a line,
git log --merge -p billing/rates.py shows the history of that spot — only the
commits that touched the conflicted area remain in the output.
The same conflicts on every rebase. Turn on recorded resolutions and Git will reapply them for you:
Starting a merge with a dirty working copy. Git refuses to start if
uncommitted edits touch the files being merged. Commit or stash first
(git stash push), then merge — see the article on
git stash.
A huge conflict after a long-lived branch. The cure is a habit, not a trick: bring the main branch into yours often. A branch two days behind almost always merges without questions; one two months behind almost always has them.
Step-by-step plan
- List the conflictsgit status or git diff --name-only --diff-filter=U — only the unresolved files.
- Read both versionsMarkers <<<<<<<, =======, >>>>>>>; with zdiff3 you also see the common ancestor.
- Build the correct codeKeep what is needed, delete every marker; if appropriate use checkout --ours or --theirs.
- Mark it resolvedgit add each file; check that no markers remain (grep the project).
- Finish and verifygit commit, then build and run the tests: a merge without conflicts is not the same as working code.
Start learning this in your own space
The plan goes into your repository: tick off stages, keep notes — the change history shows how far you have come.
Check yourself
1.In a conflicted file, whose code is the part between <<<<<<< HEAD and =======?
2.You resolved the conflicts in your editor. Which command tells Git the file is ready?
3.A merge has started, there are many conflicts, and you want everything back as it was. What do you run?
4.Which setting makes Git also show the common ancestor's version between the markers?
Sources
-
Pro Git book“Git Branching” covers basic merges and conflicts, “Git Tools” the hard casesfree
-
git merge referenceThe section HOW CONFLICTS ARE PRESENTED explains the markersfree
-
git rerere referenceRecording resolved conflicts for repeated mergesfree
Was this helpful?