Appearance
Conflict Resolution
Strategies for resolving merge conflicts thoughtfully, preserving the intent of all commits involved.
When to use
Use these strategies when a merge or rebase produces conflicts — the goal is always to resolve them while retaining the intent from all conflicting versions:
| Strategy | Use when |
|---|---|
| Simple merge | Intent is clear from the conflict markers alone |
| Patch replay | Conflicts are widespread; a clean slate preserves intent best |
| Commit replay | Conflicts are isolated; per-commit replay preserves intent best |
The pattern
General principles
- Understand before resolving — Don't just pick one side
- Preserve intent — Honor what each commit was trying to accomplish
- Test after resolution — Verify the merged result actually works
- Clear commit messages — Explain how you preserved both sides
Simple merge
Deal with merge conflicts thoughtfully — think hard about what's happening. Look at all relevant git history and retain the intent of every commit.
Approach
First, understand what's happening:
- Run
git statusto see which files are conflicted - Run
git log --merge --onelineto see all commits involved in the conflict - Figure out which branches are being merged and why
- Run
Think hard about the history:
- Look at all relevant git history for each conflicted file
- Run
git log -p --merge <file>to see the actual changes in detail - Use
git show <commit>to deeply understand specific commits - Read every commit message to understand what the developer was trying to achieve
Retain the intent of every commit:
- Don't just pick one side or the other
- Understand what each commit was trying to accomplish
- Think about why each change was made
- Consider how different changes relate to each other
Deal with the conflict thoughtfully:
- Open each conflicted file and carefully examine the conflict markers
- Think hard about how to preserve the intent of both sides
- Combine changes in a way that retains what every commit was trying to do
- Don't take shortcuts — make sure the resolution honors all the work that went into both branches
- Remove conflict markers only after you're confident in your resolution
Make sure you got it right:
- Stage resolved files with
git add - Test that your resolution actually works
- Write a clear commit message that explains how you preserved the intent of all commits
- Stage resolved files with
Remember: This isn't about speed. It's about being thoughtful and retaining the intent of every single commit. Take the time to think hard about what each developer was trying to accomplish.
Quick reference
sh
git status # See conflicted files
git log --merge --oneline # See commits involved
git log -p --merge <file> # See changes in detailPatch replay
A robust, non-interactive pattern to get a conflicted branch into a mergeable state with main by converting changes to a patch, resetting to main, and manually re-applying changes. Best when the branch has conflicts with main, squashing into one commit is acceptable, and standard conflict resolution is error-prone.
Steps
Phase 1: Create a "To-Do List" (The Patch)
Save all unique work into a single patch file:
sh
git fetch origin
git diff origin/main...HEAD > /tmp/my_changes.patch
if [ ! -s /tmp/my_changes.patch ]; then
echo "No unique changes detected. Stopping."
exit 0
fiPhase 2: Create a Clean Slate
Reset the branch to be identical to main:
sh
git reset --hard origin/mainPhase 3: Thoughtfully Re-Apply Work
This is the most critical step. Read the patch file as instructions and manually edit the code. Do not use git apply, which will fail.
Provide progress visibility:
- "Found 12 change hunks across 5 files to apply"
- "Processing file 2 of 5: src/utils.js (3 hunks)"
- "Applied authentication check to line 45"
Instructions:
- Open and read
/tmp/my_changes.patch - Go through each hunk (change block) systematically
- For each hunk:
- Identify the target file
- Open that file (now the main version)
- Find the correct line number and context
- Analyze the code — main may differ from the patch's context
- Manually edit to apply the intent of the patch
Minimize approval prompts: Use built-in tools (Read, Edit, Grep) instead of shell commands (cat, sed, grep).
Phase 4: Finalize and Clean Up
sh
git add .
git commit -m "Re-apply changes on latest main"
rm /tmp/my_changes.patchChecks
- Verify merge is clean by running
git merge --no-commit --no-ff origin/main && git merge --abort - All tests must pass
- Review the final commit before merging
What not to do
- DO NOT use
git rebase -i— stateful, will fail - DO NOT parse merge conflict markers — error-prone
- DO NOT use
git apply /tmp/my_changes.patch— not conflict-aware - DO NOT apply hunks silently — users need visibility
Commit replay
A robust pattern for resolving merge conflicts by replaying each commit individually onto main, isolating conflicts to single commits while preserving commit history. Best when the branch has diverged from main, commit history is valuable and should be preserved, and conflicts are likely isolated to specific commits.
Steps
Phase 1: Setup
sh
git fetch origin
CONFLICT_BRANCH=$(git branch --show-current)
# Create new branch from latest main
git checkout -b ${CONFLICT_BRANCH}-fix origin/main
# Get commits to replay (oldest-first)
git rev-list origin/main..${CONFLICT_BRANCH} --reverse \
> /tmp/commits_to_replay.txt
COUNT=$(wc -l < /tmp/commits_to_replay.txt)
echo "Setup complete. Found $COUNT commits to replay."Phase 2: The Replay Loop
For each commit, process sequentially with clear progress visibility:
- "Processing commit 3 of 15: fixing auth bug"
Step 2a: Attempt automatic application
sh
sha=$(head -n1 /tmp/commits_to_replay.txt)
COMMIT_MSG=$(git log -1 --format=%B $sha)
git format-patch -1 $sha --stdout \
> /tmp/current_commit.patch
if git am /tmp/current_commit.patch 2>/dev/null; then
echo "Commit $sha applied cleanly"
else
echo "Conflict detected for commit $sha"
git am --abort
fiStep 2b: If conflict, resolve manually
- Read the patch to understand what changed
- Examine current state of affected files
- Re-implement the logical changes in the new context
- Apply the intent, not literal text replacement
sh
git add -A
git commit -m "$COMMIT_MSG"
echo "Conflict resolved for $sha"Use built-in tools: Prefer Read, Edit, Grep over cat, sed, grep.
Step 2c: Continue until done
Remove processed commit and repeat until /tmp/commits_to_replay.txt is empty.
Phase 3: Finalize and Replace
sh
FIX_BRANCH=$(git branch --show-current)
CONFLICT_BRANCH=${FIX_BRANCH%-fix}
# Preserve original as backup
git branch -m ${CONFLICT_BRANCH} \
${CONFLICT_BRANCH}-conflict
git branch -m ${FIX_BRANCH} ${CONFLICT_BRANCH}
git checkout ${CONFLICT_BRANCH}
rm /tmp/commits_to_replay.txt
echo "Branch successfully rebased on main."Checks
- Verify merge is clean by running
git merge --no-commit --no-ff origin/main && git merge --abort - Same number of commits as original branch
- All tests must pass
- Review final branch before merging
What not to do
- DO NOT use
git rebase -i— interactive commands fail - DO NOT use
git cherry-pick --continue— stateful, brittle - DO NOT parse merge conflict markers — error-prone
- DO NOT process commits without progress updates
Trade-offs
| Strategy | Pros | Cons |
|---|---|---|
| Simple merge | Preserves full history | Complex with many conflicts |
| Patch replay | Clean reset, simple result | Loses individual commits |
| Commit replay | Preserves individual commits | Slower, more manual effort |