Git Conflicts
This file provides comprehensive guidance on understanding, preventing, and resolving Git merge conflicts.
Understanding Git Conflicts​
What are Git Conflicts?​
Git conflicts occur when Git cannot automatically merge changes from different branches or commits. This happens when:
- The same line in a file has been modified differently in two branches
- One branch deletes a file that another branch modifies
- Binary files are modified in both branches
Types of Conflicts​
Content Conflicts​
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
Rename/Delete Conflicts​
CONFLICT (modify/delete): file.txt deleted in branch-a and modified in HEAD.
Add/Add Conflicts​
CONFLICT (add/add): Merge conflict in file.txt
Identifying Conflicts​
Check Status​
# See which files have conflicts
git status
# Output will show:
# Unmerged paths:
# (use "git add <file>..." to mark resolution)
# both modified: src/main.js
# deleted by us: old-file.txt
# added by them: new-file.txt
View Conflict Markers​
When Git encounters a conflict, it marks the conflicting sections in the file:
<<<<<<< HEAD (Current Change)
const message = "Hello from main branch";
=======
const message = "Hello from feature branch";
>>>>>>> feature-branch (Incoming Change)
Preventing Conflicts​
Best Practices​
Keep Branches Short-Lived​
# Create feature branch
git checkout -b feature/quick-fix
# Make changes and merge quickly
git checkout main
git merge feature/quick-fix
git branch -d feature/quick-fix
Regular Synchronization​
# Frequently pull from main
git checkout main
git pull origin main
# Rebase feature branch regularly
git checkout feature-branch
git rebase main
Coordinate Team Changes​
- Communicate about files being modified
- Use separate files/modules when possible
- Plan refactoring activities together
- Use feature flags for large changes
Use .gitattributes for Binary Files​
# .gitattributes
*.png binary
*.jpg binary
*.pdf binary
*.docx binary
Resolving Conflicts​
Manual Resolution​
Step 1: Identify Conflicted Files​
git status
# or
git diff --name-only --diff-filter=U
Step 2: Open and Edit Files​
// Before resolution
function greet() {
<<<<<<< HEAD
return "Hello from main!";
=======
return "Hello from feature!";
>>>>>>> feature-branch
}
// After resolution
function greet() {
return "Hello from merged version!";
}
Step 3: Mark as Resolved​
# Add the resolved file
git add src/main.js
# Check status
git status
Step 4: Complete the Merge​
# Commit the merge
git commit -m "Resolve merge conflicts in src/main.js"
# Or continue rebase
git rebase --continue
Using Merge Tools​
Configure Merge Tool​
# Set up VS Code as merge tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# Set up Beyond Compare
git config --global merge.tool bc3
git config --global mergetool.bc3.path "C:/Program Files/Beyond Compare 4/bcomp.exe"
# Set up P4Merge
git config --global merge.tool p4merge
git config --global mergetool.p4merge.path "/Applications/p4merge.app/Contents/MacOS/p4merge"
Use Merge Tool​
# Launch merge tool for conflicts
git mergetool
# This will open your configured tool with three panels:
# - LOCAL (your changes)
# - BASE (common ancestor)
# - REMOTE (their changes)
# - MERGED (result)
IDE Integration​
VS Code​
- Install GitLens extension
- Open conflicted file
- Use "Accept Current Change", "Accept Incoming Change", or "Accept Both Changes"
- Edit manually if needed
- Save file and stage changes
IntelliJ IDEA​
- Go to VCS → Git → Resolve Conflicts
- Select conflicted files
- Use the merge dialog with three panels
- Choose changes to accept or edit manually
- Click "Apply" to resolve
Advanced Conflict Resolution​
Interactive Rebase​
# Start interactive rebase
git rebase -i HEAD~3
# In the editor, choose actions:
pick abc123 First commit
edit def456 Second commit (has conflicts)
pick ghi789 Third commit
# When conflicts occur during rebase:
# 1. Resolve conflicts
# 2. git add resolved-files
# 3. git rebase --continue
Cherry-pick Conflicts​
# Cherry-pick commit with conflicts
git cherry-pick abc123
# Resolve conflicts
git add .
git cherry-pick --continue
# Or abort cherry-pick
git cherry-pick --abort
Merge vs Rebase Conflicts​
Merge Strategy​
git checkout feature-branch
git merge main
# Conflicts appear, resolve them
git add .
git commit -m "Merge main into feature-branch"
Rebase Strategy​
git checkout feature-branch
git rebase main
# Conflicts appear for each commit
# Resolve conflicts for first commit
git add .
git rebase --continue
# Repeat for each conflicted commit
Conflict Resolution Strategies​
Taking One Side Completely​
# Take your version (current branch)
git checkout --ours conflicted-file.txt
# Take their version (incoming branch)
git checkout --theirs conflicted-file.txt
# For entire merge, prefer one side
git merge -X ours feature-branch
git merge -X theirs feature-branch
Partial Resolution​
// Original conflict
function calculateTotal(items) {
<<<<<<< HEAD
return items.reduce((sum, item) => sum + item.price, 0);
=======
return items.reduce((sum, item) => sum + item.cost, 0);
>>>>>>> feature-branch
}
// Resolution combining both approaches
function calculateTotal(items) {
return items.reduce((sum, item) => sum + (item.price || item.cost), 0);
}
Complex Conflicts​
For files with multiple conflict sections:
# Show all conflicts in file
git diff conflicted-file.txt
# Use pattern to find conflicts
grep -n "<<<<<<< HEAD" src/**/*.js
Aborting and Resetting​
Abort Operations​
# Abort merge
git merge --abort
# Abort rebase
git rebase --abort
# Abort cherry-pick
git cherry-pick --abort
# Reset to before merge attempt
git reset --hard HEAD~1
Emergency Reset​
# Find the commit hash before the problematic merge
git reflog
# Reset to that commit
git reset --hard abc123
# Force push if already pushed (DANGEROUS)
git push --force-with-lease origin branch-name
Binary File Conflicts​
Understanding Binary Conflicts​
# Git cannot merge binary files automatically
warning: Cannot merge binary files: image.png (HEAD vs. feature-branch)
Resolving Binary Conflicts​
# Choose version from current branch
git checkout --ours image.png
# Choose version from incoming branch
git checkout --theirs image.png
# Add resolved file
git add image.png
Preventing Binary Conflicts​
- Use version control for source files, not generated files
- Store binary assets in separate repositories
- Use Git LFS for large binary files
- Coordinate binary file changes in team
Team Workflows​
Conflict Resolution in Pull Requests​
GitHub Workflow​
- Create pull request
- If conflicts exist, GitHub will show "This branch has conflicts"
- Options:
- Resolve conflicts in GitHub web interface
- Resolve locally and push
Local Resolution for PR​
# Sync with target branch
git checkout main
git pull origin main
# Switch to feature branch
git checkout feature-branch
# Rebase or merge to resolve conflicts
git rebase main
# or
git merge main
# Push resolved changes
git push origin feature-branch
Code Review with Conflicts​
- Resolve conflicts before requesting review
- Document complex resolution decisions
- Consider splitting large conflicted changes
- Use pair programming for complex merges
Automated Conflict Resolution​
Git Rerere​
# Enable rerere (reuse recorded resolution)
git config --global rerere.enabled true
# Git will remember how you resolved similar conflicts
# and automatically apply the same resolution
Custom Merge Drivers​
# .gitattributes
*.generated merge=ours
# .git/config
[merge "ours"]
driver = true
Troubleshooting​
Common Issues​
"Already up to date" but conflicts exist​
# Check if you're on the right branch
git branch
# Verify remote is up to date
git fetch origin
# Check for uncommitted changes
git status
Conflicts keep reappearing​
# Check if rerere is causing issues
git config --get rerere.enabled
# Clear rerere cache
rm -rf .git/rr-cache
# Check for automatic merge/rebase tools
git config --get-regexp merge
Lost changes during conflict resolution​
# Check reflog for lost commits
git reflog
# Recover lost changes
git checkout abc123
# Create new branch from recovered commit
git checkout -b recovery-branch abc123
Best Practices Summary​
-
Prevention
- Keep branches small and short-lived
- Regular synchronization with main branch
- Good communication within team
- Use appropriate .gitattributes
-
Resolution
- Understand the conflict before resolving
- Test the resolution thoroughly
- Document complex resolution decisions
- Use appropriate tools (merge tools, IDE integration)
-
Team Process
- Resolve conflicts before code review
- Coordinate on large refactoring efforts
- Use consistent merge strategies
- Train team members on conflict resolution
Emergency Contacts​
- For critical production merges: Contact senior developer or team lead
- For complex architectural conflicts: Involve system architect
- For data-related conflicts: Involve database administrator
Remember: When in doubt, ask for help rather than risk introducing bugs through incorrect conflict resolution!