How stacking works

What is a stack?

A stack is a sequence of dependent code changes (pull requests), each building off of its parent. Stacks enable users to break up a large engineering task into a series of small, incremental code changes, each of which can be tested, reviewed, and merged independently.

Benefits of stacked changes

Stacking encourages PRs to act as self-contained units of change for developing and reviewing. These are some of the main benefits for adopting stacking:

  • Incremental development: Stacking encourages you to organize complex features into smaller, manageable pieces—allowing you to land changes faster.

  • Parallel workstreams: Each stack represents a specific piece of functionality, making it easier to understand, develop, and review. This allows you to stay unblocked, working on the next self-contained PR while you wait for code review on another one.

  • Better code review: Receive feedback on small, easy-to-grok changes. This leads to shorter review times and less re-reviews. You can also more easily bisect and roll back if something goes wrong.

  • Tighter collaboration: Stacking allows developers to collaborate on shared stacks and avoid and resolve merge conflicts more efficiently.

Many of the largest companies have built internal code review platforms that support and encourage engineers to work with stacked changes, such as Critique (Google) and Phabricator (Facebook, Dropbox, Uber, Pinterest, Quora, Twitter).

Creating a good stack

  • Create self-contained, atomic PRs—ideally that are 50–100 lines long.

  • Each stack should focus on a cohesive change or feature. Don't mix mostly unrelated changes within the same stack.

  • Stacks with dependencies should be ordered correctly to ensure they're merged in the right sequence.

  • Keep stacks small and focused to maintain manageability and ease of review.

How Graphite implements stacked changes

In Graphite, a stack is represented by a directed, acyclic graph (DAG) of dependent git branches. We chose to compose stacks of branches rather than commits because, on GitHub, branches are the smallest discrete unit of CI and code review.

Graphite extends Git's commits and branches with a third unit—stacks. A Graphite stack is a chain (DAG) of dependent branches. Graphite tracks stacks by recording parent relationships between branches through git refs.

Whenever you move a parent branch forward by a commit or rebase, Graphite uses its persisted metadata to remember the DAG of branches and automatically rebase them to keep your stack up-to-date.

The metadata is stored in your repo in the form of refs, visible at .git/refs/branch-metadata/. All information stays within git and can be synced to and from remote repositories.

References

Here are some helpful blog posts and papers on the topic: