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
- Explain exactly what makes Git raise a merge conflict
- Read the three conflict markers (<<<<<<<, =======, >>>>>>>)
- Resolve a conflict by editing the file and removing all markers
- Finish the merge with git add and git commit
- Bail out of a bad merge instantly with git merge --abort
- Prevent most conflicts with small, frequent merges and communication
💡 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-branch2️⃣ 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 --oneline5️⃣ 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 status6️⃣ 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)
- Committing the markers by accident — leaving <<<<<<< / ======= / >>>>>>> in a file breaks your code. Run git diff --check before every merge commit — it lists any leftover markers so you can delete them.
- Panicking and hacking at a bad merge — if a merge is going wrong, stop. git merge --abort rewinds to before the merge cleanly. That's almost always safer than trying to manually undo a half-resolved mess.
- Resolving the wrong side — blindly clicking "Accept Current" (or always keeping "mine") can silently throw away a teammate's fix. Read both versions, then choose — or combine them.
- "fatal: There is no merge to abort" — you've already committed the merge (or there isn't one). To undo a finished merge instead, use git reset --hard HEAD~1 on a local-only merge (with care).
- "error: Committing is not possible because you have unmerged files" — you tried to commit before resolving. Fix the markers, git add each file, then commit.
Pro Tips
- 💡 Search before you commit: git diff --check (or grep your project for <<<<<<<) catches markers you missed.
- 💡 Resolve, don't rush: a conflict is Git protecting two people's work. Read both sides before choosing.
- 💡 Abort is free: git merge --abort costs you nothing — practise with it until merges stop feeling scary.
- 💡 Small and often beats big and rare: frequent small merges create tiny, easy conflicts instead of giant ones.
📋 Quick Reference
| Command | Purpose |
|---|---|
| git merge <branch> | Start a merge (may raise a conflict) |
| git status | See which files are conflicted |
| git add <file> | Mark a resolved file as fixed |
| git commit | Complete the merge |
| git merge --abort | Cancel an in-progress merge |
| git diff --check | Warn about leftover markers |
| git mergetool | Open 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
- ✅ A conflict means two branches changed the same lines of the same file
- ✅ <<<<<<< HEAD … ======= … >>>>>>> wrap your version and theirs
- ✅ Resolve by editing to the content you want and deleting all three markers
- ✅ Finish with git add then git commit; check with git status
- ✅ git merge --abort safely rewinds a merge that's going wrong
- ✅ Small, frequent merges plus good communication prevent most conflicts
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
- Previous: Working with Remote Repositories
- Next: Git Workflows and Best Practices — Feature branch workflow, GitFlow, and commit message conventions
- Quick reference: Git cheat sheet
- From the blog: Essential Git Commands for Developers
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.