65  65. Merge Conflicts

Most merges happen automatically. But when two branches change the same lines of a file in different ways, Git can’t know which version you want, so it stops and asks you to decide. This is a merge conflict. Conflicts are a normal part of working with branches, teammates, and AI agents, and once you have resolved one or two, they are not scary.

65.1 When do conflicts happen?

Git merges files line by line:

What the two branches changed Result of the merge
Different files Merged automatically
Different parts of the same file (with unchanged lines between them) Merged automatically
The same lines (or lines right next to each other), in different ways Conflict - you decide
One branch deleted a file, the other edited it Conflict - you decide

The same thing can happen with git pull, because a pull ends with a merge (see Sharing a Repository). When a conflict happens, nothing is lost: Git keeps both versions and shows you exactly where they disagree.

65.2 A conflict, step by step

The easiest way to learn is to create a conflict on purpose. Maria continues from Branches and Merging. In src/index.html, her introduction line reads:

    <p>Hi, I'm Maria. I study business and build websites.</p>
  1. She creates a branch new-intro, changes the page title to Maria Lopez - Portfolio, rewrites the intro line as <p>Hi, I'm Maria, a business student who builds websites.</p>, and commits.
  2. She switches back to main, changes the same intro line differently, to <p>Hi, I'm Maria. I study business and love building websites.</p>, and commits again.

Both branches changed the intro line, so merging them conflicts:

git merge new-intro

Output:

Auto-merging src/index.html
CONFLICT (content): Merge conflict in src/index.html
Automatic merge failed; fix conflicts and then commit the result.

The merge is now paused. Git is waiting for you.

65.3 Reading the conflict

git status tells you which files need attention:

git status

Output:

On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
    both modified:   src/index.html

no changes added to commit (use "git add" and/or "git commit -a")

“Unmerged paths” lists the conflicted files; both modified means both branches changed the file. Open src/index.html in your editor (or look with cat):

<!DOCTYPE html>
<html>
<head>
    <title>Maria Lopez - Portfolio</title>
    <link rel="stylesheet" href="../css/style.css">
</head>
<body>
    <h1>Welcome to My Portfolio</h1>
<<<<<<< HEAD
    <p>Hi, I'm Maria. I study business and love building websites.</p>
=======
    <p>Hi, I'm Maria, a business student who builds websites.</p>
>>>>>>> new-intro
    <p><a href="contact.html">Contact me</a></p>
</body>
</html>

Git has written conflict markers into the file:

Marker Meaning
<<<<<<< HEAD Start of the conflict. The lines below it are your current branch’s version (HEAD, here main).
======= Separates the two versions.
>>>>>>> new-intro End of the conflict. The lines just above it are the version from the branch you are merging in (new-intro).

Notice that the new title is already there, without markers: Git merged the part only one branch changed and left only the real disagreement for you.

65.4 Resolving the conflict

  1. Decide what the file should say. Keep your version, keep the other version, or combine them. Maria combines them:

        <p>Hi, I'm Maria, a business student who loves building websites.</p>
  2. Delete all three marker lines (<<<<<<<, =======, >>>>>>>) and save the file. A file that still contains markers is broken: the markers would appear on the web page. Before you stage the file, git diff --check lists any leftover markers (it also flags stray spaces at the ends of lines) and prints nothing when the file is clean:

    git diff --check
  3. Mark the file as resolved by staging it:

    git add src/index.html
    git status

    Output:

    On branch main
    Your branch is ahead of 'origin/main' by 1 commit.
      (use "git push" to publish your local commits)
    
    All conflicts fixed but you are still merging.
      (use "git commit" to conclude merge)
    
    Changes to be committed:
     modified:   src/index.html
  4. Finish the merge with a commit:

    git commit

    Git opens your editor with the message Merge branch 'new-intro' already filled in (plus some comment lines starting with #, which Git ignores). Save and close to accept it (in nano: Ctrl+O, Enter, Ctrl+X).

    Output:

    [main cd24c15] Merge branch 'new-intro'

The history now shows the merge commit joining the two branches:

git log --oneline --graph

Output (older commits cut off):

*   cd24c15 (HEAD -> main) Merge branch 'new-intro'
|\
| * 0f4ca56 (new-intro) Update title and intro
* | ed29994 Reword intro
|/
*   c2c5ec0 (origin/main) Merge branch 'style-links'

Finally, Maria tests the page in her browser, deletes the merged branch (git branch -d new-intro), and runs git push.

65.5 Changing your mind: git merge --abort

If a conflict is bigger than you expected, or you are not sure which version is right, you can cancel the whole merge before you commit it:

git merge --abort

This prints nothing; your files and branch go back to exactly how they were before you ran git merge, and git status shows a clean working tree again. You can talk to your teammate, then try the merge later.

65.6 Conflicts when you pull

git pull downloads new commits and then merges them, so a teammate’s edit to the same lines produces the same kind of conflict, and you resolve it the same way (edit, git add, git commit). The only visible difference is that the bottom marker shows a long commit ID instead of a branch name, for example >>>>>>> 2d96bf5be8abfe33f58d30404c943a4cb773bfe6. Pulling in teams is covered in Sharing a Repository.

If you know you want all of one version of a conflicted file, you don’t have to edit the markers by hand. To keep your current branch’s version of the whole file:

git restore --ours src/index.html

Or, to keep the incoming branch’s version instead:

git restore --theirs src/index.html

Then git add the file and git commit as usual. During a merge, “ours” is the branch you are on and “theirs” is the branch you are merging in. (Careful: during a rebase, Git swaps these two meanings.)

Many editors, including VS Code, also highlight conflict markers and offer one-click buttons to keep one side or both. They edit the same markers for you, so the steps afterwards (git add, git commit) are the same.

  • Modify/delete: one branch deleted a file that the other branch edited. Git reports CONFLICT (modify/delete) and git status shows, for example, deleted by them: css/style.css. Resolve it by keeping the file (git add css/style.css) or deleting it (git rm css/style.css), then commit.
  • Binary files such as images: Git can’t put markers inside a picture. Pick one version with git restore --ours or --theirs, then git add.

65.7 Avoiding conflicts (and keeping them small)

  • Pull often and merge main into your branch regularly, so you find differences while they are small.
  • Keep branches short-lived and commits small and focused. A branch that lives for weeks drifts far from main.
  • Communicate. Agree on who is working on which files or features.
  • Don’t reformat whole files (or let an editor or AI do it) as part of an unrelated change. Changing the indentation of 300 lines creates 300 conflicting lines for everyone else.
  • Give parallel AI agents separate areas of the code (see Git Worktrees and Parallel AI Agents).

65.8 Getting help from Claude Code

As of Oct 6, 2026 · Official docs: Prompt library · Quickstart

Claude Code can resolve conflicts for you. The Claude Code prompt library includes this prompt:

resolve the merge conflicts in this branch and explain what you kept from each side

Claude reads both versions, edits the files, and explains its choices. That explanation matters, because the AI only sees the code: it doesn’t know which change your team actually wanted. Before you commit Claude’s resolution:

  • Read the explanation and the changes. git diff HEAD shows everything the merge will change compared with your last commit, even in files Claude has already staged. Is each choice what the authors of both branches intended?
  • Make sure no markers are left with git diff HEAD --check. (Plain git diff --check misses markers in files that have already been staged with git add, which Claude may have done.)
  • Run the app or the tests and check the result in the browser.
  • If you want to review first, say so in the prompt, for example “…but don’t commit; I’ll review it first.”

65.9 Key takeaways

  • A conflict happens when two branches change the same lines differently (or one deletes a file the other edits). Nothing is lost.
  • Between <<<<<<< HEAD and ======= is your current branch’s version; between ======= and >>>>>>> other-branch is the incoming version.
  • To resolve: edit the file, remove all markers, git add the file, then git commit.
  • git merge --abort cancels a merge that you haven’t committed yet.
  • Pull often, keep branches short, and coordinate to avoid conflicts. Review any AI-made resolution before committing.

Practice Questions

Easy

Question 1 · Multiple choice

When does Git report a merge conflict?

  1. Every time you merge two branches.
  2. When both branches changed the same lines of a file in different ways.
  3. When a branch has more than three commits.
  4. When you merge a branch that was pushed to GitHub.

b. Git merges automatically whenever the changes don’t overlap. Only overlapping changes to the same lines (or a deleted-versus-edited file) need a human decision. Most merges don’t conflict (a), and the number of commits (c) or where a branch has been pushed (d) doesn’t matter.

Question 2 · Matching

Match each part of a conflict with its meaning.

Part Meaning
1. <<<<<<< HEAD A. Separates the two versions
2. Lines between <<<<<<< HEAD and ======= B. End of the conflict, naming the branch being merged in
3. ======= C. Your current branch’s version
4. Lines between ======= and >>>>>>> D. Start of the conflict
5. >>>>>>> new-intro E. The incoming branch’s version

1 → D, 2 → C, 3 → A, 4 → E, 5 → B.

Question 3 · True or false

A merge conflict means that Git has lost part of your work.

False. Git keeps both versions and writes them into the file between conflict markers. It only needs you to decide what the final version should be.

Question 4 · Fill in the blank

After editing a conflicted file and removing the markers, you mark the file as resolved with git ______ <file> and finish the merge with git ______.

git add <file> and then git commit. Staging the file tells Git the conflict in it is resolved; the commit creates the merge commit.

Question 5 · Short answer

What does git merge --abort do, and when can you use it?

It cancels the merge in progress and puts your files and branch back exactly as they were before you ran git merge. You can use it while the merge is paused by a conflict, before you have committed the merge.

Question 6 · True or false

Maria changes line 3 of README.md on her branch, and Sam changes line 40 of the same file on his. Merging the two branches will always produce a conflict.

False. Git merges line by line. Changes to different, non-adjacent parts of the same file are combined automatically. Only overlapping changes conflict.

Medium

Question 7 · Ordering

Put these steps for handling a conflict in the right order:

  • A. Run git commit
  • B. Run git merge feature and see CONFLICT
  • C. Edit the file so it contains the right text, and delete the markers
  • D. Run git status to see which files are conflicted
  • E. Run git add on the fixed file

B → D → C → E → A. Start the merge, find the conflicted files, fix each file (removing all markers), stage it, then commit to complete the merge.

Question 8 · Read the output

Sam is on main and runs git merge price-update. Part of menu.html now looks like this:

<<<<<<< HEAD
    <p>Coffee: $3.00</p>
=======
    <p>Coffee: $3.50</p>
>>>>>>> price-update

Which price is on main, and which is on price-update? If the new price is correct, what should this part of the file look like after resolving?

$3.00 is on main (the HEAD section, between <<<<<<< and =======), and $3.50 is on price-update (between ======= and >>>>>>>). Resolved, the part should be just:

    <p>Coffee: $3.50</p>

with all three marker lines removed.

Question 9 · Write the resolution

Two teammates each added a different item at the end of the same list:

    <li>Home</li>
<<<<<<< HEAD
    <li>About</li>
=======
    <li>Contact</li>
>>>>>>> add-contact-link

Both links should stay. Write the resolved lines.

    <li>Home</li>
    <li>About</li>
    <li>Contact</li>

Combining both sides is often the right answer when both people added something useful. The markers must be gone.

Question 10 · Short answer

During a conflict, where in the output of git status do you find the conflicted files, and what label does a file get when both branches changed it?

Under the heading Unmerged paths, where each conflicted file is labeled both modified: (for example both modified: src/index.html).

Question 11 · Write the command

You think you have removed all conflict markers from your files, but you want Git to double-check before you stage them. Which command lists leftover markers?

git diff --check. It prints a line such as src/index.html:9: leftover conflict marker for each marker it finds and prints nothing when the files are clean. (Searching with grep -n "<<<<<<<" src/index.html also works.)

Question 12 · Scenario

In the middle of resolving a conflict in five files, Maria realizes she doesn’t understand Sam’s changes and wants to talk to him first. She hasn’t committed anything yet. What should she do?

Run git merge --abort. It cancels the merge and restores her branch and files to the state before the merge, so she can talk to Sam and redo the merge later.

Question 13 · Scenario

Sam runs git pull and gets a conflict. The end marker in his file reads >>>>>>> 2d96bf5be8abfe33f58d30404c943a4cb773bfe6 instead of a branch name. Why, and does he resolve it differently from a branch merge?

git pull downloads the new commits from GitHub and merges them, and Git labels the incoming side with the commit ID it is merging instead of a local branch name. The resolution is exactly the same: edit the file, remove the markers, git add it, and git commit.

Hard

Question 14 · Find the bug

After a conflict, Maria ran git add src/index.html and git commit immediately. Now her home page shows <<<<<<< HEAD and >>>>>>> new-heading as text. What went wrong, why didn’t Git stop her, and how should she fix it?

She staged and committed the file without editing it, so the conflict markers were committed as ordinary text. Git doesn’t check file contents when you run git add: staging is how you tell Git the conflict is resolved. To fix it, she edits the file to the correct text, deletes the markers, checks with git diff --check, then git add src/index.html and commits the fix (for example git commit -m "Remove leftover conflict markers").

Question 15 · Long answer

Why can’t Git simply keep the newest change when two branches edit the same line? Use an example.

Git doesn’t understand what the text means, and “newest” isn’t necessarily “right”. Example: Maria changes a price to $3.50 because of a supplier increase, and later Sam changes the same line to Coffee (large): $3.00 to add a size. Keeping only the newer line would silently undo Maria’s price change; the correct result might be Coffee (large): $3.50. Only a person who knows the intent of both changes can decide, so Git stops and asks.

Question 16 · Scenario

You asked Claude Code to “resolve the merge conflicts in this branch and explain what you kept from each side”. It says it’s done. List what you should check before committing the merge.

  • Read Claude’s explanation and the actual changes (git status, and git diff HEAD, which also covers files Claude has already staged). Does each choice match what both authors intended? The AI only sees the code, not your team’s decisions.
  • Confirm that no conflict markers are left (git diff HEAD --check, which also checks files Claude has already staged).
  • Run the app or tests and check the affected pages.
  • Only then git add and git commit (or let Claude commit after your review).

Question 17 · Long answer

Three students are building one website together. Give four habits that will reduce merge conflicts, and briefly say why each one helps.

Any four of these, with reasons:

  1. Pull often / merge main into your branch regularly - you see others’ changes early, while differences are small.
  2. Keep branches short-lived and commits small - less time to drift apart, and smaller conflicts when they happen.
  3. Agree who works on which files or features - fewer people editing the same lines.
  4. Don’t reformat whole files in unrelated changes - reformatting touches every line and conflicts with everyone.
  5. Push finished work promptly - others build on the latest version.

Question 18 · Scenario

Two AI coding sessions worked in parallel on the same website. One added a dark theme to css/style.css; the other was asked to “clean up the CSS” and re-indented and reordered the whole file. Why is merging these two branches likely to be painful, and how could it have been avoided?

The clean-up changed almost every line of css/style.css, and the dark theme also changed that file, so the two branches overlap nearly everywhere and the merge produces large conflicts that are hard to read. To avoid it: give parallel sessions separate files or areas, avoid whole-file reformatting while other work is in progress (or do it alone, merged quickly, before other branches start), and merge small changes often.

© 2025-2026 Y. Rosenthal. All rights reserved.