How to resolve a merge conflict in Git

A conflict is not an error — it's Git refusing to guess which of two edits wins. The fix is a text edit plus two commands. Escape hatch first, in case you're mid-panic: git merge --abort puts everything back.

Step 1 — see which files conflict

git status
# "Unmerged paths:" lists the conflicted files:
#   both modified:   config.py

Step 2 — open the file, read the markers

<<<<<<< HEAD
timeout = 30                 # ← YOUR version (current branch)
=======
timeout = 60                 # ← THEIR version (incoming branch)
>>>>>>> feature-x

# everything between the markers is the disputed zone.
# the rest of the file is already merged fine.

Step 3 — edit to the truth, delete all three markers

# keep yours, keep theirs, or write something new:
timeout = 60

# what must be true when you're done:
# 1. the code is what you actually want
# 2. no <<<<<<<, =======, >>>>>>> anywhere in the file

Step 4 — mark resolved, finish the merge

git add config.py
git commit                   # git pre-fills the merge message — save & close
# done. the merge commit ties both histories together.

Shortcut: take one side wholesale

# the whole file, my version:
git checkout --ours  config.py  && git add config.py
# the whole file, their version:
git checkout --theirs config.py && git add config.py

# great for lock files (package-lock.json etc.) — often the
# right answer is "take either side, then re-run the install".
The two classic mistakes
1. Committing the markers. Your app crashes pointing at a line of <<<<<<< — search the project for <<<<<<< before committing any merge. 2. Resolving in a rush by picking a side blindly. The markers show what changed but not why — when both edits look intentional, ask the other author. Two minutes of Slack beats re-breaking their fix.
During a rebase instead?
Same markers, same edit, but finish with git rebase --continue (not commit), and the escape hatch is git rebase --abort. "Ours/theirs" are swapped during a rebase — read the marker labels, not your assumptions.

Having fewer conflicts (the real fix)

git pull often               # small frequent merges beat giant rare ones
# keep branches short-lived (days, not months)
# don't reformat whole files in the same commit as logic changes
#   (formatting-only diffs are conflict factories)
📚 This is one page of our Git series. The full mental model — three trees, branches as sticky notes, with audio: Git in 10 Minutes →