All posts
4 min read

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.

getting startedtoolingdebuggingbeginner

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 <<<<<<< HEAD and =======: 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

  1. See which files conflict.
    git status
    
    They're listed under "Unmerged paths."
  2. Fix each file: choose a version or combine them, and remove the markers.
  3. Mark each file resolved by staging it:
    git add src/app.js
    
  4. Finish the merge.
    git commit
    
    Git suggests a message; accept it.
  5. 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 main into 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