Resolving Merge Conflicts

Reviewed & published by Brayan K

By the end of this lesson you'll be able to read Git's conflict markers, resolve a clash by hand, finish the merge with git add and git commit, bail out safely with git merge --abort, and structure your work so conflicts rarely happen at all.

Part of the free Git course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn

💡 Real-World Analogy

A merge conflict is like two people editing the same sentence of a shared document at the same time. When their edits come together, the document can't show both, so it asks: "Alice wrote blue but Bob wrote green — which should I keep?" Git is exactly that careful editor. It happily combines edits to different sentences on its own, but when two edits land on the same line it stops and lets you, the human, make the final call. A conflict isn't an error or a bug — it's Git refusing to silently throw away someone's work.

1️⃣ Why Conflicts Happen

Git is very good at merging changes automatically. A conflict happens only when two branches modify the exact same lines of the same file. Different files, or different lines of the same file? Git merges them for you with no fuss. Read this worked example, then run a merge and watch Git stop.

# A conflict happens when two branches change the SAME lines of the SAME
# file, so Git can't decide which version is correct. It refuses to guess
# and hands the decision to you.
#
#   main   had:  color: blue;
#   you    made: color: red;     (on branch main)
#   teammate made: color: green; (on branch feature-branch)
#                                 -> both touch line 5 -> CONFLICT
#
# What does NOT conflict (Git merges these for you, no markers):
#   - different files were modified
#   - the same file, but different lines
#   - one branch adds new content, the other leaves that area alone
#
# Try to merge a branch that changed the same line and Git stops:
git merge feature-branch

2️⃣ Reading the Conflict Markers

When a conflict occurs, Git edits the file and wraps the clashing lines in three markers. Everything between <<<<<<< HEAD and ======= is your version (the branch you're on, called HEAD); everything between ======= and >>>>>>> is theirs (the branch coming in). Lines outside the markers merged cleanly.

# When a conflict happens, Git edits the file IN PLACE and inserts three
# markers around the clashing section. Open style.css and you'll see:

body {
  font-size: 16px;
<<<<<<< HEAD
  color: red;          # YOUR version  (the branch you are ON, called HEAD)
=======
  color: green;        # THEIR version (the branch you are merging IN)
>>>>>>> feature-branch
  margin: 0;
}

# Read the markers like this:
#   <<<<<<< HEAD        start of YOUR version (everything above =======)
#   =======             the dividing line between the two versions
#   >>>>>>> feature-branch   end of THEIR version (everything below =======)
#
# Note: "font-size" and "margin" are OUTSIDE the markers — Git merged those
# fine. Only the lines Git couldn't reconcile are wrapped.

3️⃣ Resolving by Hand

Resolving means making a decision and cleaning up. You edit the file to the version you actually want — keep yours, keep theirs, combine both, or write something new — and then delete all three markers. The conflict is "resolved" the moment no markers remain. Here's the same file from above, finished.

# To resolve, you EDIT the file by hand: pick the version you want (or
# combine them, or write something new), then DELETE all three markers.
# Here you decide "green" is correct, so the finished file reads:

body {
  font-size: 16px;
  color: green;        # kept THEIR version; HEAD line + all 3 markers gone
  margin: 0;
}

# A conflict is "resolved" when NO markers remain. Git doesn't care which
# side you keep — it only checks that <<<<<<<, =======, and >>>>>>> are gone.

Your turn. Below is a conflict in greeting.txt. You've decided the page should greet returning visitors. Replace the ___ with the one line that should remain — and remember, no markers belong in the finished file.

# 🎯 YOUR TURN — a conflict in greeting.txt. You decide the page should
# say "Welcome back!" (THEIR version). Write the file with NO markers left.

# The conflicted file currently looks like this:
#   <<<<<<< HEAD
#   Hello!
#   =======
#   Welcome back!
#   >>>>>>> feature-greeting

# Replace ___ with the single correct resolved line:
___                       # 👉 the one line that should remain (no markers!)

# ✅ Expected resolved greeting.txt:
#   Welcome back!

4️⃣ Finishing the Merge

Editing the file isn't quite the end. You have to tell Git the conflict is fixed by staging the file with git add, then complete the merge with git commit. Use git status at any point to see which files are still "both modified".

Now you finish a merge. You've already edited config.json and removed every marker — only the two final commands remain. Fill in the blanks.

# 🎯 YOUR TURN — you've already edited config.json and deleted every
# conflict marker. Two commands are left to FINISH the merge.

# 1) Tell Git the conflict in config.json is resolved
___ config.json          # 👉 the command that stages a resolved file

# 2) Complete the merge by recording a commit
git ___ -m "Merge feature-config"   # 👉 the verb that records a commit

# ✅ Expected: git status afterwards shows "working tree clean"
#    and the merge appears in  git log --oneline

5️⃣ The Escape Hatch: git merge --abort

Sometimes you start a merge and realise it's the wrong branch, or the conflicts are bigger than expected. Don't panic and start deleting markers at random. One command rewinds you to exactly how things were before the merge — like it never happened.

# Made a mess, or merged the wrong branch? Don't panic and don't start
# deleting markers blindly. One command rewinds you to BEFORE the merge,
# as if it never happened — no commits, no half-resolved files:
git merge --abort

# After aborting, your working tree is clean again:
git status

6️⃣ Resolution Tools

You never have to manage markers in a bare text editor. VS Code recognises conflicts and shows clickable Accept Current Change, Accept Incoming Change, and Accept Both Changes buttons right above each clash, plus a side-by-side comparison. Most editors and IDEs (JetBrains, Sublime) have the same. Git also ships git mergetool, which opens a dedicated three-way merge view. Whatever tool you use, the end state is identical: the right content, and no markers left behind.

7️⃣ Preventing Conflicts

The best conflict is one that never happens. Merge from main often so your branch doesn't drift, keep branches small and focused, talk to your team so two people aren't rewriting the same file, and use .gitignore so generated files never collide.

# The best conflict is one that never happens. Prevention strategies:
#   - Merge/pull often so your branch never drifts far from main.
#   - Keep branches small and focused (fewer changes = fewer clashes).
#   - Communicate so two people don't rewrite the same file at once.
#   - Don't mix a big refactor and a new feature in one branch/PR.
#   - Use .gitignore so generated files never cause fake conflicts.

# A simple "stay in sync" routine — pull main into your feature branch:
git checkout main
git pull origin main
git checkout my-feature
git merge main

# Create a .gitignore so build artefacts are never tracked (and so they
# never collide on merge):
cat > .gitignore <<'EOF'
node_modules/
dist/
.env
.DS_Store
*.log
coverage/
EOF
git add .gitignore
git commit -m "Add .gitignore"

Common Errors (and the fix)

Pro Tips

📋 Quick Reference

CommandPurpose
git merge <branch>Start a merge (may raise a conflict)
git statusSee which files are conflicted
git add <file>Mark a resolved file as fixed
git commitComplete the merge
git merge --abortCancel an in-progress merge
git diff --checkWarn about leftover markers
git mergetoolOpen a visual 3-way merge tool

Mini-Challenge: Resolve a Real Conflict

No blanks this time — just a brief and an outline. Reproduce a real conflict in your own terminal and take it all the way to a clean merge. This is the exact loop you'll run on real projects.

# 🎯 MINI-CHALLENGE: resolve a real conflict end to end.
# In your own terminal, reproduce and fix a conflict:
#
# 1. Make a repo and an initial commit on main with a file note.txt
#    containing one line:  Draft v1
# 2. Create a branch "edit-a", change the line to  Final A, commit.
# 3. Switch back to main, change the SAME line to  Final B, commit.
# 4. Merge edit-a into main  -> Git reports a CONFLICT in note.txt.
# 5. Open note.txt, decide the line should read  Final B,
#    delete all three markers, then stage and commit to finish.
#
# ✅ Expected: after the merge commit, git status is clean and note.txt
#    contains exactly one line:  Final B
#    (Tip: if you get stuck, git merge --abort rewinds and you can retry.)

# your commands here

🎉 Lesson Complete

Practice quiz

When does Git raise a merge conflict?

  • When two branches change different files
  • When you create a new branch
  • When a branch only adds new files
  • When two branches change the same lines of the same file

Answer: When two branches change the same lines of the same file. A conflict happens only when two branches modify the exact same lines of the same file, so Git can't auto-merge.

In a conflict, what is the section between <<<<<<< HEAD and =======?

  • The remote's version
  • Your version — the branch you are currently on
  • The version being merged in
  • A deleted file

Answer: Your version — the branch you are currently on. Everything above ======= up to <<<<<<< HEAD is your current branch's version (HEAD).

What does git status show during an unresolved conflict?

  • Files listed as 'both modified' / unmerged paths
  • A clean working tree
  • Nothing at all
  • A list of remotes

Answer: Files listed as 'both modified' / unmerged paths. git status lists conflicted files under 'Unmerged paths' as 'both modified'.

How do you know a conflict is fully resolved in a file?

  • You picked your own side
  • You ran git pull
  • No conflict markers (<<<<<<<, =======, >>>>>>>) remain
  • The file is empty

Answer: No conflict markers (<<<<<<<, =======, >>>>>>>) remain. Git only checks that all three marker lines are gone; it doesn't care which side you kept.

After editing a conflicted file, which command tells Git the conflict is resolved?

  • git resolve
  • git merge --done
  • git fix
  • git add

Answer: git add. Staging the edited file with git add marks that conflict as resolved.

What does git merge --abort do?

  • Rewinds to exactly before the merge, as if it never happened
  • Force-keeps your version everywhere
  • Deletes the conflicted branch
  • Commits the conflict markers

Answer: Rewinds to exactly before the merge, as if it never happened. git merge --abort cancels an in-progress merge and restores the pre-merge state.

After resolving and staging all conflicts, how do you finish the merge?

  • git push
  • git commit
  • git merge --continue only
  • git stash

Answer: git commit. You complete a conflicted merge with git commit; Git pre-fills a merge message for you.

Which command warns you about leftover conflict markers before committing?

  • git status --markers
  • git log --check
  • git diff --check
  • git merge --verify

Answer: git diff --check. git diff --check flags any leftover <<<<<<<, =======, or >>>>>>> marker lines.

Which is a good way to PREVENT conflicts?

  • Merge or pull from main frequently and keep branches small
  • Always work on one giant long-lived branch
  • Never communicate with teammates
  • Commit build output and node_modules

Answer: Merge or pull from main frequently and keep branches small. Small, frequent merges and focused branches mean each merge has far less to clash over.

What does the section between ======= and >>>>>>> branch-name represent?

  • Your current branch's version
  • A backup of the file
  • An empty placeholder
  • Their version — the branch being merged in

Answer: Their version — the branch being merged in. Below ======= up to >>>>>>> branch-name is the incoming branch's version.

Continue this course

Frequently asked questions

What do the <<<<<<<, =======, and >>>>>>> conflict markers mean?

Git inserts them around code it could not merge. Everything between <<<<<<< HEAD and ======= is your version (the branch you are on). Everything between ======= and >>>>>>> branch-name is their version (the branch you are merging in). To resolve, edit the section to what you want and delete all three marker lines.

I committed the conflict markers by mistake — how do I fix it?

Edit the file to remove the leftover <<<<<<<, =======, and >>>>>>> lines, then make a new commit. To catch this before committing, run git diff --check, which flags any leftover markers. Many teams also add a CI check or pre-commit hook that fails if markers are found.

What does git merge --abort do?

It cancels the in-progress merge and rewinds your repository to exactly how it was before you ran git merge — no merge commit, no half-resolved files. It is the safe escape hatch whenever a merge goes wrong or you merged the wrong branch. It only works while a merge is unfinished (before you have committed the merge).

How do I finish a merge once I've resolved the conflicts?

Stage each resolved file with git add <file> (this marks the conflict as resolved), then run git commit. Git pre-fills a merge commit message for you, so you usually just save and close. After that, git status should report a clean working tree.

How can I avoid merge conflicts in the first place?

Pull or merge from main frequently so your branch never drifts far, keep branches small and focused, and communicate so two people don't edit the same file at once. Avoid mixing big refactors with feature work, and use .gitignore so generated files (like node_modules or build output) never collide.

Related lessons