PullNotifier Logo

PullNotifier

Git WorkflowGitHubCode Review

Stacked PRs: The Complete Guide

How to use stacked pull requests to ship faster, get better reviews, and unblock your entire team.

Last updated: February 2026

·

15 min read

Tweet

Table of Contents

1. What Are Stacked PRs?2. Why Use Stacked Pull Requests?3. Stacked PRs vs Large PRs4. How Stacked PRs Work on GitHub5. Step-by-Step Walkthrough6. Handling Review Feedback & Rebases7. Best Tools for Stacked PRs8. Best Practices9. Staying on Top of Stacked PRs10. FAQ

Other Tools

Code Coverage GuideGit Commit Message GuideMerge Request vs Pull RequestIntegrate GitLab with SlackSlack GitHub Actions
See all tools →
PullNotifier — Pull request alerts directly on Slack

What Are Stacked Pull Requests?

Stacked pull requests (also called stacked diffs, dependent PRs, or chained PRs) are a development workflow where a large feature or change is broken into multiple smaller, sequential pull requests that build on top of each other. Each PR in the stack contains a focused, logically coherent change, and each depends on the one before it in the chain.

Instead of one massive 2,000-line pull request that takes days to review, you create a chain of four or five 200-line PRs that reviewers can understand, approve, and merge independently. The first PR targets main, the second targets the first PR's branch, the third targets the second, and so on — forming a "stack" of changes.

The mental model

Think of stacked PRs as a queue of changes ahead of main. New work appends to the queue; approved work lands from the bottom. You're always building forward — never waiting.

Consider building an e-commerce checkout feature. Rather than one giant PR, you'd stack it like this:

Stack Visualization

main

base

Production branch

PR #1 — Database schema

~80 lines · targets main

PR #2 — API endpoints

~120 lines · targets PR #1

PR #3 — UI components

top of stack

~150 lines · targets PR #2

Merge order: PR #1 → PR #2 → PR #3 (bottom-to-top)

This workflow was pioneered at Meta (Facebook) using their internal tool Phabricator, where it's called "stacked diffs." Google uses a similar approach through their internal tools. The concept entered the broader GitHub ecosystem through tools like ghstack and was popularized by Graphite, founded by former Meta engineers who wanted to bring the stacked diffs workflow to GitHub.


Why Use Stacked Pull Requests?

Research analyzing 1.5 million pull requests from top engineering teams found that PRs with 200-400 lines have 40% fewer defects than larger ones, and small PRs (<200 lines) get approved 3x faster. Each additional 100 lines increases review time by 25 minutes. At 1,000+ lines, defect detection drops by 70%.

Unblocked development

Keep coding while earlier PRs await review. No idle time waiting for approvals.

Faster, better reviews

Small PRs (<200 LOC) are reviewed 3x faster and catch 40% more defects than large ones.

Fewer merge conflicts

Frequent integration of small changes keeps everyone in sync with the latest code.

Easier rollbacks

If something breaks, the root cause is isolated to a small, recent change — revert one PR, not fifty files.

Better code design

Breaking work into logical layers forces you to think about clean interfaces and separation of concerns.

Early design feedback

Get architectural feedback on foundation layers before building the full feature on top.


Stacked PRs vs Large Pull Requests

Here's a side-by-side comparison of the traditional "one big PR" workflow versus stacked pull requests:

DimensionLarge / Traditional PRStacked PRs
PR sizeHundreds or thousands of linesTypically <200 lines each
Review timeHours to days — reviewers procrastinate on big diffsMinutes to hours — reviewers engage quickly
Review quality70% lower defect detection at 1,000+ linesHigh effectiveness — focused, line-by-line reviews
Developer blockingIdle while waiting for reviewKeep building on top of pending PRs
Merge conflictsHigh risk — long-lived branches divergeLow risk — frequent small integrations
DebuggingHard — large diff to bisectEasy — small changes isolate root cause
Rollback safetyRisky — reverting pulls back many changesSurgical — revert one small PR
Cognitive loadVery high for reviewersLow — each PR has a single thesis
Tooling requiredNone — native Git workflowRecommended (Graphite, --update-refs, etc.)
Merge strategyAny (squash, rebase, merge commit)Merge commit required (except last PR)

How Stacked PRs Work on GitHub

GitHub does not have built-in support for stacked PRs, but the workflow works natively with standard Git branching. The key insight is simple: each PR targets the previous branch as its base, not main.

  1. PR #1 branches from main and targets main — this is your normal PR.
  2. PR #2 branches from PR #1's branch and targets PR #1's branch as its base. The diff only shows changes introduced in PR #2.
  3. PR #3 branches from PR #2's branch and targets PR #2. And so on.
  4. Merging happens bottom-to-top. Merge PR #1 into main first. GitHub automatically retargets PR #2 to main. Merge PR #2, and PR #3 retargets. Repeat.

Important: merge strategy

You cannot use "squash and merge" on intermediate PRs in the stack. Squash merge rewrites commit history, which breaks the commit references that downstream PRs depend on. Use regular merge commits for all PRs except the last one (which can be squashed).


Step-by-Step: Creating a Stack of Pull Requests

Let's walk through creating a stack of three PRs for an e-commerce checkout feature, using plain Git (no extra tools).

1

Create the first branch and PR

Start from main, create your first feature branch, make your changes, push, and open a PR targeting main.

git checkout main && git pull
git checkout -b feature/checkout-01-schema

# Make your database schema changes
git add -A && git commit -m "Add checkout schema"
git push -u origin feature/checkout-01-schema

# Open PR in GitHub → base: main

Handling Review Feedback & Rebases

The trickiest part of stacked PRs is when a reviewer requests changes to an earlier PR in the stack. Every change to a lower branch must be propagated to all branches above it. Here's how to handle it:

Manual rebase (works with any Git version)

# 1. Fix the issue on the base branch
git checkout feature/checkout-01-schema
# Make changes, commit, push
git add -A && git commit -m "Address review feedback"
git push origin feature/checkout-01-schema

# 2. Rebase each dependent branch, one by one
git checkout feature/checkout-02-api
git rebase feature/checkout-01-schema
git push --force-with-lease origin feature/checkout-02-api

git checkout feature/checkout-03-ui
git rebase feature/checkout-02-api
git push --force-with-lease origin feature/checkout-03-ui

Using --update-refs (Git 2.38+, recommended)

Git 2.38 introduced --update-refs, which automatically updates all intermediate branches during a rebase. This is a game-changer for stacked PRs — one command replaces the entire manual cascade.

# Enable globally (do this once)
git config --global rebase.updateRefs true

# Now rebase the entire stack from the top branch
git checkout feature/checkout-03-ui
git rebase main --update-refs

# All intermediate branches are automatically updated!
# Force-push all branches at once
git push --force-with-lease origin \
  feature/checkout-01-schema \
  feature/checkout-02-api \
  feature/checkout-03-ui

Pro tip: interactive rebase

When you run git rebase -i main --update-refs, the rebase todo file includes update-ref markers for each intermediate branch. You can reorder, squash, or edit commits and the branch pointers will follow automatically.

Using Graphite (automatic)

With Graphite, rebasing is fully automatic. When you modify a branch, all children are restacked in a single command:

# Make changes on any branch in the stack
gt modify -a    # stage all changes and auto-restack children

# Push the entire stack
gt submit --stack

Best Tools for Stacked Pull Requests

While you can manage stacked PRs with plain Git, tooling dramatically reduces friction. Here are the most popular options, from built-in Git features to full commercial platforms.

Graphite

Commercial (free tier)

The most full-featured stacked PR tool. CLI, VS Code extension, web dashboard, and GitHub integration. Automatic rebasing, stack visualization, and a stack-aware merge queue.

Best for: Teams wanting a polished, end-to-end solution

gt create -am "message"
gt modify -a
gt submit --stack
gt log short

git --update-refs

Built into Git (2.38+)

Native Git feature that automatically updates intermediate branches during rebase. No external tool needed — just enable it globally. The foundation for manual stacking.

Best for: Developers who prefer native Git without extra tools

git config --global rebase.updateRefs true
git rebase main --update-refs

ghstack

Open source (Meta)

Python CLI that submits stacked diffs as separate PRs on GitHub. Each commit becomes its own PR. Originally inspired by Meta's internal Phabricator workflow.

Best for: Teams familiar with the stacked diffs mental model (commit = PR)

ghstack
ghstack checkout PR_URL
ghstack land PR_URL

spr (stack-pr)

Open source (Modular)

Lightweight CLI where each commit on a single branch becomes its own PR. No separate branches needed — cleaner than ghstack with fewer branches created.

Best for: Teams wanting a simple, commit-oriented workflow

stack-pr view
stack-pr submit
stack-pr land

Aviator

Commercial (free <15 users)

Platform with open-source CLI for managing stacked PRs. Includes an integrated merge queue for batch processing and sequential merging.

Best for: Small teams wanting stacking + merge queue in one tool

av stack branch <name>
av stack sync
av stack tree

git-branchless

Open source

High-velocity, monorepo-scale Git workflow. Treats commits (not branches) as the primary unit. Smartlog visualization, automatic rebasing, and undo support.

Best for: Monorepo teams comfortable with commit-oriented workflows

git sl
git amend
git next / git prev
git sync

Minimum recommendation

Even if you don't use a dedicated stacking tool, enable rebase.updateRefs globally. It's built into Git, costs nothing, and makes manual stacking dramatically easier.


Best Practices for Stacked Pull Requests

For PR authors

1

Keep each PR under 200 lines

This is the sweet spot where reviewers can be thorough without getting fatigued. Research shows PRs in this range have 40% fewer defects.

2

Give each PR a single thesis

Each PR should be independently understandable. If it doesn't make sense without extensive context from the rest of the stack, restructure it.

3

Split along logical boundaries

Break by architectural layer (schema → business logic → API → UI) or by concern (validation, error handling, feature flag setup).

4

Submit PRs immediately

Don't batch them. The sooner a PR enters review, the sooner you get feedback. Your reviewers can start while you keep building.

5

Mark downstream PRs as drafts

Prevent premature merging of PRs further up the stack before their dependencies are merged.

6

Use descriptive branch names

Clearly communicate stacking order and purpose. Example: feature/checkout/01-schema, feature/checkout/02-api, feature/checkout/03-ui.

7

Use tooling — don't stack manually

At minimum, enable git config --global rebase.updateRefs true. For teams, invest in Graphite or a similar tool.

For reviewers

1

Review bottom-to-top

Start with the base PR (closest to main) and work upward. Understand foundational changes before assessing dependent code.

2

Treat each PR independently

Evaluate it as a standalone change. Each PR should be coherent on its own.

3

Review promptly

Don't wait for downstream approvals before reviewing upstream PRs — this creates bottlenecks that defeat the purpose of stacking.

For teams

  • Agree on PR size limits. Set a team standard of <200 LOC and <24-hour review turnaround.
  • Flag large PRs automatically. Set up CI automations to flag PRs over 250 lines or 25 files and encourage splitting.
  • Enable "Automatically delete head branches" in GitHub settings to simplify stack management after merges.
  • Consider disabling "dismiss stale approvals" to avoid re-review cascades when stacks are rebased.
  • Use a stack-aware merge queue. GitHub's native merge queue doesn't handle dependent PR ordering. Use Graphite, Aviator, or Mergify for stack-aware merging.

Staying on Top of Stacked Pull Requests

Stacked PRs multiply the number of open pull requests your team is managing at any given time. A feature that would have been one PR is now three or five — each needing review, each passing through CI, each getting merged in order. That's a lot of activity to track.

GitHub's built-in notification system (email + bell icon) was already noisy with single PRs. With stacked workflows, it becomes overwhelming. The signal-to-noise ratio drops, and critical events get buried — an approval on PR #1 (which unblocks the rest of the stack) looks the same as a routine comment.

For teams that live in Slack, a dedicated GitHub-to-Slack integration makes stacked PR workflows dramatically more manageable. Instead of polling GitHub, you get real-time alerts in the channels where your team already communicates: PullNotifier sends instant Slack notifications for new PRs, review requests, approvals, CI status changes, and merges — so your team knows the moment a PR in the stack is unblocked and ready for the next review or merge.

This is especially valuable for stacked workflows where merge order matters. When PR #1 gets approved, the reviewer of PR #2 needs to know immediately — not whenever they happen to check GitHub.


Never Miss a PR in the Stack

PullNotifier sends real-time Slack notifications for every pull request event — new PRs, review requests, approvals, CI status, and merges. Keep your stacked PR workflow flowing without constant GitHub tab-checking.

Try PullNotifier FreeView Pricing

Frequently Asked Questions

What are stacked pull requests?

Stacked pull requests (also called stacked PRs, stacked diffs, or dependent PRs) are a development workflow where a large feature is broken into multiple smaller, sequential pull requests that build on top of each other. Each PR in the stack contains a focused, logically coherent change, and each depends on the one before it. Instead of one massive 2,000-line PR, you create a chain of five 200-line PRs that reviewers can understand and approve independently.

How do stacked PRs work on GitHub?

On GitHub, each PR in the stack targets the previous branch as its base (not main). PR 1 targets main, PR 2 targets PR 1's branch, PR 3 targets PR 2's branch, and so on. You merge bottom-to-top: merge PR 1 into main first, then GitHub automatically retargets PR 2 to main. Without tooling, you manage this manually with git rebase. Tools like Graphite or git --update-refs automate the process.

Can you use squash merge with stacked PRs?

Not for intermediate PRs in the stack — only the last one. Squash merge rewrites commit history, which breaks the commit references that downstream PRs depend on. This causes merge conflicts in every dependent PR. You must use regular merge commits for all PRs except the last one in the chain. Some teams accept this tradeoff; others use tools like Graphite that handle squash merging across stacks.

What is the difference between stacked PRs and stacked diffs?

Stacked PRs and stacked diffs describe the same concept with different atomic units. "Stacked diffs" (from Meta/Phabricator) treats each individual commit as the unit for review. "Stacked PRs" (GitHub ecosystem) uses branches, where each branch can have multiple commits. The workflow philosophy is identical: break large changes into small, reviewable units that build on each other sequentially.

What tools help manage stacked PRs?

The most popular tools are: Graphite (full-featured commercial tool with CLI, web UI, and merge queue), git --update-refs (built into Git 2.38+, auto-updates intermediate branches during rebase), ghstack (open source, Meta, commit-oriented), spr/stack-pr (open source, Modular, lightweight), Aviator (commercial with merge queue), and git-branchless (open source, monorepo-scale). At minimum, enable rebase.updateRefs in your Git config.

How many PRs should be in a stack?

Most practitioners recommend keeping stacks to 3-5 PRs. Longer stacks become harder to manage, especially when review feedback requires changes to early PRs (which cascade through the entire chain). If your feature needs more than 5 PRs, consider whether it can be split into independent features or sub-stacks.

Do stacked PRs work with GitHub merge queues?

GitHub's native merge queue does not handle dependent PR ordering — it treats each PR independently. For stack-aware merging, use Graphite's merge queue, Aviator's merge queue, or Mergify, which understand PR dependencies and merge them in the correct order.

Are stacked PRs worth the complexity?

For teams that regularly produce large PRs (500+ lines), the answer is overwhelmingly yes. Research across 1.5 million PRs shows that small PRs (<200 lines) are reviewed 3x faster and have 40% fewer production defects. The learning curve of stacking pays for itself quickly. For solo developers or teams that already write small PRs, the additional tooling may not be necessary.



Other Tools

See all tools →
PullNotifier — Pull request alerts directly on Slack
PullNotifier Logo

PullNotifier

© 2026 PullNotifier. All rights reserved