Merge conflicts are an inevitable part of collaborative software development. When working with Claude Code, understanding how to resolve these conflicts efficiently can significantly boost your productivity. This guide provides practical strategies and commands for handling merge conflicts in any project.
Understanding Merge Conflicts in Git
A merge conflict occurs when Git cannot automatically combine changes from two branches. This typically happens when the same lines of code were modified in different ways, or when one branch deleted a file while another modified it.
When Claude Code helps you with git operations, it will notify you when conflicts arise. The tool will present conflict markers in affected files, showing you exactly where manual intervention is needed.
Common Conflict Scenarios
1. Same Line Modified
The most frequent conflict happens when both branches modify the same line:
// In your feature branch
export function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// In main branch
export function calculateTotal(items, taxRate = 1.0) {
return items.reduce((sum, item) => sum + item.price * taxRate, 0);
}
2. File Deleted on One Branch
Another common scenario involves deleted files:
$ git merge feature/remove-utils
# CONFLICT (modify/delete): utils/helper.js deleted in feature/remove-utils
# and modified in main.
3. Both Branches Add Similar Code
When two developers add similar functionality independently:
# Feature A adds
class Logger:
def log(self, message):
print(f"[INFO] {message}")
# Feature B adds
class Logger:
def log(self, message):
print(f"[LOG] {message}")
Resolution Strategies with Claude Code
Strategy 1: Accept Current or Incoming Changes
For simple conflicts, you can quickly choose one version:
# Keep your changes (current branch)
git checkout --ours filename.ext
# Keep incoming changes (branch being merged)
git checkout --theirs filename.ext
After choosing, stage the file and commit:
git add filename.ext
git commit -m "Resolve conflict: accepted incoming changes"
Strategy 2: Manual Resolution with Editor
For complex conflicts, manually edit the file to combine changes intelligently:
// <<<<<<< feature/user-auth
function authenticateUser(email, password) {
return bcrypt.compare(password, getHash(email));
}
// =======
function authenticateUser(email, password, totpCode) {
const valid = bcrypt.compare(password, getHash(email));
return valid && verifyTOTP(email, totpCode);
}
// >>>>>>> main
Remove the conflict markers and keep the desired logic:
function authenticateUser(email, password, totpCode = null) {
const valid = bcrypt.compare(password, getHash(email));
if (!valid) return false;
if (totpCode) {
return verifyTOTP(email, totpCode);
}
return true;
}
Strategy 3: Abort and Reattempt
If conflicts are extensive, abort and restructure your approach:
# Abort the merge
git merge --abort
# Alternatively, abort a rebase
git rebase --abort
Then rebase your branch onto the latest main:
git fetch origin
git rebase origin/main
Preventing Conflicts
Use Feature Branches
Always work in feature branches and keep them small and focused. This reduces the likelihood of conflicts. Large, long-lived branches accumulate changes from multiple team members, making conflicts more likely and more complex to resolve.
When creating a new branch, use descriptive names:
git checkout -b feature/user-authentication
git checkout -b fix/login-validation
git checkout -b chore/update-dependencies
Sync Frequently
Pull from main regularly to stay current with the latest changes:
git pull origin main
# or if using rebase
git pull --rebase origin main
Frequent synchronization catches conflicts early, when they’re easier to resolve. Waiting weeks or months between syncs guarantees painful merge sessions.
Communicate with Team
When working on shared files, communicate with teammates to coordinate changes. A quick message in Slack or a team chat prevents duplicate work:
Hey, I'm working on the auth module. Any plans to touch user-service.js?
Break Up Large Changes
Instead of one massive commit, break changes into logical pieces:
# Instead of one huge PR with 50 files
# Split into multiple focused PRs
git checkout -b feature/auth-types
git checkout -b feature/auth-validation
git checkout -b feature/auth-api
This approach reduces conflict surface area and makes code reviews more manageable.
Working with Conflict Markers
Git marks conflicts with special delimiters. Understanding these markers helps you navigate resolution:
Incoming changes from the branch being merged
The <<<<<<< HEAD section shows your current branch. The ======= line separates your changes from the incoming changes. The >>>>>>> branch-name marks the end of the conflict section.
Finding All Conflicts
Quickly locate all conflicted files:
# List all files with conflicts
git diff --name-only --diff-filter=U
# Show conflict status
git status
Using Git Mergetool
Launch your configured merge tool:
# Open merge tool for all conflicts
git mergetool
# Configure a specific tool
git config merge.tool vscode
git config merge.tool 'code --wait'
The mergetool provides a visual interface for resolving conflicts, showing three panes: yours, theirs, and the result.
Using Claude Skills
Several Claude skills can assist with merge conflict workflows. The tdd skill helps verify that resolved conflicts don’t break existing tests. After resolving conflicts, run tests to ensure everything works correctly:
claude "Run the test suite to verify the merge resolved correctly"
The frontend-design skill is useful when conflicts involve UI components, helping you maintain design consistency. The pdf skill can generate documentation about conflict resolution decisions for team records.
For teams using supermemory, conflict resolution notes can be stored and referenced for future similar situations. The docx skill helps create detailed reports about complex resolutions for stakeholder communication.
Post-Resolution Checklist
After resolving conflicts, always verify:
- Run tests:
npm testor your test command - Check linting:
npm run lint - Verify build:
npm run build - Review changes:
git diff --stat - Stage resolved files:
git add . - Complete the merge:
git commit
Verify No Conflicts Remain
# Ensure no unmerged files remain
git status
# If any remain, address them before committing
git diff --name-only --diff-filter=U
Advanced Techniques
Squash Merges to Reduce Conflicts
Using squash merges creates a cleaner history:
git merge --squash feature/my-feature
git commit -m "Add user authentication feature"
This technique combines all commits from your branch into one, reducing future conflict opportunities.
Merge vs Rebase Strategy
Choose the right strategy for your workflow:
# Merge preserves history but can create more merge commits
git merge origin/main
# Rebase creates linear history but rewrites commits
git rebase origin/main
Teams often prefer rebase for feature branches to maintain a clean, linear commit history.
Conclusion
Merge conflicts are a normal part of development. With Claude Code and the strategies outlined in this guide, you can resolve conflicts efficiently while maintaining code quality. Remember to communicate with your team, keep branches small, and always verify your resolutions with tests. Using skills like tdd for validation and supermemory for documentation creates a robust workflow that scales with your team.
Related Reading
- Claude Code for End of Day Commit Workflow — Clean commit habits reduce merge conflicts
- Claude TDD Skill: Test-Driven Development Workflow — Tests validate that conflict resolutions are correct
- Claude Skills Workflows Hub — More git and development workflow guides
Built by theluckystrike — More at zovo.one