Main Branch

Fundamentals first, always

Articles

Give each pull request in a stack one review decision

I tried GitHub's native stacked pull requests on a messy repo with 10 stale drafts and a broken test suite. Here's what stacks fix, what they cost, and how to decide when a change earns the extra branches.

Andrea Griffiths 6 min read 🌐 Read in Spanish 🌐 阅读中文版
Pull Requests Code Review GitHub Stacked PRs Developer Workflow
Listen to article

Leer en español → · 阅读中文版 →

I wanted to try stacked pull requests somewhere messy enough to tell me whether they were useful.

The repo had 10 old draft PRs. Two were separate attempts at dark mode. Two overlapped on flight-delay emails. And npm test failed because a Playwright test lived inside the Jest test directory.

That was the development history in this repo. Work pauses. Context moves. You come back to a queue that needs a shape before it needs more code.

I closed the drafts without deleting their branches, then rebuilt one real fix as three pull requests: test runners first, locale behavior second, browser coverage and CI third.

  • Separate Jest and Playwright so CI can give us a useful signal.
  • Set the document language from the active locale.
  • Add browser coverage and run it in CI.

GitHub rendered the work as a 3/3 stack. Each layer ran CI and CodeQL. The useful result was a review order I could explain: fix the signal, change the behavior, prove the behavior.

The GitHub merge panel showing a 3/3 stacked pull request ready to land

Each layer gives a reviewer one question: test infrastructure, locale behavior, then browser CI. GitHub shows the three PRs as a 3/3 stack.

That experience changed how I think about the oversized PR.

The reviewer has too many jobs

A pull request can be correct, tested, and painful to review.

You start with one reasonable change. Then you need a schema update. Then shared types. Then an API endpoint. Then a UI component. Then tests. Then a refactor because the existing code makes the new behavior awkward.

A few days later, you have an 800-line PR with six kinds of work inside it.

The reviewer has to build the whole feature in their head before they can say anything useful. They need to understand the model, trace the backend behavior, inspect the UI, verify the tests, and decide whether the refactor belongs in the same change.

SmartBear’s code review guidance recommends reviewing 200-400 lines of code at a time. Beyond 400 lines, its guidance says defect detection drops.

The 400-line number is not as important, but when a reviewer must hold too many unrelated decisions at once, that is a challenge.

The branch gets older while that happens. Main keeps moving. Feedback arrives late, often in a pile. Then the author has to separate review changes from branch drift. Large pull requests create a review problem before they create a Git problem.

A stack earns its branches

A useful stack has a dependency order you can explain.

One large diff versus a three-layer stack, where each layer holds one review decision

One large diff asks a reviewer to make six decisions. A stack gives each layer one question.

The model gives the API something real to build on. The API gives the UI a contract. A reviewer can make one decision at a time and still see where the work is going.

A 600-line rename can still be one coherent pull request. A 120-line change across auth, persistence, and UI can hold three separate decisions. Line count helps you notice trouble. The decision tells you where to cut.

I use four questions before I create a stack:

  • Can the lower layer land safely on its own, or behind an appropriate flag?
  • Will feedback on the lower layer reshape the work above it?
  • Can a reviewer assess this layer without reconstructing the entire feature?
  • Does the branch order match the real implementation dependency?

If the answers are yes, the extra branches earn their keep.

Watch the whole stack, not just each split. Three layers that pass the test on their own can still add up to a review that costs more than a single well-shaped PR would. If you land at four or five layers, look at the work again. Either it holds that many separate decisions, or the branching became the point.

A lower layer can also stall while upper branches accumulate, concentrating risk and coordination pressure at the bottom of the stack.

When feedback changes the foundation, revisit the layer above it. If its review question changed, reshape or rebuild it.

Changes to a lower layer still cascade into rebase and conflict-resolution work in every branch above it.

Some work needs to stay together. If a reviewer needs the UI and API in the same diff to judge the behavior, keep them together. The goal is a useful review, not a tidy branch diagram.

Agents make oversized diffs faster

Coding agents make feature-sized diffs cheap. Your agent is fast. Your reviewer is a person with a coffee.

I have seen the 2,000-line agent pull request. It may contain good work. It also asks someone to trust a model, an API, a UI, test coverage, and a pile of generated glue all at once.

Give the agent a review shape before it starts. Ask it to identify the dependency order, build the foundation first, and keep each layer centered on one question a reviewer can answer.

That changes the output from one enormous branch into work the team can actually discuss.

Native stacks keep reviews and checks in place

Dependent branches are old Git. The work around them has always been the painful part.

GitHub’s native stacks keep the policy connected to the whole chain. Each PR is evaluated against the stack’s final base, usually main, so required reviews, CODEOWNERS, and checks keep applying as the work moves upward.

Merge the highest PR to land the whole stack. If you merge only part of it, GitHub rebases the layers that remain.

One knock-on effect: because every PR runs its checks against the stack’s base, CI usage multiplies with stack size. GitHub exposes github.event.pull_request.stack.position and .size in workflow expressions, so you can run the fast checks on every layer and reserve the full suite for the top PR or the lowest unmerged one. The API handles the wiring; the workflow choice is yours.

I wanted to test that in the demo repo. The three layers all ran their checks. The stack map made the dependency explicit. The system understood the shape of the work instead of making reviewers infer it from branch names and commit history.

Start where the decisions split

Start with two layers. Pick a feature where the foundation and the behavior already feel like separate review conversations. Open the foundation early. Let feedback arrive before the work above it hardens.

The short workflow is:

gh extension install github/gh-stack
gh stack init
gh stack add <branch>
gh stack submit

The official GitHub walkthrough covers the commands and agent setup at gh.io/stacks. Read that when you are ready to build.

On your next feature, find the first independently reviewable decision and open that PR early.

About the Author: Andrea Griffiths is a Senior Developer Advocate at GitHub, where she helps engineering teams adopt and scale developer technologies. She's passionate about making technical concepts accessible—to both humans and AI agents. Connect with her on LinkedIn, GitHub, or Twitter/X. · Read in Spanish · 阅读中文版