Agent Skills: Stacked Pull Requests

Stacked pull request workflows for large features. Use when creating stacked PRs, managing dependent PRs, or rebasing after parent merges. Covers stack creation, merge order, and squash merge handling.

UncategorizedID: tianjianjiang/smith/smith-stacks

Install this agent skill to your local

pnpm dlx add-skill https://github.com/tianjianjiang/smith/tree/HEAD/smith-stacks

Skill Files

Browse the full folder contents for smith-stacks.

Download Skill

Loading file tree…

smith-stacks/SKILL.md

Skill Metadata

Name
smith-stacks
Description
Stacked pull request workflows for large features. Use when creating stacked PRs, managing dependent PRs, or rebasing after parent merges. Covers stack creation, merge order, and squash merge handling.

Stacked Pull Requests

<metadata>
  • Scope: Advanced stacked PR workflows and patterns for large features
  • Load if: Creating stacked PRs, working on PR stacks, managing dependent PRs
  • Prerequisites: @smith-gh-pr/SKILL.md, @smith-git/SKILL.md, @smith-gh-cli/SKILL.md
</metadata>

CRITICAL (Primacy Zone)

<forbidden>
  • NEVER merge child PR before parent
  • NEVER merge main directly into child branch
  • NEVER create stacks deeper than 3-4 levels
  • NEVER use squash merge for non-final PRs in a stack
</forbidden>

Stack Scope Verification

<required>

Before stack-wide operations (rebase cascade, PR creation):

  1. Load stack metadata from Serena memory (if available)
  2. Enumerate ALL branches with commit counts
  3. Present scope summary to user
  4. Get explicit scope approval before proceeding
  5. After completion, report status per branch

Empty rebase detection:

  • If git rebase produces 0 new commits, STOP
  • Investigate why (already up-to-date? wrong base?)
  • Report the anomaly to user before continuing
</required> <context>

For large features, use stacked PRs to maintain atomic, reviewable changes.

When to stack:

  • Feature requires 500+ lines of changes
  • Multiple logical components that can be reviewed independently
  • Need to unblock dependent work before full feature is ready
</context>

Creating Stacked PRs

<required>

How to stack:

  1. Create base PR with foundation (e.g., feat/auth-base)
  2. Create child PR branching from base (e.g., feat/auth-login from feat/auth-base)
  3. Each PR should be independently reviewable and mergeable
  4. Merge bottom-up: base first, then children
</required> <examples>

Stack structure:

main
 └── feat/auth-base (PR #1: models, migrations)
      └── feat/auth-login (PR #2: login endpoint)
           └── feat/auth-oauth (PR #3: OAuth integration)

PR description for stacked PRs:

## Stack
- **Depends on**: #123 (feat/auth-base) ← This PR requires #123 to be merged first
- **Blocks**: #125 (feat/auth-oauth) ← PR #125 depends on this PR

Field meanings:

  • Depends on: PRs that must merge before this one (upstream dependencies)
  • Blocks: PRs waiting for this one to merge (downstream dependents)
</examples>

Stacked PR Merge Workflow

<required>

Sequential merge order (bottom-up):

  1. Wait for parent PR approval
  2. Merge parent PR into main
  3. Rebase child PR onto updated main
  4. Get child PR approved
  5. Repeat for each level in stack
</required> <examples>

Correct merge sequence:

1. Merge PR #1 (feat/auth-base) → main
2. Rebase PR #2 (feat/auth-login) onto main
3. Merge PR #2 → main
4. Rebase PR #3 (feat/auth-oauth) onto main
5. Merge PR #3 → main (can squash this one)
</examples>

Rebasing After Parent Merges

<required>

When a parent PR merges, child PRs must be rebased:

  1. Fetch latest changes
  2. Checkout child branch
  3. Rebase onto updated main
  4. Force push (safe for your PR branch)
git fetch origin
git checkout feat/auth-login
git rebase --onto origin/main feat/auth-base
git push --force-with-lease

Why --onto: Only transplants commits unique to child branch (commits between parent and child), avoiding duplicate commits.

</required> <examples>

Before rebase (after parent merged):

main ──●──●──●──M (parent merged as M)
                 \
feat/auth-login ──A──B──C (still based on old parent)

After git rebase --onto origin/main feat/auth-base:

main ──●──●──●──M
                 \
                  └──A'──B'──C' (feat/auth-login rebased)
</examples>

Squash Merge with Stacked PRs

<required>

Squash merge IS allowed if you follow the branch deletion process for stacked PRs.

Merge Strategy by PR Position:

  • Parent (has children): Squash OK with process, delete after child base updated
  • Middle: Squash OK with process, delete after child base updated
  • Final (leaf): Squash OK, immediate deletion OK
</required> <context>

Why squash merge requires extra steps:

Squash merge creates a single commit, destroying commit ancestry. Child branches still contain parent's original commits, causing:

  • Duplicate commits in child PR
  • Merge conflicts when rebasing
  • Git unable to recognize commits already in main
</context> <examples>

Fixing child PR after parent was squash merged:

Option 1 - Rebase with --fork-point:

git fetch origin
git checkout feat/auth-login
git rebase --onto origin/main --fork-point origin/feat/auth-base
git push --force-with-lease

Option 2 - Interactive rebase to drop parent's commits:

git checkout main && git pull
git checkout feat/auth-login
git rebase -i main

In the interactive editor, mark all commits from the parent branch as drop.

</examples>

Keeping Stack Updated

<required>

When pulling changes from main into a stack, cascade updates through the stack sequentially:

git checkout feat/auth-base
git merge main
git push

git checkout feat/auth-login
git merge feat/auth-base
git push
  • After each cascade step, run git log --oneline -3 and confirm the tip commit is the merge/rebase you just performed before proceeding downstream
</required> <forbidden>

Merging main directly into a child branch corrupts history:

git checkout feat/auth-login
git merge main
</forbidden>

Best Practices

<examples>

Good stack structure:

  • Each PR is independently reviewable (clear purpose, focused changes)
  • Clear dependency documentation in PR descriptions
  • Commits are atomic within each level
  • Bottom-up merge order maintained

Good communication:

  • Document stack relationships in PR descriptions
  • Update child PRs promptly after parent merges
  • Notify reviewers when dependencies merge
  • Explain the overall feature in parent PR
</examples> <forbidden>

Bad practices:

  • Creating stacks deeper than 3-4 levels (too complex to manage)
  • Merging PRs out of order (breaks dependency chain)
  • Forgetting to update child PRs after parent merge (causes conflicts)
  • Using stacked PRs for unrelated changes (defeats purpose of atomicity)
</forbidden> <related>
  • @smith-gh-pr/SKILL.md - Complete GitHub PR lifecycle
  • @smith-git/SKILL.md - Commits, branches, rebase
  • @smith-gh-cli/SKILL.md - GitHub CLI commands
</related>

ACTION (Recency Zone)

<required>

Merge stacked PRs bottom-up:

  1. Merge parent PR first
  2. Rebase child: git rebase --onto origin/main feat/parent
  3. Force push child: git push --force-with-lease
  4. Delete parent branch after child base updated

Verify stack scope before operations:

./smith-stacks/scripts/verify-stack-scope.sh 'feat/PROJ-*'
</required>