Conflicts
Trace commits and branches, choose an appropriate undo operation, and resolve a small merge conflict.
THE IDEA
What a conflict is
A conflict is not an error in Git; it is a question Git cannot answer. Two branches changed the same lines in different ways, and only a person knows which result is intended. Git merges everything it can, leaves the file with conflict markers, and pauses the merge.
Git stops and writes both sides into the file
$ git merge legal
Refund policy <<<<<<< HEAD Refunds are accepted within 30 days. ======= Refunds are accepted within 7 days for sale items. >>>>>>> legal Contact: [email protected]
Between <<<<<<< and ======= is what the branch you are on (HEAD) has. Between ======= and >>>>>>> is what the other branch has. Everything else merged cleanly.
<<<<<<< HEAD
what the branch you are on has
=======
what the other branch has
>>>>>>> legalResolving is editing plus telling Git
git statuslists Unmerged paths ("both modified").- Open each file and edit it into the final content. Remove all three marker lines.
git add <file>marks it resolved.git commitfinishes the merge.- Or give up cleanly with
git merge --abort.
Removing the markers is necessary, not sufficient. Try five resolutions of the same conflict:
Policy file: main says 30 days, legal says 7 days for sale items. Pick a resolution
Predict first. You delete just the three marker lines and keep everything else. Is the merge correct?
Search for <<<<<<< before staging, then run the program or its tests.
Stage every conflicted file blindly just to make git status go quiet.
Chapter context
Git records snapshots in a graph of commits. Branch names are movable references to commits. Treat the working tree, staging area and recorded history as distinct states, and many apparently mysterious commands become predictable.
TRY IT YOURSELF
On main the refund window became 30 days; on legal it was changed to 7 days for sale items and a new last line was added. Edit files with printf 'line\nline\n' > file. The prompt shows MERGING while a merge waits.
- Merge the legal branch into main and meet the conflict
- Back out completely with the abort command. Your files return to how they were before the merge
- Merge again and open policy.txt to read the conflict markers
- Rewrite policy.txt: keep the title, the 30-day sentence (the team decided 30 days), the contact line and legal's line Sale items are final. No markers and no 7-day or 14-day sentence
- Tell Git the conflict is resolved by staging the file
- Finish the merge with a commit
Commit graph (live)
Stuck, or something not working? You can come back to it any time.
CHECK YOUR UNDERSTANDING
After you delete only the conflict marker lines from a file, what must you still check before committing?
Chapter reference: math, worked example & code
This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.
Math and notation
Model history as a directed acyclic graph. A commit is reachable from a branch when following parent edges reaches it. A merge preserves both ancestry paths; rebasing creates a different path with new commit identities.
Worked example
Let B have parent A, C have parent B, and D have parent B. A merge M with parents C and D makes both C and D reachable. Moving a branch from C to M is different from copying D's files over C: the graph also records why those histories meet.
Reference code
The following example uses the Python standard library and does not call a remote service.
parents = {'A': [], 'B': ['A'], 'C': ['B'], 'D': ['B'], 'M': ['C', 'D']}
def ancestors(commit):
seen, todo = set(), [commit]
while todo:
node = todo.pop()
if node not in seen:
seen.add(node)
todo.extend(parents[node])
return seen
assert ancestors('M') == {'A', 'B', 'C', 'D', 'M'}
Python examples are provided for study and local execution; this page does not execute Python.
Common mistakes
Git commit does not automatically upload data. Rebase changes commit identities. Reset modes have different effects on uncommitted work.