You opened the link your teammate sent you. There are four pull requests. They reference each other. You scroll the diff of PR #3 and recognise lines you’ve already seen in PR #2. You sigh, close the tab, and reach for coffee.
It doesn’t have to be like this. Reviewing a stacked PR is faster than reviewing one giant PR — once you know the rhythm. This article is the rhythm.
The mental model
A stacked PR is not one big change presented across four pages. It’s four independent (but linearly-ordered) changes — each one reviewable on its own merits. Specifically:
- PR #1 changes things relative to
main. - PR #2 changes things relative to PR #1’s tip. Its diff doesn’t include PR #1’s lines.
- PR #3 changes things relative to PR #2’s tip.
- PR #4 changes things relative to PR #3’s tip.
The diff GitHub or GitLab shows you for each PR is already scoped to just that step. If you scroll PR #3 and recognise lines from PR #2, your provider’s UI is fighting you (this happens occasionally with old views or unusual configurations) — the canonical view of each PR is the diff at its target branch.
Read those four diffs in order, and you’re reading four small changes. None of them is a 4,000-line monster.
The bottom-up rule
Always review a stack bottom-up. That means:
- Start with the bottom PR (whatever’s targeted directly at
main/master/trunk). - Land it (or approve and let the author land it).
- Move up one PR. Now its diff is “what was added on top of the previous step.”
- Repeat.
Don’t try to read the top of the stack first. The top of the stack assumes the bottom of the stack landed; without that context, lines and APIs reference things that won’t exist on main yet.
If you’re tempted to read top-down because the top PR has the “interesting” code in it, resist. Trust the bottom-up flow — the interesting code will still be interesting when you get there, and you’ll understand it better with the foundation already in your head.
What to look for in each PR
A practical checklist:
For the bottom PR (touching main)
This is the foundation. It often contains:
- Schema migrations — verify forward and backward compatibility.
- New abstractions, interfaces, or types — these define the contract everything above will use, so they get the most rigorous review.
- Feature flags — if there’s one, make sure it defaults to off.
Approving the bottom PR is a commitment: every higher PR is built on it. So if you have doubts about the foundation, hold up the bottom PR. The author would much rather know now than after they’ve stacked three more on top.
For middle PRs
Middle PRs are the meat of the change. They’re usually:
- Implementation that uses the abstractions established below.
- New behavior behind whatever feature flag the foundation defined.
Look for:
- Single-purpose. Each middle PR should do one thing well. If you see two unrelated changes in one PR, ask the author to split —
gtmakes this easy. - Reversible. If this PR introduced a bug, could it be reverted on its own without dragging the rest of the stack down? If not, that’s a signal the split is wrong.
For the top PR
The top PR is often:
- Tests, docs, or the user-facing wiring (the UI update, the API route, the CLI flag).
- The feature-flag flip that enables the whole change.
This is the PR you can usually approve quickly — by the time you get here, you’ve already approved every dependency.
Approve and land as you go
The biggest mistake reviewers make on stacked PRs is treating them as one logical unit: “I’ll wait until I’ve reviewed all four, then approve all four.”
Don’t do that. Approve each PR as you finish it, and let the author land it.
Why:
- The author wants the bottom to land so they can stop maintaining four PRs in their head.
- The smaller
maingets ahead of the stack, the easier any restacks become. - The smaller the open-PR queue, the easier it is for anyone (you, the author, other reviewers) to keep mental track.
- If you wait to approve all four, you’re back to the bad equilibrium that stacking was meant to fix.
If the bottom PR is good to land on its own, land it. Don’t gate it on “the rest of the stack also being good.” The point of stacking is exactly that the bottom can ship while the top is still in flight.
Commenting across the stack
A common scenario: you spot a problem on PR #3, but the right fix actually belongs on PR #1. What do you do?
Comment on PR #3 (where you found the symptom) and link to PR #1 (where the fix belongs). Tag the author. They have two clean options:
- Fix in place on PR #1, then
gt restackto propagate the change up to PR #2, #3, #4. Provider UIs will show the propagated commits on each PR. This is the right move if the fix is small. - Open a fresh PR on top of the stack (PR #5) that fixes the symptom directly, leaving the foundation alone. This is the right move if the fix is large enough that touching PR #1 would invalidate review work that’s already done.
Either is fine. The author chooses. Your job is to flag the problem clearly.
”I think this whole PR is wrong”
Sometimes the right feedback isn’t “fix line 47” but “this whole approach won’t work.” On stacks, this is much better than on monster PRs:
- If it’s the bottom PR, you’ve caught the issue before any dependent work was stacked on top. Block the bottom PR and ask the author to rethink.
- If it’s a middle PR, the bottom may still be salvageable. Comment that you’re approving the bottom but blocking the middle, and explain why.
- If it’s the top PR, the issue is usually local to that step. The middle and bottom can still land.
In every case, the stack contains the damage. You’ve never accidentally approved a giant PR that contains the bad idea buried in line 2,300.
When gt restack updates the PRs
After you’ve left comments and the author runs gt restack followed by gt submit --stack, the PRs above the changed one get force-pushed. You may get a “force-pushed since your last review” warning on GitHub or GitLab.
This is normal. The diff you’ve already reviewed on the higher PRs is not what changed — only the base against which that diff is computed is different. The set of added lines should be the same.
A good provider UI shows you “what changed since your last review” as zero (or near-zero) lines when this happens. If it shows large changes, that’s a signal the author edited content during the restack, and you should re-review.
Approving a draft
A small process tip: if your team uses draft PRs in the middle of stacks (because the author is still working on top), you can still leave review comments and approvals on drafts. The author will mark them “ready for review” when the time is right, and your approval will count. Don’t wait until everything is non-draft to start reviewing — you’ll create exactly the bottleneck stacking was meant to remove.
Tooling that helps
- stkd’s
gt login the author’s repo shows the whole stack with PR numbers. If you have repo access, run it yourself to ground your reviewing in the actual stack structure. - stkd’s optional web dashboard gives reviewers a Graphite-web-style view of every stack across the team.
- GitHub’s “Files changed” for each PR shows just that PR’s changes — use it, not “Conversation,” to understand the diff.
- GitLab’s “Changes” tab does the same, with the bonus that GitLab auto-retargets dependent MRs to
mainas the bottom merges.
A worked review session
Here’s what a 20-minute review of a 4-PR stack looks like in practice:
00:00 Open PR #100 (the bottom). Read the description. Skim files changed.
00:03 ✓ Approve PR #100 — it's a clean schema migration with a backfill.
00:04 Open PR #101. Read description. Files changed against PR #100's tip.
00:09 Leave one inline nit. ✓ Approve.
00:10 Open PR #102. Read description.
00:14 Spot a concern: this PR adds a route, but doesn't add a test.
00:15 Comment: "Can we get one test that hits the new route? Otherwise lgtm."
00:16 Move on to PR #103. Read description, files changed.
00:19 ✓ Approve — it's the UI wiring + docs, and it's clean.
00:20 Done.
Twenty minutes for four PRs you’d otherwise have spent two days reviewing as one giant blob. The author can land #100 and #101 immediately, has a clear path on #102 (one missing test), and #103 is ready as soon as #102 lands.
This is the rhythm. Once you have it, stacks feel faster, not slower.