smith-stacks
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.
When & Why to Use This Skill
This Claude skill optimizes large-scale feature development by implementing advanced stacked pull request (PR) workflows. It provides comprehensive guidance on creating, managing, and rebasing dependent PRs to ensure atomic, reviewable changes and streamlined merge sequences, significantly improving code review efficiency and repository health.
Use Cases
- Breaking down massive features (500+ lines) into smaller, logical, and independently reviewable pull requests to accelerate the peer review process.
- Managing complex dependency chains where multiple PRs rely on unmerged base code, ensuring the correct bottom-up merge order and branch hierarchy.
- Handling technical rebases and updates for child branches after a parent PR has been squash-merged, preventing duplicate commits and messy merge conflicts.
- Maintaining a clean and navigable Git history by enforcing best practices for branch deletion and sequential updates across a multi-level stack.
| 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
- 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
CRITICAL (Primacy Zone)
- 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
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
Creating Stacked PRs
How to stack:
- Create base PR with foundation (e.g.,
feat/auth-base) - Create child PR branching from base (e.g.,
feat/auth-loginfromfeat/auth-base) - Each PR should be independently reviewable and mergeable
- Merge bottom-up: base first, then children
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)
Stacked PR Merge Workflow
Sequential merge order (bottom-up):
- Wait for parent PR approval
- Merge parent PR into
main - Rebase child PR onto updated
main - Get child PR approved
- Repeat for each level in stack
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)
Rebasing After Parent Merges
When a parent PR merges, child PRs must be rebased:
- Fetch latest changes
- Checkout child branch
- Rebase onto updated main
- 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.
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)
Squash Merge with Stacked PRs
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
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
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.
Keeping Stack Updated
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
Merging main directly into a child branch corrupts history:
git checkout feat/auth-login
git merge main
Best Practices
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
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)
@smith-gh-pr/SKILL.md- Complete GitHub PR lifecycle@smith-git/SKILL.md- Commits, branches, rebase@smith-gh-cli/SKILL.md- GitHub CLI commands
ACTION (Recency Zone)
Merge stacked PRs bottom-up:
- Merge parent PR first
- Rebase child:
git rebase --onto origin/main feat/parent - Force push child:
git push --force-with-lease - Delete parent branch after child base updated