Stacked PRs
Break large features into small, reviewable PRs that depend on each other. Merge in order for clean history.
Quick Reference
main ──────────────────────────────────────────● / PR #3 (final) ─────────────────────────●────┘ ← Merge last / PR #2 (middle) ────────────────────●──┘ ← Depends on #1 / PR #1 (base) ────────────────●── ← Merge first / feature/auth ──────●────●────● ← Development
Workflow
- Plan the Stack
Identify logical chunks
Example: Auth feature
PR 1: Add User model + migrations
PR 2: Add auth service + tests
PR 3: Add login UI + integration tests
- Create Base Branch
git checkout main git pull origin main git checkout -b feature/auth-base
Implement first chunk
git add -p git commit -m "feat(#100): Add User model" git commit -m "feat(#100): Add user migrations"
Push and create first PR
git push -u origin feature/auth-base
gh pr create --base main --title "feat(#100): Add User model [1/3]"
--body "## Stack
- PR 1/3: User model (this PR)
- PR 2/3: Auth service (depends on this)
- PR 3/3: Login UI (depends on #2)
Changes
- Add User model with validation
- Add database migrations"
- Stack Next PR
Branch from first PR's branch (not main!)
git checkout -b feature/auth-service
Implement second chunk
git add -p git commit -m "feat(#100): Add auth service" git commit -m "test(#100): Add auth service tests"
Push and create PR targeting FIRST branch
git push -u origin feature/auth-service
gh pr create --base feature/auth-base
--title "feat(#100): Add auth service [2/3]"
--body "## Stack
- PR 1/3: User model (#101)
- PR 2/3: Auth service (this PR)
- PR 3/3: Login UI (depends on this)
Depends on #101 - merge that first"
- Continue Stacking
git checkout -b feature/auth-ui
Implement third chunk
git commit -m "feat(#100): Add login form" git commit -m "test(#100): Add login integration tests"
git push -u origin feature/auth-ui
gh pr create --base feature/auth-service
--title "feat(#100): Add login UI [3/3]"
Managing the Stack
When Base PR Gets Feedback
Make changes to base PR
git checkout feature/auth-base git add -p git commit -m "fix: Address review feedback" git push
Rebase dependent PRs
git checkout feature/auth-service git rebase feature/auth-base git push --force-with-lease
git checkout feature/auth-ui git rebase feature/auth-service git push --force-with-lease
When Base PR Merges
After PR #1 merges to main
git checkout main git pull origin main
Update PR #2 to target main now
gh pr edit 102 --base main
Rebase PR #2 on main
git checkout feature/auth-service git rebase main git push --force-with-lease
Repeat for PR #3 after #2 merges
Stack Visualization
Track your stack with comments:
PR Stack for Auth Feature (#100)
| Order | PR | Status | Branch |
|---|---|---|---|
| 1 | #101 | Merged | feature/auth-base |
| 2 | #102 | Review | feature/auth-service |
| 3 | #103 | Draft | feature/auth-ui |
Merge order: #101 -> #102 -> #103
Automation Script
#!/bin/bash
stack-rebase.sh - Rebase entire stack after changes
STACK=( "feature/auth-base" "feature/auth-service" "feature/auth-ui" )
BASE="main"
for branch in "${STACK[@]}"; do echo "Rebasing $branch onto $BASE..." git checkout "$branch" git rebase "$BASE" git push --force-with-lease BASE="$branch" done
echo "Stack rebased successfully!"
Tools for Stacked PRs
GitHub CLI Extensions
Install stacked PR helper
gh extension install dlvhdr/gh-dash
View PR dependencies
gh pr view --json baseRefName,headRefName
Third-Party Tools
-
Graphite - graphite.dev (full stack management)
-
Stacked - stacked.dev
-
git-branchless - github.com/arxanas/git-branchless
Best Practices
DO: ✅ Keep each PR < 400 lines ✅ Make each PR independently reviewable ✅ Document the stack in PR descriptions ✅ Number PRs clearly [1/3], [2/3], [3/3] ✅ Use draft PRs for incomplete stack items ✅ Rebase after feedback, don't merge
DON'T: ❌ Create circular dependencies ❌ Stack more than 4-5 PRs deep ❌ Leave stacks open for > 1 week ❌ Force push to already-approved PRs ❌ Merge out of order
When NOT to Stack
-
Small features (< 300 lines total)
-
Unrelated changes
-
Urgent hotfixes
-
Single-purpose refactors
PR Template for Stacked PRs
Summary
Brief description of this PR's changes
Stack Position
- PR 1/N: Description (#xxx) - [Status]
- PR 2/N: This PR
- PR 3/N: Description (#xxx) - [Status]
Dependencies
Depends on: #xxx (merge that first) Blocks: #xxx (must merge this first)
Changes
- Change 1
- Change 2
Test Plan
- Tests added
- CI passes
Related Skills
-
git-workflow: Branching, commits, and recovery patterns
-
create-pr: PR creation basics
References
-
Stack Management
-
Rebase Strategy