Merge Conflicts Explained: What They Are and How to Fix Them
CONFLICT (content): Merge conflict in app.js looks alarming, but it's Git asking you a simple question. Why conflicts happen, how to read the <<<<<<< and >>>>>>> markers, how to resolve one in VS Code or with an AI tool, how to back out safely, and how to avoid most of them.
You try to merge a branch, or pull the latest changes, and Git stops with:
Auto-merging src/app.js
CONFLICT (content): Merge conflict in src/app.js
Automatic merge failed; fix conflicts and then commit the result.
Nothing is broken and nothing is lost. Git is asking you a question it can't answer on its own.
Why conflicts happen
Git is good at combining changes. If one branch edited the top of a file and another edited the bottom, it merges both automatically.
A conflict happens when two branches changed the same lines of the same file in different ways. Git can't know which version is right — maybe you want one, maybe the other, maybe a mix — so it marks the spot and asks you. (Git Branches Explained.)
It also happens when one branch edits a file and the other deletes it.
Reading the markers
Open the conflicted file and you'll find something like:
function greeting(name) {
<<<<<<< HEAD
return `Hello, ${name}!`
=======
return `Welcome back, ${name}.`
>>>>>>> new-welcome-text
}
- Between
<<<<<<< HEADand=======: the version on the branch you're on ("current" or "ours"). - Between
=======and>>>>>>> new-welcome-text: the version coming in from the other branch ("incoming" or "theirs").
Your job: edit the file so it contains what it should say, and delete all three marker lines. For example:
function greeting(name) {
return `Welcome back, ${name}.`
}
Resolving it step by step
- See which files conflict.
They're listed under "Unmerged paths."git status - Fix each file: choose a version or combine them, and remove the markers.
- Mark each file resolved by staging it:
git add src/app.js - Finish the merge.
Git suggests a message; accept it.git commit - Run the app and its tests. A conflict resolved without errors can still be wrong.
Search the whole project for <<<<<<< before committing. A leftover marker is a syntax error waiting to happen.
Resolving in VS Code
VS Code highlights conflicts and adds clickable options above each one:
- Accept Current Change — keep yours.
- Accept Incoming Change — keep theirs.
- Accept Both Changes — keep both, one after the other (then tidy up).
- Compare Changes — see them side by side.
For bigger conflicts, Resolve in Merge Editor shows your version, their version, and the result in three panes. (VS Code for Beginners.)
Resolving with an AI tool
Claude Code handles conflicts well, because it can read both branches and understand what each change was for. Ask it to:
Resolve the merge conflicts. For each one, explain what both sides were trying to do and how you combined them.
The explanation is the important part. If both sides changed the same function for different reasons, you usually want both intentions preserved — and a quick "keep the incoming version" can silently throw one of them away. Review the result before committing.
Getting out safely
If a merge goes sideways and you want to go back to before you started:
git merge --abort
For a rebase in progress, git rebase --abort. Everything returns to how it was. (How to Undo Anything in Git.)
Special cases
Lock files (package-lock.json, pnpm-lock.yaml) conflict often and are painful to fix by hand. Usually the easiest fix: take either version, then regenerate it:
git checkout --theirs package-lock.json
npm install
git add package-lock.json
Binary files like images can't be combined. Pick one version with git checkout --ours or --theirs.
How to get fewer conflicts
- Keep branches small and short-lived. Merge within a day or two.
- Pull
maininto your branch often, so you deal with small conflicts early rather than one huge one later. - Don't reformat whole files in the same branch as real changes. A formatter touching every line conflicts with everything. (Linters and Formatters Explained.)
- Give parallel AI agents separate areas of the code when you run several at once. (Run Parallel Claude Code Agents With Git Worktrees.)
EasySpawn gives each project a persistent, GitHub-connected workspace where Claude Code can pull, merge, resolve conflicts, and run your tests in the same environment before anything is pushed. See how it works or join the waitlist.
Related: Git Branches Explained · What Is a Pull Request? · How to Read a Diff
Keep reading
Regular Expressions for Beginners: Reading Regex Without Panic
^[\w.+-]+@\w+\.\w{2,}$ looks like a cat walked on the keyboard. It's a regular expression, and AI tools write them constantly. The dozen symbols that cover most regex, how to read one piece by piece, how to test them, and when not to use regex at all.
File Paths Explained: Absolute, Relative, and Why 'File Not Found' Happens
Cannot find module './components/Button'? ENOENT: no such file or directory? Most of the time it's a path problem. How file paths work on Mac, Linux, and Windows, absolute vs relative paths, ./ and ../, the working directory, case sensitivity, and import aliases like @/.