Handling Merge Conflicts
What is a Merge Conflict?
A merge conflict occurs when Git cannot automatically resolve differences between two commits during a merge or pull. This happens when:
- The same line was edited differently in two branches
- One branch deleted a file that another branch modified
- Two branches added different files with the same name
When Conflicts Occur
Merge conflicts happen during:
git merge- merging one branch into anothergit pull- pulling remote changes (which is fetch + merge)git rebase- rebasing onto another branchgit cherry-pick- applying commits from one branch to another
Identifying Conflicts
Git Status
git status
Output during a conflict:
On branch main
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: app.js
both modified: config.json
Conflict Markers
When you open a conflicted file, you'll see conflict markers:
// ... existing code ...
<<<<<<< HEAD
// This is your current branch's version
const API_URL = 'https://api.example.com';
const TIMEOUT = 5000;
=======
// This is the incoming branch's version
const API_URL = 'https://api.new.com';
const TIMEOUT = 10000;
>>>>>>> feature-update
// ... more code ...
Understanding Markers
<<<<<<< HEAD- Start of your current branch's changes=======- Separator between your changes and incoming changes>>>>>>> branch-name- End of incoming branch's changes
Resolving Conflicts
Manual Resolution
- Open the conflicted file(s)
- Choose which version to keep:
const API_URL = 'https://api.example.com';
const TIMEOUT = 5000;
- Or keep their version:
const API_URL = 'https://api.new.com';
const TIMEOUT = 10000;
- Or combine both:
const API_URL = 'https://api.example.com';
const NEW_API_URL = 'https://api.new.com';
const TIMEOUT = 10000; // Use the larger timeout
Step-by-Step Conflict Resolution
# 1. Check status to see conflicted files
git status
# 2. Edit each conflicted file (remove markers, keep desired code)
vim app.js
vim config.json
# 3. Stage the resolved files
git add app.js config.json
# 4. Complete the merge
git commit -m "Resolve merge conflicts"
Conflict Resolution Tools
Using VSCode
VSCode provides built-in conflict resolution:
- "Accept Current Change" - Keep your version
- "Accept Incoming Change" - Keep their version
- "Accept Both Changes" - Keep both versions
- "Compare Changes" - See differences side-by-side
Command Line Tools
git mergetool
This opens your configured merge tool (like Meld, KDiff3, etc.)
git diff
Shows conflict markers with surrounding context.
Conflict Resolution Strategies
Strategy 1: Interactive Resolution
# See list of conflicts
git diff --name-only --diff-filter=U
# Resolve each file
git add file1.js
git add file2.js
# Complete merge
git commit -m "Resolve conflicts"
Strategy 2: Use Ours or Theirs
git checkout --ours path/to/file
git add path/to/file
# Or use their version
git checkout --theirs path/to/file
git add path/to/file
Strategy 3: Abort and Restart
git merge --abort
git rebase --abort
There is no git pull --abort — a conflicted pull is just a conflicted merge (or rebase, if you pulled with --rebase), so cancel it with git merge --abort or git rebase --abort accordingly.
Practical Conflict Examples
Example 1: Conflicting Line Changes
Your branch (main):
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000
};
Incoming branch (feature-update):
const config = {
apiUrl: 'https://api.new.com',
timeout: 10000
};
Conflict in file:
<<<<<<< HEAD
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000
};
=======
const config = {
apiUrl: 'https://api.new.com',
timeout: 10000
};
>>>>>>> feature-update
Resolution - communicate with team:
const config = {
apiUrl: process.env.API_URL || 'https://api.example.com',
timeout: 10000 // Higher timeout is safer
};
Example 2: Deleted vs Modified
Your branch: Deleted a file Their branch: Modified the same file
# Decide: should the file exist?
git rm path/to/file # Delete it
# OR
git add path/to/file # Keep it
Example 3: Both Added Same File
Two branches added different new files:
git ls-files
# One of the files might have conflict markers
# Open and verify you want both files
git add new-file1.js new-file2.js
Preventing Conflicts
1. Communication
- Discuss with team which files you'll edit
- Use feature branches for different features
- Avoid editing the same lines simultaneously
2. Frequent Pulls
git pull origin main
Run this regularly — it brings in changes early, making conflicts smaller and easier to resolve.
3. Proper Branching Strategy
git checkout main
git pull origin main
git checkout -b feature/my-feature
Always start from an updated main branch.
4. Review Changes Before Merge
git log main..feature-branch
git diff main...feature-branch
Understand what you're merging before doing it.
5. Small, Focused Changes
- Make changes to different parts of the codebase
- Avoid massive refactors without team coordination
- Create specific feature branches instead of long-running branches
Best Practices During Conflicts
# 1. Keep your changes safe
git stash push -m "my current work"
# 2. Try the merge
git merge feature-branch
# 3. If conflicts arise
git status # See which files conflict
# 4. Resolve conflicts carefully
# - Read the code, understand both sides
# - Don't just delete one side without thinking
# - Test the resolved code
# 5. Mark as resolved and complete merge
git add resolved-files
git commit -m "Resolve conflicts and merge feature-branch"
# 6. Run tests to verify
npm test
Conflict Resolution Checklist
When resolving conflicts:
- Understand what each change is trying to do
- Verify the resolution makes logical sense
- Remove all conflict markers (
<<<<<<<,=======,>>>>>>>) - Test the resolved code if possible
- Run automated tests (linting, tests)
- Stage the resolved files with
git add - Commit with a clear message explaining the resolution
Understanding Conflict Causes
git log --oneline main..feature-branch
# See what commits are in feature-branch
git show <commit-hash>
# See what that specific commit changed
git blame conflicted-file.js
# See who changed each line
Using Git Attributes
Create .gitattributes to handle conflicts better:
# Don't merge binary files
*.png merge=binary
*.jpg merge=binary
# Union merge for specific files
package.json merge=union
Key Takeaways
- Merge conflicts are normal and manageable
- Always read conflict markers carefully before resolving
- Test your resolution before committing
- Communicate with team to prevent conflicts
- Use version control to understand who made what changes
- Small, focused changes reduce conflict frequency
- Frequently pull/update to catch conflicts early
- When in doubt, ask your team about the right resolution
Common Mistakes to Avoid
❌ Don't: Just delete one side without understanding it ✅ Do: Read both versions and think about what's needed
❌ Don't: Resolve conflicts without testing ✅ Do: Verify the resolved code works correctly
❌ Don't: Keep working on a branch while main changes significantly ✅ Do: Regularly pull main into your feature branch
❌ Don't: Create conflicts through poor communication ✅ Do: Discuss major refactors with your team first