How do I resolve merge conflicts in a Git repository?
Git merge conflicts occur when Git cannot automatically merge changes from different branches because both modified the same parts of files. To resolve merge conflicts, you need to manually edit the conflicted files to accept or combine changes, then mark them as resolved and complete the merge process.
Contents
- What Are Git Merge Conflicts?
- How to Detect Merge Conflicts
- Step-by-Step Conflict Resolution Process
- Advanced Conflict Resolution Techniques
- Best Practices for Avoiding Merge Conflicts
What Are Git Merge Conflicts?
A Git merge conflict happens when you try to combine changes from different branches that have modified the same lines of code in the same file. When this occurs, Git cannot automatically determine which changes should take precedence, so it pauses the merge process and requires manual intervention.
Key Insight: Merge conflicts are actually a feature, not a bug - they protect your codebase from accidental overwrites and ensure you consciously decide how to combine changes.
Common scenarios that cause merge conflicts include:
- Multiple developers editing the same function or method
- Changes to shared configuration files
- Modifications to database schemas
- Updates to documentation sections
Understanding the root cause helps you approach conflicts systematically rather than viewing them as frustrating obstacles.
How to Detect Merge Conflicts
When you attempt a merge and conflicts arise, Git provides several indicators:
Command Line Signs
- The merge command will fail with an error message
- Files with conflicts will be marked with
<<<<<<<,=======, and>>>>>>>markers - The
git statuscommand will show conflicted files in the “Unmerged paths” section
Visual Indicators
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
Changes to be committed:
modified: src/components/Header.js
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: src/utils/helpers.js
IDE Integration
Most modern IDEs (VS Code, IntelliJ, WebStorm) automatically detect and highlight merge conflicts within the editor interface, often with visual markers and side-by-side comparison views.
The git mergetool command can launch a visual merge tool configured in your Git setup, which provides an interactive interface for resolving conflicts.
Step-by-Step Conflict Resolution Process
Step 1: Identify Conflicted Files
Start by checking which files have conflicts using:
git status
This will show you all files that need manual resolution before you can complete the merge.
Step 2: Open and Examine Conflicted Files
Open each conflicted file in your text editor or IDE. You’ll see markers like this:
<<<<<<< HEAD
// Your current branch changes
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
=======
// Changes from the branch you're merging
function calculateTotal(items) {
const taxRate = 0.08;
return items.reduce((sum, item) => sum + item.price * (1 + taxRate), 0);
}
>>>>>>> feature/tax-calculation
Step 3: Resolve the Conflict
You have several options for resolving conflicts:
Option A: Keep Your Changes (HEAD)
Remove the markers and keep only the content from HEAD:
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
Option B: Keep Incoming Changes
Remove the markers and keep only the content from the branch you’re merging:
function calculateTotal(items) {
const taxRate = 0.08;
return items.reduce((sum, item) => sum + item.price * (1 + taxRate), 0);
}
Option C: Combine Changes (Manual Merge)
Manually merge both sets of changes:
function calculateTotal(items) {
const taxRate = 0.08;
return items.reduce((sum, item) => sum + item.price * (1 + taxRate), 0);
}
Option D: Use Git’s Automatic Merge Tools
Launch a visual merge tool:
git mergetool
This opens configured tools like meld, p4merge, or IDE-specific merge tools.
Step 4: Mark Files as Resolved
After editing conflicted files, mark them as resolved by adding them to the staging area:
git add <resolved-file>
Step 5: Complete the Merge
Once all conflicts are resolved and marked, complete the merge with:
git commit
Git will automatically create a merge commit with a message indicating the resolution.
Advanced Conflict Resolution Techniques
Using Git Add -p for Partial Resolution
For large files with multiple conflicts, use interactive staging:
git add -p <file>
This allows you to stage changes chunk by chunk, giving you fine-grained control over what gets included in the merge.
Abort a Problematic Merge
If you encounter issues during resolution, you can abort the merge and return to the pre-merge state:
git merge --abort
Continue After Partial Resolution
If you’ve resolved some conflicts but not all, you can continue the process:
git merge --continue
Using Third-Party Merge Tools
Configure advanced merge tools in your Git configuration. For example, to use vimdiff:
git config --global merge.tool vimdiff
git config --global mergetool.vimdiff.cmd 'vimdiff -c "set wrap" $LOCAL $BASE $REMOTE $MERGED'
git config --global mergetool.trustexitcode false
Recursive Merge Strategy
For complex merges, specify a merge strategy:
git merge -s recursive -Xours feature-branch
This tells Git to prefer changes from the current branch (-Xours) when conflicts arise.
Interactive Rebase Before Merging
Sometimes it’s better to rebase before merging to create a linear history:
git checkout feature-branch git rebase main git checkout main git merge feature-branch
Best Practices for Avoiding Merge Conflicts
Regular Pulls and Commits
- Pull changes frequently from the main branch
- Make small, frequent commits rather than large, infrequent ones
- Keep feature branches up-to-date with regular rebases
Clear Branch Strategy
- Use feature branches for new development
- Avoid long-lived feature branches
- Consider Git flow or GitHub flow workflows
Communication and Coordination
- Communicate with team members about overlapping work
- Use pull requests with clear descriptions
- Review code changes before merging
Use Atomic Commits
Make commits that represent single, logical changes:
- One commit per feature
- One commit per bug fix
- One commit per refactoring
Pre-commit Hooks
Set up pre-commit hooks to run tests and linting:
husky # or custom git hooks
Use .gitattributes
Configure Git to handle specific files appropriately:
*.png binary
*.jpg binary
*.md text=auto
Conflict Prevention Tools
Consider using tools like:
- Merge driver configurations
- Git LFS (Large File Storage) for binary files
- Git submodules for managing dependencies
Conclusion
Resolving Git merge conflicts is an essential skill for collaborative development work. By following the systematic approach outlined above, you can efficiently handle conflicts when they arise and minimize their impact on your workflow.
Key Takeaways:
- Understand the conflict - Examine the markers and understand what changes are conflicting
- Choose the right resolution strategy - Decide whether to keep your changes, incoming changes, or combine them
- Use appropriate tools - Leverage both command-line and visual merge tools as needed
- Prevent future conflicts - Follow best practices for regular communication and coordination
- Practice regularly - The more you resolve conflicts, the more comfortable you’ll become with the process
Remember that merge conflicts are a natural part of collaborative development. By approaching them systematically and using the right tools, you can turn potential frustration into an opportunity to carefully consider how changes should be integrated into your codebase.
For ongoing learning, explore Git’s merge strategies, conflict drivers, and advanced workflow patterns. The Git documentation and community resources provide excellent guidance for mastering these essential skills.