Skip to content
Development
Skill

/epic-merge

Sequential squash-merge of stacked PR chains into an epic branch. Handles dependency-ordered rebase, collision-safe backup tags, CI monitoring (delegates to /watch-ci), and post-merge verification. Use when: merging a chain of stacked PRs into an epic branch, collapsing a linear

From plugin
sd0x-dev-flow
195102 skills16 agents5 hooks

Claude Code

$ npx -y skills add sd0xdev/sd0x-harness --skill epic-merge --agent claude-code

SKILL.md

epic-merge.SKILL.md
name: epic-merge
description: "Sequential squash-merge of stacked PR chains into an epic branch. Handles dependency-ordered rebase, collision-safe backup tags, CI monitoring (delegates to /watch-ci), and post-merge verification. Use when: merging a chain of stacked PRs into an epic branch, collapsing a linear PR stack into per-PR squash commits, preparing an epic branch for final review. Triggers on: 'merge PRs into epic', 'squash chain', 'collapse PR stack', 'epic merge', or when user has a linear PR dependency chain (PR A -> B -> C) targeting an epic branch. Not for: single PR merge (use /create-pr + GitHub UI), simple rebase (use /smart-rebase), pre-merge analysis (use /merge-prep). Output: chain analysis table + backup tag manifest + per-iteration AskUserQuestion gate + verification log."
disable-model-invocation: true
allowed-tools: Bash(git:*), Bash(gh:*), Bash(bash:*), Read, Grep, Glob, AskUserQuestion, Skill

Epic Merge — Stacked PR Chain Squash-Merge

**Read first**: `@skills/push-ci/references/authorization-contract.md` before any push or merge — § Push safety for the credential, the unshared attestation and the force-with-lease rules, § Efficacy Boundary for what the per-iteration approval authorizes. If that Read fails, stop and report it; push and merge nothing.

Sequentially squash-merge a chain of stacked PRs into an epic branch, producing one squash commit per PR for clean per-PR review on the epic. Every destructive iteration is gated by `AskUserQuestion` to keep the operator in control.

When NOT to Use

  • Single PR merge — use `/create-pr` + GitHub UI
  • Simple rebase without stacked dependencies — use `/smart-rebase`
  • Pre-merge conflict / impact analysis only — use `/merge-prep`
  • Diamond / parallel merge chains — this skill handles **linear chains only**
  • Repos that use merge-commit or rebase-merge — this skill assumes squash-merge only

Permissions

This skill is one of the explicit exceptions in `@rules/git-workflow.md` allowed to execute `git rebase --onto`, `git push --force-with-lease`, and `gh pr merge --squash`. Every destructive step is gated by `AskUserQuestion`.

| Phase | Operation | Mutates | Approval | |-------|-----------|---------|----------| | Phase 0 step 0 refresh | bounded `git fetch` (§ Phase 0 step 0) | `refs/remotes/origin/*` + `.git/FETCH_HEAD` | No (local, bounded, recoverable) | | Phase 1 backup | `git tag -f` | local refs only | No (no remote / non-recoverable mutation) | | Phase 2 iteration | rebase + force-push + `gh pr merge` | local + remote | **Yes** — single bundled gate per iteration (or per-step with `--per-step`) | | Phase 3 verify | `git log` | none | No (read-only) |

**`--dry-run` outputs the plan and performs exactly one bounded local *operation*** — enumerated rather than implied, because every earlier phrasing was a promise the flag did not keep. "Skips all destructive steps" let Phase 1 run unconditionally, so a dry run force-updated every `backup/pr-*` tag and left a manifest per PR in the working tree. The repair overcorrected: it said the run "writes nothing" while still running `git fetch origin`, which is not a read and is not confined to `origin/*` — see § Phase 0 step 0. And "one bounded **write**" was still too strong: a refspec bounds which *refs* a fetch may update, not what else fetching does.

| Under `--dry-run` | Behaviour | |-------------------|-----------| | Phase 0 step 0 refresh | **Runs.** The one mutating operation a dry run keeps: the bounded fetch of § Phase 0 step 0, whose **ref updates** are bounded to `refs/remotes/origin/*` plus `.git/FETCH_HEAD` — its other writes are not, see § `--dry-run` residue below. Skipping it would print a plan derived from stale refs, and a wrong plan is worse than a refreshed `origin/*` | | Phase 0 analysis | Runs — read-only, over the refs step 0 has just refreshed | | Phase 1 `git tag -f "backup/pr-*"` | **Skipped.** Printed as a command, not executed | | Phase 1 manifest files | **Skipped.** The `git log` runs, but its output goes to the report instead of `$(git rev-parse --git-path epic-merge)/expected-pr-*.manifest`, so no file is created and none of a previous run's are overwritten | | Phase 2 iteration | **Skipped entirely** — no gate is asked, no rebase, no push, no merge. The commands are printed | | Phase 3 verification | Skipped — there is nothing to verify |

The residue, stated because a dry run that leaves a trace should say where. **Refs**: `refs/remotes/origin/*` and `.git/FETCH_HEAD` — that set is what the explicit refspec bounds. **Objects and metadata**: a fetch that finds new commits downloads them into the object database, and depending on configuration git may run auto-maintenance or rewrite the commit-graph on its way out; in a shallow clone it may update the shallow metadata too. None of that is destructive and none of it is bounded by a refspec, which is why the promise above is "one bounded operation" and not "one bounded write". Pass `--no-auto-maintenance --no-write-commit-graph` to suppress the maintenance half; the downloaded objects are inherent to fetching and remain. **Nothing changes on the remote.**

Core Concept

After squash-merging PR N, the original commits are replaced by a single squash commit on epic. PR N+1 still contains N's original commits as its base — these must be cut via `git rebase --onto` before merging N+1. The cut point is the original tip of PR N's branch, captured in Phase 1 as a backup tag.

epic:    E ─── S_N (squash of PR N)
PR N+1:  E ─ A1 ─ A2 ─ ... ─ B1 ─ B2
              └── drop (in S_N) ──┘ └─ keep ─┘

After: git rebase --onto origin/epic backup/pr-<N> PR_N+1
epic:    E ─── S_N ─── B1' ─ B2'

Names in commands

**A PR head branch name is not display text.** It arrives from GitHub, and `git check-ref-format` accepts far more than the names people type: measured, `refs/heads/feat/x$(printf${IFS}PWNED>&2)` and `refs/heads/--all` both pass, `git update-ref` creates both, and `git c

Read more
@sd0xdev
Ships withsd0x-dev-flow

Language: English | 繁體中文 | 简体中文 | 日本語 | 한국어 | Español The harness layer for Claude Code. Let the model choose the path. Keep "done" verifiable. Claude has discretion inside a closed, test-pinned anchor set.

195102 skills16 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
195
Star history of sd0xdev/sd0x-dev-flow on GitHub, a chart by star-history.com

Other skills on sd0x-dev-flow.

adr

adr

Write an Architecture Decision Record (ADR) for a feature — Context / Decision / Status / Consequences / Alternatives, filed as…

agentctl-setup

agentctl-setup

Install and set up the optional agentctl mod (task scope, refusal before execution, evidence that goes stale, model-free…

architecture

architecture

Architecture design and documentation. Produces 3-architecture.md with component diagrams, data flow, integration points, and…

ask

ask

Context-aware Q&A with auto context gathering. Use when: user has a quick question about codebase, git history, rules, docs, or…

best-practices

best-practices

Industry best practices conformance audit with mandatory adversarial debate. Produces audit artifact: verdict (OK/WARN/FAIL) +…

bug-fix

bug-fix

Bug fix workflow. Use when: fixing bugs, resolving issues, regression fixes. Not for: new features (use feature-dev),…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about epic-merge.

Which coding agents can use epic-merge?
epic-merge installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.