Every engineer who has worked on a substantial feature knows the feeling: you’ve spent days — maybe weeks — building something, and now it’s time to open a pull request. You stare at the +2,847 −412 diff and know, deep down, that no reviewer is going to give this the attention it deserves. The feedback will be superficial. The merge will be delayed. And three weeks later, someone will discover a bug that a proper review would have caught.
Large pull requests are one of the most persistent productivity killers in software engineering. They slow down reviews, increase defect rates, and create merge conflicts that cascade through your team’s backlog. After twenty years of building production systems across Go, TypeScript, PHP, .NET, and Rust, I’ve seen this pattern play out at startups and enterprises alike. The solution isn’t “write smaller PRs” — that’s obvious. The challenge has always been how to break work into small PRs when the changes are inherently interdependent.
GitHub’s newly announced Stacked PRs feature (currently in private preview) finally brings native support for a workflow that high-performing teams have been hacking together for years. Let me walk you through what stacked PRs are, why they matter, and how to start using them effectively.
The Problem with Monolithic Pull Requests
Research from Google and Microsoft has consistently shown that review quality degrades significantly when PRs exceed 200-400 lines of changed code. Yet most real-world features — adding authentication, building an API layer, refactoring a data model — naturally produce diffs far larger than that.
The conventional advice is to break these into smaller PRs. But here’s the friction: if your API endpoints depend on your auth layer, and your frontend depends on both, you end up with a chain of PRs where each one targets the branch of the previous one. Managing that manually is a nightmare. Rebase one layer, and every layer above it needs updating. A reviewer requests changes on PR #2? Now you’re rebasing PRs #3 through #7 by hand.
What Are Stacked PRs?
A stack is a series of pull requests where each PR targets the branch of the PR below it, forming an ordered chain that ultimately lands on your main branch. Instead of one massive PR, you get a sequence of small, focused, independently reviewable changes.
For example, building a user authentication feature might break down into:
- PR #1 (auth-layer): Core authentication middleware and session management
- PR #2 (api-routes): API endpoints that use the auth middleware
- PR #3 (frontend): Frontend login/logout components that consume the API
Each PR is small enough for thorough review, yet together they form a complete feature. GitHub now understands these stacks natively — the PR UI shows a stack map for navigation, branch protection rules are enforced against the final target branch (not just the direct base), and CI runs for every PR as if targeting main.
Getting Started with gh stack
GitHub provides a CLI extension that handles the entire local workflow. Install it and start stacking:
# Install the CLI extension
gh extension install github/gh-stack
# Optional: alias for easier use
gh stack alias
# Initialize a new stack
gs init auth-layer
# Make your commits for the auth layer...
# Add a new layer on top
gs add api-routes
# Make commits for the API routes...
# Add another layer
gs add frontend
# Make commits for the frontend...
# Push all branches to GitHub
gs push
# Create the stack of PRs in one command
gs submit
That’s it. gs submit opens a stack of interconnected PRs on GitHub, each with the correct base branch set automatically. Reviewers see the stack map in the PR UI and can navigate between layers.
Managing the Stack: Rebases and Merges
This is where stacked PRs truly shine compared to manual branch chains. When a reviewer requests changes on a lower layer, you make your fixes and rebase:
# Rebase the entire stack from a specific layer
gs rebase auth-layer
# Push the updated stack
gs push
The CLI handles the cascading rebase across all layers automatically. When you merge PRs, the remaining layers are automatically rebased so the lowest unmerged PR targets main. No more manual branch juggling.
Practical Pattern: The Review-First Stack
Here’s a pattern I’ve found highly effective for production features. Start with a design layer that contains only interfaces, types, and documentation — no implementation. This gives reviewers a chance to validate the architecture before you invest in building it out.
// PR #1: Design layer — interfaces and types only
package auth
// Session represents an authenticated user session.
type Session struct {
UserID string
Roles []string
ExpiresAt time.Time
}
// Authenticator validates credentials and creates sessions.
type Authenticator interface {
Login(ctx context.Context, email, password string) (*Session, error)
Logout(ctx context.Context, token string) error
Validate(ctx context.Context, token string) (*Session, error)
}
// PR #2: Implementation layer — concrete types
type JWTAuthenticator struct {
secret []byte
duration time.Duration
}
func (a *JWTAuthenticator) Login(ctx context.Context, email, password string) (*Session, error) {
// Implementation...
}
// PR #3: Integration layer — HTTP handlers
func RegisterRoutes(mux *http.ServeMux, auth Authenticator) {
mux.HandleFunc("POST /api/login", loginHandler(auth))
mux.HandleFunc("POST /api/logout", logoutHandler(auth))
}
Reviewers can validate the design in PR #1 quickly — it’s just types and interfaces. By the time they review PRs #2 and #3, they already understand the architecture, making the implementation review much faster and more focused.
When to Use Stacked PRs (And When Not To)
Stacked PRs aren’t the right tool for every situation. Here’s a practical decision framework:
Use stacked PRs when:
- A feature naturally decomposes into sequential layers (foundation → business logic → integration)
- Your diff is going to exceed 400 lines and can be logically separated
- Multiple reviewers with different expertise need to focus on different parts
- You want early design feedback before investing in implementation
Skip stacking when:
- The change is small enough for a single well-scoped PR (under 300 lines)
- Layers would be tightly coupled — reviewers need to see everything together
- You’re fixing a bug or making a hotfix — speed matters more than review ergonomics
AI Agent Integration
One of the most forward-looking aspects of GitHub’s implementation is first-class AI agent support. You can teach your AI coding agents to work with stacks:
# Teach your AI agent how to work with stacks
npx skills add github/gh-stack
This means AI coding assistants can break up a large diff into a stack or develop with stacks from the start. As AI-assisted development becomes the norm, having a structured workflow that both humans and agents can follow is a significant advantage.
The Bigger Picture: Small PRs as a Discipline
Stacked PRs are a tool, but the underlying discipline — breaking work into small, reviewable units — is one of the most impactful skills a software engineer can develop. Small PRs:
- Reduce bugs: Reviewers catch more issues in focused diffs
- Speed up delivery: Parallel review of independent layers moves faster
- Improve documentation: Each PR has a clear, self-contained purpose
- Reduce risk: Smaller merges mean smaller blast radius when something goes wrong
- Enable better rollback: You can revert one layer without losing the entire feature
The teams I’ve seen consistently deliver high-quality software at speed all share one trait: they treat code review as a first-class part of the development process, not an afterthought. Stacked PRs make that discipline easier to maintain.
Getting on the Waitlist
GitHub Stacked PRs is currently in private preview. You can sign up for the waitlist at gh.io/stacksbeta. In the meantime, the gh stack CLI extension is available now and works with existing GitHub PR workflows — you can start practicing the discipline even without the full native UI.
If you’re already using tools like git-absorb, graphite, or stacked-git, the transition will be natural. The key difference is that GitHub’s implementation integrates directly with the PR review experience your team already uses — no new platforms, no context switching, no adoption friction.
Wrapping Up
The craft of software engineering isn’t just about writing code — it’s about how we structure, review, and deliver that code. Large, monolithic PRs have been a quiet productivity tax on teams for decades. GitHub’s native Stacked PRs, combined with the gh stack CLI, finally gives us an ergonomic way to practice what we’ve always known: small, focused changes reviewed thoroughly ship faster and with fewer defects.
Start small. Pick your next feature, sketch out the layers, and try a two or three-layer stack. The workflow becomes natural after just a couple of iterations, and your reviewers will thank you.