| name | merge |
| description | Merge one branch into another by opening a pull request, then arming auto-merge (GitHub) or auto-complete (Azure DevOps) so the merge only lands once CI / branch policies pass. Detects the remote platform automatically. Use this skill whenever the user runs /merge, asks to "merge branch X into Y", "integrate branch", "fold branch", or wants to combine branch history. Always invoke this skill before any git merge / gh pr merge / az repos pr work. |
| argument-hint | <source> → <target> [--squash|--rebase|--no-auto|--message: <text>] |
Merge Skill
Merge one branch into another by opening a pull request and arming auto-merge. The arrow direction is source → target (left → right). Works on both GitHub (gh) and Azure DevOps (az repos) — the skill detects which from the origin remote and routes to the matching helper scripts.
Why PR + auto-merge
Direct git merge && git push skips CI. We open a PR and arm auto-merge (GitHub) / auto-complete (Azure DevOps) so the merge only commits once every required check or branch policy passes. If a check fails, the PR stays open and the user sees what broke.
Arguments
/merge <source> → <target> — required. The arrow can be →, ->, or into. Examples:
/merge feat/login → develop
/merge feat/login -> develop
/merge feat/login into develop
/merge develop → main
Optional trailing flags:
--squash — squash-merge instead of preserving a merge commit
--rebase — rebase-merge
--no-auto — open the PR but don't arm auto-merge (user will merge manually)
--message: <text> — override the auto-generated PR title (still apply conventional prefix)
Helper scripts
The skill lives in ~/.claude/skills/merge/. The shell scripts in scripts/ carry the heavy lifting so the model only writes the title + body and orchestrates the call sequence.
Platform detection + shared scripts (scripts/, work on any platform — pure git):
scripts/detect_platform.sh — reads the origin URL and prints github or azure. Exits non-zero on an unrecognized host. Run this first; use its output as <platform> below. Requires the matching CLI to be installed and authed (gh for github, az with the azure-devops extension for azure).
scripts/preflight.sh <source> <target> — clean tree check, branch existence, remote sync. Prints OK plus an original=<branch> line so we can return to it later. Exits non-zero on any precondition failure.
scripts/changes.sh <source> <target> — prints commit log + diff stat for the model to summarise into a title and body. Bounded output, model-friendly.
Platform-specific scripts (scripts/<platform>/, where <platform> is github or azure):
scripts/<platform>/open_pr.sh <source> <target> <title> <body> — pushes <source> if needed, creates or updates the PR, prints pr_number=N and url=.... (github: gh pr; azure: az repos pr, org/project/repo auto-detected from the remote.)
scripts/<platform>/auto_merge.sh <pr_number> [strategy] — strategy ∈ merge | squash | rebase (default merge).
- github — checks
autoMergeAllowed and arms gh pr merge --auto when supported; otherwise (or if arming fails) falls back to a poll loop (every 15s, merges when everything passes, aborts on any failed check).
- azure — arms
az repos pr update --auto-complete true (the PR completes once branch policies pass). The CLI only exposes --squash, so merge→no-squash, squash→squash, rebase→basic merge with a warning.
The PR body skeleton lives in assets/pr_template.md — fill it in from changes.sh output and pass the rendered text as <body>. It's platform-agnostic.
Title / body format
PR title is the conventional-commit shape the user already prefers, with a scope in parens for the target branch:
merge(<target>): <source> → <target> | <pithy content summary>
<target> in parens is the destination branch (e.g. develop, main). Drop any feat/ / fix/ prefix when shortening (e.g. feat/embeddings target → (embeddings) only if it's a long-lived branch; for the common develop / main case use those names verbatim).
<source> and <target> in the arrow segment are literal branch names with a real Unicode arrow →.
- Content summary is what the model writes from
changes.sh output. Lowercase, one clause.
- Title length budget ~120 chars. Anything longer goes in the body.
Examples:
merge(develop): feat/embeddings → develop | tier-3 SLM hints + cognee-style resolver
merge(main): develop → main | landing page + backtest knobs + postgres port
Body should describe what landed at the subsystem level (api, workers, client, ci, etc) and any operationally-relevant notes (migrations, env changes, breaking calls). Don't restate the title. Include a brief test plan when the change touches user-facing surfaces.
Steps (model orchestration)
- Parse args — extract
<source>, <target>, and flags. If either branch is missing, ask the user before any tool call.
- Detect platform —
PLATFORM=$(bash ~/.claude/skills/merge/scripts/detect_platform.sh). If it exits non-zero, surface the error and stop. Use $PLATFORM (github or azure) for the path in steps 5–6.
- Pre-flight —
bash ~/.claude/skills/merge/scripts/preflight.sh <source> <target>. If it exits non-zero, surface the error to the user and stop. Capture the original= line for step 8.
- Diff context —
bash ~/.claude/skills/merge/scripts/changes.sh <source> <target>. Read the output.
- Craft title + body — title in the format above (under ~120 chars); body from
assets/pr_template.md, only when needed.
- Open / update PR —
bash ~/.claude/skills/merge/scripts/$PLATFORM/open_pr.sh <source> <target> <title> <body>. Capture the pr_number= line from stdout.
- Arm auto-merge — unless
--no-auto: bash ~/.claude/skills/merge/scripts/$PLATFORM/auto_merge.sh <pr_number> <strategy>. Strategy comes from the flags (--squash → squash, --rebase → rebase, default merge).
- Return to original branch —
git checkout <original> using the value from preflight's original= line.
- Report — give the user the PR URL, the chosen strategy, and the auto-merge / auto-complete state (
armed, merged, or awaiting CI / policies).
What NOT to do
- Don't
git merge locally and push — that bypasses CI.
- Don't force-push the source branch unless the user explicitly asks.
- Don't approve the PR programmatically — auto-merge handles policy.
- Don't push to
main/master without explicit user confirmation.
- Don't add
Co-Authored-By lines.
- Don't reference issue numbers unless the user asks.
- For multi-paragraph bodies, write the body to a temp file and pass the file content to
open_pr.sh via "$(cat path)" so shell quoting stays sane.