C.W.K.
Stream
Lesson 04 of 05 · published

Conflict Resolution Without Panic

~24 min · conflict, merge

Level 0Untracked Rookie
0 XP0/47 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Conflicts are not failure; they are review

The first time Git stops mid-merge with "CONFLICT (content):" the instinct is panic. That is wrong. A conflict is Git correctly refusing to guess. Two branches changed the same lines; Git cannot decide whose intent is right; you make the call. Treating conflicts as a normal part of integration — instead of a sign something broke — is the difference between fearing merges and shipping them daily.

When a conflict happens, Git inserts conflict markers into the affected file. Everything between <<<<<<< HEAD and ======= is your side. Everything between ======= and >>>>>>> other-branch is the incoming side. Your job: decide what the file should look like, edit accordingly, remove the markers, then git add the file. When all conflicted files are added, git commit finalizes the merge. git status walks you through this the entire time.

Three resolution moves cover most cases. Take one side wholesale when a file's incoming change is right and you can drop your local version: git checkout --ours file or git checkout --theirs file, then add. Take both sides manually when both changes are needed — common for additions to lists, imports, configs. Make something new when neither side captures the right behavior alone — common for logic conflicts where the merged version differs from both inputs.

If you started a merge and want out: git merge --abort rewinds everything back to before the merge, no traces. If you finished a merge resolution and pushed it, you cannot abort, but you can git revert -m 1 <merge-hash> to undo the merged content while keeping the merge commit's history shape. The escape hatches are real; conflicts are reversible until you commit the resolution.

Code

Conflict markers and the resolution loop·bash
# After a conflicting merge, file.js looks like:
# <<<<<<< HEAD
# const color = "blue";
# =======
# const color = "red";
# >>>>>>> feature/red-theme

# Edit file.js by hand to the version you want, e.g.:
# const color = process.env.THEME_COLOR || "blue";

git status                # shows "both modified: file.js"
git add file.js
git commit                # finalize the merge (Git pre-fills the message)
Wholesale and abort moves·bash
# Take only your side (current branch):
git checkout --ours conflicted-file
git add conflicted-file

# Take only their side (incoming branch):
git checkout --theirs conflicted-file
git add conflicted-file

# Bail out completely, restore pre-merge state:
git merge --abort

# After a bad merge that's already committed:
git revert -m 1 <merge-hash>      # undo the merge content, keep the shape

External links

Exercise

Engineer a conflict on purpose in a scratch repo: branch feature from main, change one line, switch back to main, change the same line differently, commit, then git merge feature. Open the conflicted file and resolve it three ways across three runs (reset between): wholesale ours, wholesale theirs, hand-edited synthesis. After each resolution, run git log --oneline --graph and inspect the merge commit with git show. Note which resolution feels best for which kind of change.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.