White Prompt
DevOpsOct 5, 2026 · 6 min read

GitHub Stacked Pull Requests: Breaking a Large Feature into Reviewable Layers

By David Rodriguez

93e431a239561658324303072933bf6b.webp

The ticket looked like one feature. By the time I was ready to open the PR, it was really four.

Two parts could have worked independently, but the request was to deliver all four together as one larger feature. Putting everything into one pull request worked technically, but it created a different problem: reviewing it meant understanding four separate changes at once.

The solution was to split the work into smaller, dependent PRs. Each part could be reviewed separately, while the overall feature remained behind a feature flag until it was ready.

Today, GitHub’s stacked PRs provide native support for this workflow: developers can organize a large change as an ordered chain of smaller PRs, review each layer independently, and merge some or all of the stack together. GitHub announced stacked PRs as a public preview on July 30, 2026.

What are stacked pull requests?

A stacked pull request is one layer in a sequence of dependent PRs.

In a conventional workflow, several branches might all target main:

main
├──feature-part-1
├── feature-part-2
└── feature-part-3

With stacked PRs, each branch is based on the branch immediately below it:

main
└── feature-part-1    
   └── feature-part-2        
      └── feature-part-3            
         └── feature-part-4

Each PR now represents one logical layer of the larger change. The top PR depends on the changes below it, but reviewers can examine each layer independently rather than having to understand the entire feature in one enormous diff.

GitHub describes a stack as an ordered series of pull requests representing focused layers of a change. Each PR has its own diff and can be reviewed and checked independently, while the stack remains connected as a larger unit of work.

This distinction is important: a PR in a stack should be independently reviewable, even if it is not independently shippable. For example, one PR might add a database field, another might introduce the service logic that uses it, and a third might expose the new behavior through an API. The layers depend on one another, but each one has a clear purpose and a manageable scope.

What happened in my first attempt

I did not use stacked pull requests from the beginning.

Instead, after the large PR became difficult to follow, I had to cherry-pick parts of the implementation and build smaller PRs manually. That helped me recover, but it also introduced extra coordination work and made the branch relationships harder to maintain.

Looking back, the better approach would have been to design the dependency chain before writing the code. The goal would not have been to create four arbitrary PRs, but to identify four meaningful layers and make those dependencies explicit from the start.

That is where stacked PRs would have helped.

How I would structure the same ticket today

In my case, I could have organized the ticket like this:

main
└── Part 1: foundational changes
    └── Part 2: first independent improvement
            └── Part 3: second independent improvement
                        └── Part 4: integration and final wiring

The stack would introduce the feature flag early, with later layers keeping the unfinished behavior behind it until the full feature was ready.

That would provide several benefits:

  • Reviewers could focus on one part of the solution at a time.
  • I could continue developing later parts without waiting for the first PR to merge.
  • The feature could remain inactive in production while the stack was still incomplete.
  • Changes and conflicts would be isolated to more focused layers, although modifying a lower layer could still require rebasing the PRs above it.
  • The relationship between the four parts would be visible through the stack rather than hidden inside one large PR.

This would also have made the code easier to navigate. Instead of asking a reviewer to understand a large diff and mentally separate it into four conceptual areas, each PR could explain one milestone in the implementation.

The feature flag is especially useful in this workflow because it separates deployment from release. The code can be merged incrementally without exposing the unfinished feature to users.

In my situation, that means the team could land the foundational changes and individual improvements while continuing to work on the remaining layers.

The GitHub workflow

GitHub’s public-preview implementation supports creating and managing stacks from GitHub.com, the GitHub CLI, GitHub Mobile, and coding-agent workflows. GitHub also provides a CLI extension that can be installed with:

gh extension install github/gh-stack

For my example, the first PR would target main. The next branch would be created from that first layer, and its PR would target the branch below it. The same pattern would continue for Parts 3 and 4.

GitHub recognizes that dependency chain as a stack and displays a stack map at the top of each pull request. Reviewers can therefore inspect only the diff for the layer they are responsible for while still seeing where it fits within the larger change.

This is also what allows development to continue without waiting for every earlier PR to merge. If Part 2 depends on Part 1, I can keep building Part 2 while Part 1 is still under review instead of blocking until the first change reaches main.

The merge behavior is designed for incremental delivery as well. Teams can merge an entire stack or only part of it, but the dependency order is preserved from the bottom upward. If lower layers are merged first, GitHub automatically rebases and retargets the PRs that remain above them. Existing branch protections and required checks still apply to what reaches the stack’s base branch.

For my ticket, that could mean merging the foundational layer first, then landing the independent improvements as they become ready, while keeping the feature flag disabled until the final integration layer is complete.

What I would do differently next time

The biggest lesson for me is not simply that smaller PRs are better.

Splitting a feature into smaller PRs without a clear dependency model can create its own problems. A poorly divided stack can still be confusing, and changing an earlier layer can affect everything built above it. GitHub even describes rebasing as one of the trickier parts of working with stacks, which is why the platform includes cascading rebase support.

The important part is deciding where the logical boundaries are.

Each layer should have a narrow purpose. The changes should be ordered according to their dependencies, and the branch and PR names should make that sequence obvious. A feature flag can protect incomplete functionality when individual layers reach production before the full feature is ready.

Stacked PRs are not a replacement for good architecture or clear communication. They are a way to make the structure that already exists in a large change visible to both the developer and the reviewer.

In my case, stacked PRs would not have changed the architecture of the feature. They would have changed how the team had to reason about it.

Instead of asking a reviewer to process four related changes at once, I could have given them four focused layers while still treating the work as one feature.

One feature does not have to mean one pull request. It can remain a single delivery effort while being divided into several reviewable implementation layers.

The next time a ticket looks simple but contains several dependent changes, that is the model I would reach for first.

Share

Ready to Build Something That Lasts?

Let's talk about your project. We'll bring the engineering judgment and the speed to ship.