Skip to content

Instantly share code, notes, and snippets.

@cassiozen
Created May 23, 2025 18:11
Show Gist options
  • Save cassiozen/eb678365a50ba7b874aeeef6ae381ad4 to your computer and use it in GitHub Desktop.
Save cassiozen/eb678365a50ba7b874aeeef6ae381ad4 to your computer and use it in GitHub Desktop.

PR Stacking

Large PRs are a problem: properly reviewing them becomes incredibly difficult, their size makes it easier for bugs to slip through the cracks...

PR stacking offers a solution: breaking big features into a chain of incremental code changes:

What is PR Stacking?

PR stacking is a development approach where large features are broken down into a series of small, dependent pull requests that build upon each other. Instead of one monolithic PR, you create a "stack" of focused changes, each addressing a specific aspect of the feature.

Once all incremental pull requests have been approved, they get merged with main.

Benefits

Improved review quality is the headline benefit: each branch becomes more focused and is easier to review and fix.

Continuous Progress: Engineers stay unblocked. While PR #1 awaits review, work continues on PRs #2, #3, and beyond.

The Basic Stacking Workflow

Let's walk through creating a stack. Suppose we're building a feature that requires API changes, authentication, and user management endpoints.

Start as usual by branching of main:

# From main branch
git checkout -b feature/api-base main
# Implement base API structure
git commit -m "Add base API router and middleware setup"
git commit -m "Add error handling middleware"
git commit -m "Add request logging and monitoring hooks"

Push and create your first PR.

Then, to continue working, create a new branch out of feature/api-base:

# Branch from api-base, not main
git checkout -b feature/api-auth
# Implement authentication layer
git commit -m "Add JWT token generation and validation"
git commit -m "Add auth middleware with role checking"
git commit -m "Add refresh token rotation logic"

Push this branch and create PR #2. The PR will show only the auth-related commits, making it easy to review in isolation. Continue the pattern:

# Branch from api-auth
git checkout -b feature/api-users
# Implement user management
git commit -m "Add user CRUD endpoints"
git commit -m "Add user validation and sanitization"
git commit -m "Add user permission management"

You now have a stack:

main
  └── feature/api-base (PR #1)
        └── feature/api-auth (PR #2)
              └── feature/api-users (PR #3)

Keeping the stack in sync

You have to take care to keep the PRs in the stack in sync.

If a reviewer identifies issues in PR #1, for example, those fixes must propagate through the entire stack.

This can be done with git's rebase and the new --update-refs flag (added on Git 2.38). Here's a practical example:

Fix issues in the base PR:

git checkout feature/api-base
# address review feedback
git commit -m "Fix: Use proper status codes"
git commit -m "Fix: Add input sanitization"

Update the entire stack:

Starting from the topmost branch in the stack:

git checkout feature/api-users  # topmost branch
git rebase --update-refs feature/api-base

This rebases your entire stack while preserving all branch references.

Then push all updates:

git push --force-with-lease origin feature/api-base feature/api-auth feature/api-users

Updating when main moves forward

When main gets new commits that you need, you can use the same pattern to sync your stack:

git checkout feature/api-users  # Topmost branch
git rebase --update-refs origin/main
git push --force-with-lease origin feature/api-base feature/api-auth feature/api-users

Handling conflicts

Conflicts during rebase are handled normally, but --update-refs ensures branch pointers stay correct:

# During rebase, if conflicts occur
# Fix conflicts in your editor
git add .
git rebase --continue
# Repeat for each conflict

The stack structure remains intact throughout the conflict resolution process.

Practical Tips for Stack Management

Make Stacking Your Default

Save yourself typing - add this to your global git config:

git config --global rebase.updateRefs true

Now git rebase automatically includes --update-refs behavior when applicable.

Visualize Your Stacks

Understanding your stack structure prevents mistakes:

# See the structure
git log --graph --pretty=oneline --abbrev-commit feature/api-users

# See which branches point where
git branch -v --contains feature/api-base

Check what needs updating

Before rebasing, see what's out of sync:

# What commits does api-auth have that api-users doesn't?
git log feature/api-users..feature/api-auth --oneline

# What's in main but not in your stack?
git log feature/api-users..origin/main --oneline

Communicate Stack Dependencies

Make it clear in PR descriptions that they're stacked. Something like:

## Stacked PR:

* #5085 👈 (This PR)
* #5083
* #4989
* `main`

which GitHub will render like:

@cassiozen
Copy link
Author

Uploading image...

Screenshot 2025-05-23 at 1 08 54 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment