Merge Conflict Resolution — How to Resolve Git Conflicts
Git merge conflicts occur when two branches change the same lines differently. Here's how to read conflict markers, resolve conflicts using tools and command line, and prevent...
A merge conflict happens when two branches modify the same region of a file differently. Git can auto-merge most changes, but when two edits overlap, it marks the conflict and asks you to resolve it. Understanding the conflict format makes resolution faster.
Use the text compare tool to compare text versions when resolving conflicts manually.
What causes merge conflicts
# Branch A modifies line 5:
# function greet(name) { return "Hi " + name; }
# Branch B also modifies line 5 differently:
# function greet(name) { return `Hello, ${name}!`; }
# Merge:
git merge feature-branch
# Auto-merging greeting.js
# CONFLICT (content): Merge conflict in greeting.js
# Automatic merge failed; fix conflicts and then commit the result.
Git can auto-merge when changes are in different parts of the file. Conflicts only occur when:
- Both branches modify the same lines
- Both branches add content in the same location
- One branch deletes a file that the other branch modifies
Reading conflict markers
<<<<<<< HEAD
function greet(name) { return "Hi " + name; }
=======
function greet(name) { return `Hello, ${name}!`; }
>>>>>>> feature/template-literals
| Marker | Meaning |
|---|---|
<<<<<<< HEAD | Start of your current branch’s version |
======= | Separator between the two versions |
>>>>>>> branch-name | End of the incoming branch’s version |
Your task: replace the entire block (including markers) with the correct final code.
Three resolution choices
Keep yours (HEAD): Delete the incoming version and markers:
function greet(name) { return "Hi " + name; }
Keep theirs: Delete your version and markers:
function greet(name) { return `Hello, ${name}!`; }
Combine both: Write a new version that incorporates both changes:
// Use template literal syntax (both teams wanted improvement):
function greet(name) { return `Hello, ${name}!`; }
Most conflicts require the “combine” approach — understanding what both branches were trying to do.
Resolving conflicts from command line
# 1. See which files have conflicts:
git status
# both modified: src/greeting.js
# 2. Open the conflicting file in your editor and fix it
# Remove conflict markers, keep correct code
# 3. Stage the resolved file:
git add src/greeting.js
# 4. Check all conflicts are resolved:
git status
# All conflicts fixed but you are still merging.
# (use "git commit" to conclude merge)
# 5. Complete the merge:
git commit
# Git pre-fills a merge commit message
# OR abort if you made a mistake:
git merge --abort # Returns to pre-merge state
VS Code conflict resolution
VS Code shows conflict markers with clickable options:
Accept Current Change | Accept Incoming Change | Accept Both Changes | Compare Changes
- Accept Current Change: Keep your version (HEAD)
- Accept Incoming Change: Keep their version
- Accept Both Changes: Append both versions (rarely what you want)
- Compare Changes: Open side-by-side diff view
In the Source Control panel, files with conflicts show a C badge.
Three-way merge (base comparison)
Standard merge shows two versions. A three-way merge shows three:
- Ours: Current branch
- Theirs: Incoming branch
- Base: Common ancestor (what both branches started from)
# Open three-way merge tool:
git mergetool
# or with VS Code as the tool:
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
git mergetool
Seeing the base version often makes conflicts clearer: you can see what each branch changed and why.
Preventing merge conflicts
Frequent integration
# Rebase your branch on main regularly:
git fetch origin
git rebase origin/main
# This moves your commits on top of the latest main,
# preventing large divergences that cause more conflicts
Small, focused commits
Large changes touching many files are more likely to conflict. Small commits that change one thing have less overlap with other work.
Communicate about shared code
If you know you’ll be changing a core module, coordinate with others working in the same area. It’s faster to align upfront than resolve conflicts after.
Use lock files
For dependency files (package-lock.json, Gemfile.lock, poetry.lock), conflicts are common but mechanical. Always regenerate lock files after merging rather than manually resolving the conflicts:
# After resolving package.json conflicts:
rm package-lock.json
npm install # Regenerates lock file cleanly
# Then add and commit:
git add package-lock.json
git commit
Common conflict patterns and how to resolve them
Conflicting imports
<<<<<<< HEAD
import { UserService } from './services/user.service';
import { AuthService } from './services/auth.service';
=======
import { UserService } from './services/user.service';
import { EmailService } from './services/email.service';
>>>>>>> feature/email-notifications
Resolution: Keep both new imports (both are needed):
import { UserService } from './services/user.service';
import { AuthService } from './services/auth.service';
import { EmailService } from './services/email.service';
Conflicting function signatures
<<<<<<< HEAD
def process_user(user_id: int, notify: bool = False):
=======
def process_user(user_id: int, email: str = None):
>>>>>>> feature/email-support
Resolution: Combine parameters:
def process_user(user_id: int, notify: bool = False, email: str = None):
Conflicting version numbers
<<<<<<< HEAD
"version": "1.2.0"
=======
"version": "1.3.0"
>>>>>>> release/1.3
Resolution: Keep the higher version (or discuss with team):
"version": "1.3.0"
Database migration conflicts
Conflicts in sequential migration numbers require special handling:
migrations/
0042_add_users_index.py ← Your branch
0042_add_orders_table.py ← Their branch (same number!)
Resolution: Renumber one migration:
migrations/
0042_add_users_index.py
0043_add_orders_table.py ← Renumber and update dependencies
Related tools
- Text Diff — compare text versions
- Text Compare Online — compare text side by side
- Diff Algorithm Explained — how diffs work
Related posts
- How Diff Tools Work: Myers Algorithm, Unified Format, and Merge Conflicts — A technical walkthrough of how diff works: the Myers algorithm, the three output…
- Diff Algorithm Explained — How Text Comparison Tools Work — Text diff tools use the LCS (Longest Common Subsequence) or Myers diff algorithm…
- Understanding Merge Conflicts — How 3-Way Diff Works — Merge conflicts occur when two branches edit the same lines differently. Learn h…
- Text Compare Online — Find Differences Between Two Texts — Text comparison highlights added, removed, and changed lines between two text bl…
Related tool
Compare two text blocks line-by-line or word-by-word. Unified and split view. Shows added, removed, and changed segments with full color coding.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.