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
git pull --abort
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 regularly
This brings in changes early, making conflicts smaller.
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 save "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