Lesson 05 · team collaboration

Merge Conflicts, Unscared

A conflict isn't Git breaking. It's Git refusing to guess. You already know what triggers one — now learn to read the markers and finish a merge by hand, start to end.

From Lesson 04: a three-way merge reconciles two diverged tips against their merge base. When each side changed different lines, Git merges them silently. A conflict happens for exactly one reason: both sides changed the same lines, and Git won't pick a winner. It stops and hands you the decision. That's all a conflict is.

What you see when it happens

$ git merge feature
Auto-merging config.txt
CONFLICT (content): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.

The merge is now paused, mid-flight. git status confirms it and lists the conflicted files under "Unmerged paths". Open the file and Git has written both versions into it, fenced by markers:

<<<<<<< HEAD timeout = 30 # ← what's on YOUR branch (the one you're merging into) ======= timeout = 60 # ← what's coming IN from the branch you named >>>>>>> feature
<<< HEAD → "ours" — the branch you ran merge from >>> feature → "theirs" — the branch being merged in

The ======= is just the divider between the two sides — not part of your file. Everything between the markers is a menu, and you're the chooser.

Resolve it — the five steps, every time

1
Edit the file so it reads exactly how you want the final result. Keep one side, keep the other, combine them, or write something new — Git doesn't care. Delete all three marker lines (<<<, ===, >>>) while you're there.
2
Stage the resolved file: git add config.txt. This is how you tell Git "this one's settled." Staging is the signal — nothing else marks a conflict as done.
3
Repeat 1–2 for every file git status lists as unmerged. A merge can conflict in many files at once.
4
Finish the merge: git commit. Git pre-fills the merge message. This writes the merge commit — the one with two parents.
5
Verify: git status reads "nothing to commit", and git log --graph --oneline shows the two lines rejoined.
VS Code makes step 1 easier Open a conflicted file and VS Code shows Accept Current Change / Accept Incoming Change / Accept Both buttons right above each conflict, plus a side-by-side view. "Current" = HEAD / ours; "Incoming" = theirs. It's the same choice as editing by hand — the buttons just delete the markers for you. You still do steps 2 & 4 (stage + commit) in the Source Control panel.

The escape hatch — undo the whole thing

Conflicts overwhelming, or you merged the wrong branch? You are never trapped mid-merge. One command rewinds to exactly the state before you typed git merge:

git merge --abort        # throw the whole merge away, back to a clean pre-merge state

Nothing is lost — --abort only discards the half-finished merge, never your committed work. Knowing this exists is what makes conflicts stop being scary: worst case, you press undo and try again.

The one thing not to do Don't git add a file that still has <<<<<<< markers in it. Git will happily commit those literal marker lines into your code — a classic way to break a build. Always re-read the file before staging: markers gone, code correct.
Your win You can take a merge from CONFLICT to a clean rejoined graph without googling: read the markers (ours vs theirs), edit to the result you want, add to mark each done, commit to finish — or --abort to bail. This is the exact skill the mission named: "resolve a real conflict solo, start to finish."

Go deeper

Primary source — read this one: Pro Git §3.2, "Basic Merge Conflicts". Same markers, Git's own walkthrough, plus git mergetool if you ever want a dedicated resolver.

Then play: Learn Git Branching — provoke a conflict on purpose and resolve it, so the marker-reading becomes muscle memory before it's a real repo under pressure.