resolving-merge-conflicts
Resolve an in-progress git merge, rebase or cherry-pick conflict - find out what each side was trying to do, resolve each hunk without inventing behaviour, run the project's checks, then finish the operation.
- Use it when
- Git reports CONFLICT, files contain conflict markers, git status says "unmerged paths" or "rebase in progress", or the user says "fix the merge conflicts", "resolve this rebase" or "sort out the conflict". It never pushes, force-pushes or aborts on its own. Not for avoiding conflicts, choosing a branching strategy, or undoing a finished merge.
- What kind it is
- A written method: it lays out how the work is done and what to check along the way.
- Size
- 870 words. The whole text loads when the skill fires; only the 89-word description is always loaded.
- Starts with
- Ask for the job it describes.
How it is organised
What’s inside
The skill’s top-level sections, in order. The bar is each section’s share of the 870 words, so you can see where the weight sits before reading.
- 11. See the state113 words
- 22. Find the intent of each side110 words
- 33. Resolve each hunk221 words
- 44. Run the checks71 words
- 55. Finish the operation126 words
- 6About aborting129 words
- 7Report29 words
The skill itself
Read it before you install it
resolving-merge-conflicts/SKILL.md · 870 wordsDownloadSkill on GitHub ↗--- name: resolving-merge-conflicts description: Resolve an in-progress git merge, rebase or cherry-pick conflict - find out what each side was trying to do, resolve each hunk without inventing behaviour, run the project's checks, then finish the operation. Use when git reports CONFLICT, files contain conflict markers, git status says "unmerged paths" or "rebase in progress", or the user says "fix the merge conflicts", "resolve this rebase" or "sort out the conflict". It never pushes, force-pushes or aborts on its own. Not for avoiding conflicts, choosing a branching strategy, or undoing a finished merge. license: MIT --- # Resolving merge conflicts A conflict means two changes touched the same lines and git cannot decide between them. Both changes had a reason. The job is to keep the reasons, not to make the markers go away. ## 1. See the state ```bash git status git diff --name-only --diff-filter=U ``` Find out which operation is running (merge, rebase or cherry-pick), which branch is being brought in, and which files are unmerged. For each file, look at the commits on each side that touch it: `git log --merge --oneline -- <file>` while a merge is in progress. Before you touch anything, check whether `git status` shows uncommitted changes that are not part of the conflict. Git's own manual warns that `git merge --abort` may be unable to restore uncommitted changes that were present at the start, particularly if they were edited afterwards. If there are changes that are not part of this conflict, tell the user. ## 2. Find the intent of each side For every conflicting hunk, work out why each change was made. Read the commit messages on both sides, the pull request or ticket they point to, and any plan or spec the project keeps. A comment in the code is a clue, not proof. If you cannot establish what one side was for, ask the user instead of guessing. A wrong guess here compiles, passes review and breaks something later. When the markers show only the two sides, show the common ancestor too: `git checkout --conflict=diff3 -- <file>` rewrites the file with three sections, ours, the base, and theirs. Seeing what both sides started from usually makes the intent plain. ## 3. Resolve each hunk - **Keep both intents** when they can coexist. Often that is combining two edits, or applying one change to the other's new shape. - **When they cannot coexist**, take the one that fits the stated goal of the merge, and note the trade-off in the commit message and your report. Say what was lost. - **Do not invent behaviour.** If the only resolution would be new logic neither side wrote, stop. That is a decision for the user, who may need to talk to whoever wrote the other change. - **Check which side is which.** In a merge, "ours" is the branch you are on. In a rebase it is reversed: "ours" is the branch you are rebasing onto, and "theirs" is the commit being replayed, which is usually your own work. A blanket `git checkout --ours <file>` or `--theirs` that discards one whole side is only right when that side is meant to go entirely. - **Generated and lock files.** Do not hand-merge them. Resolve the source files, then regenerate with the project's own tool. - **Deleted on one side, edited on the other, renamed, or binary.** These need a decision, not a text edit. Say which choice you made and why. - **Remove every marker.** After editing, run `git diff --check`. It flags leftover `<<<<<<<`, `=======` and `>>>>>>>` lines. ## 4. Run the checks Find the project's automated checks, usually a type check, then the tests, then formatting. Run them and fix whatever the merge broke. If a test was already failing before the operation, report it by name; do not claim the merge is clean. In a rebase the tree is only partly replayed until the last commit, so run the full checks when the rebase finishes. Whatever you could not run, say so. ## 5. Finish the operation Stage the files you resolved by name, not with `git add -A`, which can sweep in untracked files that have nothing to do with the merge. Look at `git status` to confirm nothing unmerged remains. Then conclude: - Merge: `git commit`. Keep the message git prepared and add a line for any trade-off from step 3. If the host has no editor, pass the message with `-m`. - Cherry-pick: `git cherry-pick --continue`. - Rebase: `git rebase --continue`. Expect to repeat steps 1 to 5 for each later commit that conflicts, until git reports the rebase is done. Stop there. Do not push. A rebase rewrites the branch's history, so publishing it needs a force-push, and that happens only if the user explicitly asks, naming the branch. ## About aborting `git merge --abort` and `git rebase --abort` put the repository back as it was before the operation began. They are the user's way out, and they are also destructive: they throw away every resolution made so far, and they can lose uncommitted changes. - Do not abort on your own because the conflict is hard or the work is going badly. - Do not start over with `git reset --hard`, `git checkout .` or `git clean` to "get a fresh start". - If resolving would mean inventing behaviour, or the conflict shows that two lines of work were never independent, stop with the conflict still in place. Explain it, and offer the abort as one of the options. - Run an abort only when the user asks for one. ## Report When done, say what was in conflict, how each hunk was resolved and why, what the checks showed, and the state of the repository now: operation finished, nothing pushed.
The second audit
What we found in the sources
The four sources are one 921-byte five-step text, two copies of it and a version extended for one project. This skill keeps the five steps, replaces the absolute 'never --abort' with a stop-and-ask rule, and adds a section of git mechanics written by the author. That section is not from any source; its commands were run in a scratch repository on git 2.50.1 (Apple Git-155). The skill itself has not been run against real conflicts. Every source below was read at the commit the auditor recorded. Nothing was taken from a source without a permissive license.
What each source contributed
- mattpocock/skills ↗ · Primary basis · MIT
The five steps: see the state of the merge or rebase; find the primary sources for each conflict and the original intent; resolve each hunk, keeping both intents where possible, choosing the side that matches the merge's goal when they are incompatible, and not inventing behaviour; run the project's checks (type check, tests, format) and fix what the merge broke; finish the merge or continue the rebase to the end. The text of this file reappears byte for byte in one other source, with one character changed in a second, and as the base of a third, so it is treated as the origin; the direction of copying was not checked against commit dates.
- MokeyBytes/capstan ↗ · Added ideas · MIT
The exception for a conflict whose only resolution would be behaviour neither side has, or one that shows two lines of work were never independent: treat it as a problem to report, not a merge to force. Changed to 'stop with the conflict in place and ask', since the source's follow-up (abort) relies on its own setup. Its Capstan file paths were not taken.
What changed
- The description now says what the skill does, lists the phrases that should trigger it ("CONFLICT", "unmerged paths", "rebase in progress", "fix the merge conflicts") and has a not-for clause. The source description is one sentence: "Use when you need to resolve an in-progress git merge/rebase conflict."
- 'Always resolve; never --abort' was replaced. Abort restores the repository to its state before the operation, so it is the user's way out; it also discards every resolution made so far and can fail to restore uncommitted changes that were present at the start (the git-merge manual says so). The skill does not abort or start over on its own, stops with the conflict in place when the only resolution would invent behaviour, and runs an abort only when the user asks.
- 'Stage everything and commit' became staging the resolved files by name, checking git status, and concluding with git commit, git cherry-pick --continue or git rebase --continue. Pushing is left out; after a rebase it would need a force-push, which only happens on explicit request.
- Added by the author from general git knowledge, not from any source: showing the common ancestor with `git checkout --conflict=diff3`, listing unmerged paths with `git diff --name-only --diff-filter=U` and `git log --merge`, the reversal of 'ours' and 'theirs' in a rebase, regenerating generated and lock files instead of hand-merging them, treating delete/modify, rename and binary conflicts as decisions, and checking for leftover markers with `git diff --check`. The commands were run in a scratch repository on git 2.50.1 (Apple Git-155).
- Added a report section and a note that mid-rebase the tree is only partly replayed, so full checks run at the end.
Problems found in the sources
- mattpocock/skills: The description is a single sentence with no phrases a person would type and no not-for clause. 'Always resolve; never --abort' removes the user's way out, and it collides with 'Do not invent new behaviour' when the only resolution needs new behaviour; the file does not say what to do then. 'Stage everything and commit' can sweep in untracked files unrelated to the merge. It says nothing about conflicts that are not text hunks (delete/modify, binary, generated files), about leftover markers, about the ours/theirs reversal in a rebase, or about not pushing afterwards.
- MokeyBytes/capstan: Tied to the Capstan workflow: it reads .capstan/effort/plan.md and spec.md, writes to decisions.md in a document home, and refers to Builders and a decision-record skill, none in the file. Its abort exception relies on 'every Builder's work sits on its own branch, so an abort costs the merge and nothing else', which holds only in that setup.
What was dropped
- Capstan's file paths (.capstan/effort/plan.md, spec.md, decisions.md) and its reference to a decision-record skill.
- The instruction to abort when slices were not independent, which depends on Capstan's model of one branch per builder.
Read but not used (2)
- the-inconvenience-store/skills: Byte-identical to mattpocock/skills: the SHA-256 values in the bundle match and diff reports no difference. Nothing separate to use.
- Bossmann007/cursor-kit: A near copy of mattpocock/skills: diff shows one changed character in step 4, an em dash replaced by a comma. Nothing separate to use.
Same text, wherever you work
Use it where you work
Copy the folder into your skills directory, then ask for the job or type its start command.
- Download
SKILL.mdwith the button above, and put it in a folder namedresolving-merge-conflicts. - Zip the folder.
- In Claude, open Settings → Skills and upload the zip.
SKILL.md is plain Markdown. Copy the text and paste it as the system prompt or the first message. It will not trigger by itself there; you start it.