skills/merge-base-into-branch/SKILL.md
Bring a branch up to date with its base by MERGING the base in (a merge commit), never rebasing — so no commit hashes are rewritten and no force-push is needed. Use this whenever the user asks to "use the merge skill", "bring my branch up to date", "merge main/the base into this branch", "update my branch from its base without rebasing", "do a merge commit instead of rebasing", or "clear the conflict on my stacked PR without a force-push" (a common situation right after a parent PR squash-merges and the child branch suddenly shows conflicts). It handles both cases: a base that only re-packaged work the branch already has, and a base that carries genuinely new work to fold in. It always verifies the merge preserved exactly the branch's own change before pushing. This is an explicitly-invoked workflow — reach for it when the user talks about merging or updating a branch from its base, but don't hijack unrelated git merges.
npx skillsauth add MoonBoi9001/claude-code-cli-tools merge-base-into-branchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
When a branch's base has moved on, you have two ways to catch up: rebase (replay the
branch's commits on top of the new base) or merge (pull the new base in under a merge
commit). This skill is for the merge route, and for doing it intelligently — the easy part is
typing git merge; the hard part is resolving conflicts correctly and proving you didn't
silently corrupt the branch's work.
Rebase rewrites every commit on the branch (new hashes), which forces a git push --force. On
a PR that can drop review approvals, detach review threads from their commits, and clobber a
teammate who pulled the branch. A merge leaves the branch's existing commits untouched and adds
one merge commit on top, so the push is an ordinary fast-forward — no force, approvals survive.
The cost is a busier branch graph (a merge commit, and sometimes duplicated copies of commits the base already absorbed). That looks messy, but if the branch eventually lands via squash-merge, the squash takes only the net diff — the merge commit and any duplicates collapse to nothing and never reach the base. So you get safety now and a clean base history later. (If instead the branch will land as a real merge and you care about its internal linear history, rebase may genuinely be the better tool despite the force-push — say so and let the user choose.)
Everything downstream depends on which situation you're in. Don't guess; check.
Scenario A — re-packaged duplicate. The base recently absorbed work the branch already contains. The classic case: a stacked parent PR squash-merged, so the base now holds a single squashed commit that is the same change as the pre-squash commits still sitting on the branch. The "conflict" is just two representations of the same change colliding. The base has nothing genuinely new for the branch.
Scenario B — genuine new work. The base has real new commits the branch doesn't have, and the branch needs to fold them in. This is an ordinary sync.
How to tell them apart. Identify the commit your branch was built on relative to the base —
call it the fork point. For a stacked PR that is the parent PR's old tip (the commit your
branch sat on before the parent merged); git log --oneline <fork> ..HEAD should show only your
own commits. Then:
git fetch origin <base>
git diff <fork> origin/<base> --stat
This single check is what makes the rest safe. Run it every time; don't assume.
git status --short # working tree must be clean before merging
git branch --show-current # confirm you're on the branch you mean to update
git fetch origin <base>
You will verify against this afterwards, so capture it while it's still unambiguous:
bash <skill-dir>/scripts/verify-merge.sh capture <fork>
# equivalently: git diff <fork> HEAD > /tmp/own-change.diff
git diff <fork> HEAD is exactly what your PR is supposed to contribute once the base has
absorbed everything up to the fork point.
Merge a local base branch (not the remote-tracking ref) so the commit message reads the
familiar Merge branch '<base>' into <yours>. Update that local ref first:
git branch -f <base> origin/<base> # fast-forward your local <base> to the fetched tip
git merge <base> # let git create the merge commit + default message
What happens next depends on conflicts:
No conflicts → git auto-commits with its standard merge message. Go to verify.
Scenario A with conflicts → the conflicts are the duplicated work colliding. Because you
proved (step 0/the diff check) the base's content is already in the branch, the correct
result is your tree, wholesale. Use the ours merge strategy:
git merge -s ours <base> # result tree == your branch's tree, exactly
-s ours records the base as a parent but keeps your tree verbatim, discarding the base's
side — which loses nothing here precisely because you proved containment. It also auto-commits
with the clean default message.
Scenario B with conflicts → resolve each conflict by hand. You want both the base's new
work and your branch's changes, combined correctly. Never blanket-pick a side. After resolving,
git add the files and git commit to finish the merge.
-s ours vs -X ours trap — read this before reaching for eitherThese look interchangeable and are not. This is the single easiest way to silently corrupt a branch, so internalise the difference:
-X ours is a strategy option: during a normal three-way merge it resolves only the
conflicting hunks in your favour, but it still applies the base's non-conflicting changes.
If your branch deleted a line that the base still has, that deletion is not a conflict — so
-X ours quietly re-adds the line, undoing your change. Nothing warns you.-s ours is a strategy: the merge result is your tree, period. The base contributes
nothing to the tree. Safe only when you've proven the base's content is already in your
branch (Scenario A). Wrong for Scenario B — it would throw away the base's new work.For the duplicate scenario, prefer -s ours (whole-tree, provably correct after the containment
check). Avoid -X ours there. Worked example below shows exactly how -X ours bites.
A merge can look fine and have quietly changed the branch's diff. Always confirm before pushing.
Scenario A: the post-merge diff against the base must be byte-identical to the change you captured in step 2:
bash <skill-dir>/scripts/verify-merge.sh check origin/<base>
# equivalently:
# git diff origin/<base> HEAD > /tmp/post.diff
# diff /tmp/own-change.diff /tmp/post.diff && echo IDENTICAL
Anything other than identical means the merge altered your work (the -X ours trap is the
usual culprit) — stop, do not push, redo the resolution.
Scenario B: there is no single equality (the diff now legitimately includes the base's new work). Instead confirm, with judgment: every one of your own changes still survives, the base's new changes are present, and nothing contradictory slipped in.
Both scenarios: build / compile / run the affected tests. A merge that resolves cleanly can still break the code where two changes meet.
git push origin <branch> # ordinary fast-forward
If git ever demands --force (or --force-with-lease) here, you did not do a merge — you
rewrote history somewhere (an accidental rebase or amend). Stop and work out what happened; the
whole point of this skill is that the push stays a fast-forward.
Letting git merge create the commit gives you git's standard Merge branch ... message, and
it does not route through git commit — so commit-message validators that hook git commit
(e.g. ones demanding Conventional Commits) never see it. If a conflicted merge forces you to
finish with git commit and such a validator rejects the default merge wording, the cleanest
escape is to complete the merge via an auto-committing path instead (for Scenario A, git merge -s ours <base> resolves and commits in one step), which keeps the standard message and sidesteps
the hook. Don't invent a Conventional-Commits title for a mechanical merge just to satisfy a
linter if you can avoid it.
-X ours silently corrupts (real case)A stacked PR (call it the child) made a base configurable: it deleted a hardcoded line
const INTERVAL = 5000 and added a config field instead. Its parent then squash-merged into the
base, so the base now held the parent's change as one squashed commit (Scenario A — the
containment check came back empty).
Merging with git merge -X ours base reported 1 file changed, 1 insertion(+). That insertion
was const INTERVAL = 5000 coming back: the base still had that line, the child had deleted it,
the deletion wasn't a conflict, so -X ours re-applied the base's version and quietly undid
the child's whole point. The byte-for-byte verification in step 5 caught it (the post-merge diff
no longer matched the child's captured change). Redoing it with git merge -s ours base
produced a tree identical to the child's, the verification came back IDENTICAL, and the push was
a normal fast-forward.
The lesson: the verification is not ceremony. It is the thing that turns "looks merged" into "provably correct."
git fetch origin <base>.git diff <fork> origin/<base> → empty = Scenario A, non-empty = B.verify-merge.sh capture <fork>).git branch -f <base> origin/<base> then git merge <base> — -s ours if A and it
conflicts; hand-resolve if B. Never -X ours for the duplicate case.git push — fast-forward, never forced.development
Run a deep multi-agent review of a GitHub PR — 6 specialized agents covering architecture, correctness, security, tests, code quality, and integration. ONLY trigger when the user's message contains the explicit phrase 'deep review' (e.g. 'deep review this PR', 'deep review PR #1234', 'do a deep review of 1234', '/deep-review'). Do NOT trigger on bare 'review', 'review this', 'review the PR', 'code review', 'what do you think of this PR', or pasted PR URLs without 'deep review' in the message — those are handled by the lighter /review skill. The literal phrase 'deep review' must appear in the user's message; absence of that phrase means do not invoke this skill.
data-ai
--- name: re-explain description: Re-explain a concept from the ground up when an earlier explanation didn't land. Trigger aggressively whenever the user signals confusion about recent technical content — phrases like "i don't get it", "from scratch", "ground up", "explain again", "this makes no sense", "try again", "you need to work better", "what's X" (where X was something just mentioned), or invoking /re-explain directly. Also trigger on quieter cues like the user re-quoting a phrase from th
development
Load a high-fidelity recap of a prior Claude Code session into the current session's context. The goal is to be LESS lossy than running /compact would be — the user is invoking this skill precisely because /compact discards detail they need. Use this when the user wants to "resume", "pick up", "continue", or "load context from" a previous session — especially a long one (hundreds of thousands of tokens) where actually resuming the session would be prohibitively expensive, or where the session was auto-compacted mid-flow and a lot of detailed work happened after the last compaction that another /compact pass would crush. Also trigger on phrases like "recap the last session", "what was I working on yesterday", "load the prior chat", or "/load-prior-session". The skill extracts via a subagent so the full transcript never enters the current session's context.
development
Convert the most recent code review in the conversation into a grouped numbered checklist (Decisions needed / Fixes / Polish) of issues to fix. Use this skill whenever the user wants to extract, list, summarize, or triage the issues a reviewer raised — including phrasings like "list the issues from that review", "make me a todo from the review", "turn the review into a checklist", "what did the review flag", "summarize that review as a list", "give me every nit from above", or "/review-todo". Trigger especially as a natural follow-up to /review, /deep-review, /security-review, /ultrareview, or any pasted PR / inline review the user wants to act on. The output is a numbered list of every concrete issue the review raised, grouped under bold section headings, with file:line references appended in parentheses, and decision items rendered with a `→` arrow callout below the description posing the specific question — and lettered choices below that when the reviewer named discrete alternatives.