| name | merge-resolve |
| compatibility | Requires tilth MCP server (delegates file IO to cheez-read/cheez-write/cheez-search) |
| allowed-tools | bash |
| description | Resolve merge conflicts, rebase conflicts, and cherry-pick failures using mergiraf (AST-aware structural merge), git rerere, and kdiff3. Activate when: merge failed, rebase conflict, cherry-pick failed, CONFLICT in file, "resolve conflicts", "fix merge", "merge conflict", "conflict resolution", or git output shows CONFLICT markers. Also use for mergiraf diagnostics, rerere management, gitattributes regeneration, or batch conflict resolution across multiple files. Covers the full resolution chain: mergiraf (structural auto-resolve) → rerere (replay remembered fixes) → kdiff3 (manual). Do NOT use for general git operations without conflicts — those go to the commit or gh skills. Examples: "resolve the merge conflicts", "fix the rebase conflicts", "what's conflicting after the merge?", "resolve conflicts in src/auth.ts".
|
merge-resolve
Resolve merge conflicts using the structural merge chain: mergiraf → rerere → kdiff3.
File IO delegation: This skill does NOT hold Read, Edit, Write, or Glob. For
per-file conflict inspection or manual edits, delegate to:
- cheez-read — inspect conflicted files, view conflict hunks, list directory contents
- cheez-search — locate conflict markers, search for related symbols across the tree
- cheez-write — apply resolved content with hash anchors
The bash-driven flows below (git, mergiraf, python scripts) handle the bulk of resolution.
Drop into the cheez skills only when you need to inspect or rewrite a specific file.
Resolution Chain
The three tools form a cascade — each handles what the previous couldn't:
-
mergiraf runs automatically as a git merge driver. It parses all three file versions
(base, ours, theirs) into Tree-sitter ASTs and merges structurally. Independent additions
(imports, functions, struct fields) merge cleanly even when text-based merge would conflict.
Falls back to text merge if parsing fails — never makes things worse.
-
rerere ("reuse recorded resolution") activates after mergiraf. If you manually resolved
the same conflict before, rerere replays that resolution automatically. Especially valuable
during long rebases where the same conflict recurs across commits.
-
kdiff3 is the manual fallback for conflicts neither tool could resolve. Launch with
git mergetool — it opens a 3-way diff view for human decision-making.
Protocol
1. Diagnose the Conflict State
Run the summary script first — it replaces the need for grep -n '<<<<<<<' and ad-hoc parsers:
python3 skills/merge-resolve/scripts/conflict-summary.py
Default output is terse and LLM-oriented: one metadata line per file, then minimally-framed
hunks. Each hunk shows up to 5 lines of ours/theirs and 3 of base, capped to keep token cost low.
Flags:
--json — structured output for scripting
--verbose — markdown-formatted human view (the previous default)
--context N — context lines around each hunk (default 3)
If you need raw git info too:
git log --merge --oneline
2. Attempt Structural Resolution
For files where mergiraf is configured but conflicts remain (meaning the structural merge
already ran and couldn't fully resolve), you can inspect what mergiraf produced vs text merge:
git show :1:<path> > /tmp/base
git show :2:<path> > /tmp/ours
git show :3:<path> > /tmp/theirs
mergiraf merge /tmp/base /tmp/ours /tmp/theirs -o /tmp/merged -p <path>
grep -c '<<<<<<' /tmp/merged
If the merged output has no conflict markers, mergiraf resolved it cleanly — the git
merge driver may have fallen back to text merge due to a parse error or size limit.
Apply the clean output:
cp /tmp/merged <path>
git add <path>
3. Batch Resolution
For repos with many conflicted files, use the batch script:
python3 skills/merge-resolve/scripts/batch-resolve.py
python3 skills/merge-resolve/scripts/batch-resolve.py --apply
python3 skills/merge-resolve/scripts/batch-resolve.py --verbose
The script extracts 3-way inputs for every conflicted file, runs mergiraf merge
on them, and reports which files resolved cleanly vs which need manual intervention.
4. Handle Remaining Conflicts
After structural resolution, for files that still have conflict markers:
Check rerere first:
git rerere status
git rerere diff
If rerere has a resolution, it was already applied. If not, guide the user to manual resolution:
git mergetool
git mergetool <path>
After manual resolution:
git add <resolved-files>
git merge --continue
git rebase --continue
git cherry-pick --continue
5. Debug Mergiraf
When mergiraf isn't resolving something you expect it to:
RUST_LOG=mergiraf=debug mergiraf merge /tmp/base /tmp/ours /tmp/theirs -o /tmp/merged -p <path> 2>&1
mergiraf languages | grep <extension>
git check-attr merge -- <path>
Common issues:
- File not registered: Extension missing from
~/.gitattributes — regenerate after upgrade
- Parse failure: Syntax error in one of the three versions — mergiraf falls back silently
- Size limit: Very large files (>1MB) may skip structural merge
6. Maintenance Commands
Regenerate gitattributes after mergiraf upgrade:
mergiraf languages --gitattributes > ~/.gitattributes
Manage rerere state:
git rerere status
git rerere diff
git rerere forget <path>
git rerere gc
ls .git/rr-cache/
Scripts
Four scripts in skills/merge-resolve/scripts/ cover the common patterns:
| Script | Purpose | When to use |
|---|
conflict-summary.py | Structured summary with line numbers + context | Always run first |
batch-resolve.py | Run mergiraf merge on all conflicted files | Supported langs with structural conflicts |
conflict-pick.py | Choose ours/theirs per hunk | Shell, SQL, or formats not handled by mergiraf |
lockfile-resolve.py | Take one side + regenerate lockfile | Cargo.lock, package-lock.json, etc. |
conflict-pick.py — for file types not handled by mergiraf:
python3 skills/merge-resolve/scripts/conflict-pick.py hooks/session-start.sh --ours
python3 skills/merge-resolve/scripts/conflict-pick.py .gitignore --theirs
python3 skills/merge-resolve/scripts/conflict-pick.py config.yaml --grep "timeout" --ours
lockfile-resolve.py — take theirs, regenerate:
python3 skills/merge-resolve/scripts/lockfile-resolve.py
python3 skills/merge-resolve/scripts/lockfile-resolve.py --dry-run
Supports: Cargo.lock, package-lock.json, yarn.lock, pnpm-lock.yaml,
poetry.lock, Pipfile.lock, uv.lock, Gemfile.lock, go.sum.
Special Cases
Lockfiles
Lockfiles need special handling — textual or structural merge produces valid syntax
but potentially invalid dependency graphs. Use lockfile-resolve.py. The proven
pattern: take --theirs on the lockfile, then regenerate from the merged manifest.
Whitespace-Only Formatting Changes
If one branch ran a formatter while the other modified content, mergiraf may produce
more conflicts because AST positions shifted. Resolution: run the formatter on the
merged result after resolving conflicts.
Abort if Stuck
If the conflict state is unrecoverable:
git merge --abort
git rebase --abort
git cherry-pick --abort
What This Skill Doesn't Do
- Push or create PRs — hand off to the gh skill
- Run builds or tests — use appropriate build/test skills after resolving
- Commit resolved files — use the commit skill
- Architectural review of merge results — use age or code-review
- Abort the operation — presents abort as an option, user decides
- Read, edit, or search files directly — delegate to cheez-read / cheez-write / cheez-search
Gotchas
mergiraf solve flag confusion: use --stdout/-p for preview, NOT --output
- Markdown is supported by mergiraf but may need
.gitattributes registration
- Lockfile structural merge != valid lockfile — always regenerate after taking a side
- zdiff3 base markers: files may contain
||||||| sections — all scripts handle it
- If you see conflicts in a supported file type, mergiraf-as-driver already ran