Skip to main content

Conflict Resolution

Quick Summary

A merge conflict occurs when Git can't automatically combine changes because two branches modified the same lines of the same file. Conflicts aren't errors — they're Git asking you to make a decision. Understanding the process makes them routine instead of scary.


Why Conflicts Happen

flowchart TD
A["main: line 10 = 'Hello World'"] --> B["Branch A changes line 10 to 'Hello Git'"]
A --> C["Branch B changes line 10 to 'Hello GitHub'"]
B --> D["Merge: CONFLICT!<br/>Which version should line 10 use?"]
C --> D
ScenarioConflict?
Two branches edit different files❌ No — auto-merged
Two branches edit different lines of the same file❌ No — auto-merged
Two branches edit the same line of the same file✅ Yes — conflict
One branch deletes a file, the other modifies it✅ Yes — conflict
Both branches add a file with the same name✅ Yes — conflict

Reading Conflict Markers

When a conflict occurs, Git marks the affected sections in the file:

<<<<<<< HEAD
const greeting = "Hello Git";
=======
const greeting = "Hello GitHub";
>>>>>>> feature/github
MarkerMeaning
<<<<<<< HEADStart of your changes (current branch)
=======Divider between the two versions
>>>>>>> feature/githubEnd of their changes (incoming branch)

Three-Way Conflict (with diff3)

Enable the diff3 style for even clearer conflict markers:

git config --global merge.conflictstyle diff3
<<<<<<< HEAD
const greeting = "Hello Git";
||||||| common ancestor
const greeting = "Hello World";
=======
const greeting = "Hello GitHub";
>>>>>>> feature/github

Now you see the original version too, making the intent of each change much clearer.


Step-by-Step Resolution

1. Identify Conflicted Files

git status
On branch main
You have unmerged paths.

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

2. Open and Resolve Each File

Open the file, find the conflict markers, and edit to the desired result:

// Before: conflict markers
<<<<<<< HEAD
const greeting = "Hello Git";
=======
const greeting = "Hello GitHub";
>>>>>>> feature/github

// After: your resolution (remove ALL markers)
const greeting = "Hello Git and GitHub";

3. Mark as Resolved

git add src/app.js
git add src/config.js

4. Complete the Merge

git commit
# Git auto-generates a merge commit message

Or if you want a custom message:

git commit -m "Merge feature/github: resolve greeting conflict"

Abort the Merge

# Cancel the entire merge and go back to before
git merge --abort

Conflict Resolution Strategies

StrategyWhen to Use
Keep ours (--ours)Your version is correct, theirs is outdated
Keep theirs (--theirs)Their version is correct, yours is outdated
Manual editBoth changes are partially correct — combine them
Accept bothBoth changes are independent additions
Rewrite entirelyNeither version is optimal — write something new

Common Conflict Scenarios

Scenario 1: Both Edit the Same Function

<<<<<<< HEAD
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price * item.qty, 0);
}
=======
function calculateTotal(items) {
const subtotal = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
return subtotal * 1.1; // Add 10% tax
}
>>>>>>> feature/tax

Resolution: Combine both changes:

function calculateTotal(items) {
const subtotal = items.reduce((sum, item) => sum + item.price * item.qty, 0);
return subtotal * 1.1; // Add 10% tax
}

Scenario 2: Delete vs Modify Conflict

CONFLICT (modify/delete): src/legacy.js deleted in feature/cleanup
and modified in HEAD. Version HEAD of src/legacy.js left in tree.

Resolution: Decide whether the file should exist. Then:

# Keep the file
git add src/legacy.js

# Or delete it
git rm src/legacy.js

Preventing Conflicts

PracticeHow It Helps
Pull frequentlyStay up-to-date with main, reducing divergence
Small, focused branchesLess code changed = fewer potential conflicts
Communicate with teamAvoid working on the same files simultaneously
Use feature flagsChanges can coexist without modifying the same lines
Rebase before mergeResolves conflicts earlier, one commit at a time

Troubleshooting

ProblemCauseFix
Can't find conflict markersEditor hid them or wrong fileSearch for <<<<<<< in the file
Merge commit has wrong resolutionResolved incorrectlygit revert <merge-commit>, then re-merge
Conflicts in binary filesGit can't diff binariesChoose one version: git checkout --ours/--theirs <file>
Too many conflicts to resolveMassive branch divergenceConsider rebasing commit-by-commit

Best Practices

  • Enable diff3 conflict style — seeing the common ancestor makes resolution much easier
  • Use a visual merge tool — VS Code, IntelliJ, or git mergetool
  • Pull/rebase regularly — smaller, more frequent syncs = smaller conflicts
  • Don't panic — conflicts are normal; git merge --abort is always available
  • Test after resolving — run your tests before committing the resolution

What's Next

  1. Remotes, Push, Pull & Fetch — Work with remote repositories
  2. Undoing Changes — Undo commits, staged changes, and merges