Stacked diffs vs Pull Requests

Amarilis Dias
MCTW_TDW
Published in
5 min readJan 30, 2023

Introduction

In a git-based workflow, Pull Requests are a fairly ubiquitous way of working. Platforms like GitHub and Gitlab helped make it mainstream. But as the apps we develop continue to evolve in complexity, with multiple engineers working on the same product, a new way to approach code review has emerged, which promises faster ships and a better development experience.

But are stacked diffs the inevitable future of code reviews? Or are they just a fad?

Analyzing Pull Requests

In a pull request-based workflow, a new feature is created in a new branch, which is then iterated on through a series of commits until all reviewers are happy. That new branch is then merged into the main branch.

Visual representation of a typical pull request workflow

In this view, a Pull Request (PR) represents “an atomic unit of code for review” (as mentioned in this blog post). Whenever the reviewer provides feedback, you have to commit more code to the same branch. This often means pull requests with a long string of commit messages, with the last commits being something along the lines of “addressing feedback” “fixes”, or other equally vague descriptions.

While the short-term productivity losses are not immediately clear, longer-term, this workflow might lead to a loss of productivity. Imagine that, a few months down the road, something breaks in production. To be able to debug and parse the list of past commits, seeing vague messages like “final fixes” are not helpful to search for the culprit commit.

This workflow also starts breaking when working at scale. Imagine that a developer, Ana, is working on a bug fix. She creates a new branch, commits her work, and pushes it to remote to create a new Pull Request. While she’s waiting for someone to review her code, she then starts working on a new feature. She creates another branch, only to realize that work is dependent on the bug fix that is still up for review. She realizes it’s too much work to create a branch off the bug fix that is still up for review, so she’s blocked until that PR is merged to main.

Visual representation of two branches where the second branch is blocked by the first branch

To prevent this scenario where they are blocked, developers might start to push pull requests covering all the changes for a particular feature. This leads to more lines to review and, inevitably, no one will take an hour from their day to review hundreds of new lines of code.

Stack diffs — a potential solution?

To address these shortcomings and improve developer productivity, bigger organizations like Facebook and Google have started adopting a new internal code reviewing system.

Tools like Phabricator and, more recently, Graphite have enabled engineers to ship their code using stacked diffs, or stacked changes.

But what are stacked diffs?

In a nutshell, stacked diffs change the mental model for the way you work: instead of thinking about your code in terms of branches, your code is actually a queue of changes ahead of main.

Visual representation of stacked diffs

This means that instead of creating a new, clean branch for every new change in your codebase, you always work in the main branch. Its concept is very similar to the git-branchless workflow.

For each code commit, you’ll ask the tool to generate a “diff” which will then “land” on top of main. Unlike Pull Request, stacked diffs are based on exactly one commit. So if someone reviews the code and asks for a change, you can update your codebase locally and ask the platform to update your remote. When a diff gets approved, it will get merged into main.

As the author of the blog post Stacked diffs vs Pull Requests describes:

“The big “aha!” idea here is that units of code review are individual commits and that those commits can stack arbitrarily because they’re all on one branch.”

This leads to smaller chunks of code for review, which leads to less waiting time and way cleaner code.

Since we’re working ahead of the main branch, rebasing is not as frowned upon as your typical git workflow. Most tools already optimize for this process, automatically rebasing each diff as they land on top of the main branch.

Visual representation of a rebasing workflow

Dependencies are also minimal with this approach. We’re not dealing with an entanglement of branches that are dependent on each other — we’re dealing with a first in, first out queue. If a diff is ready to be landed on main, it gets sent to the front of the queue.

So what’s the caveat?

Essentially, lack of adoption. Most companies adopted the pull request-based workflow a long time ago, and it’s time-consuming to rethink their processes from the ground up.

Most mainstream git hosting platforms (GitHub, Gitlab, Bitbucket), also rely on the more traditional pull request-driven workflow, and unless they help popularize this method, we’ll continue relying on third-party software to achieve the same result.

Conclusion

Pull Requests have been the norm for code reviews for years. While it definitely continues to be the most popular option for code collaboration and review, a new wave of developers defending stacked diffs continues to emerge.

Google and Facebook are already fans of stacked diffs, which shows that the traditional method is probably not the most efficient way of working.

Are we going to see a shift in the way we review code in the next couple of years? Only time will tell.

Acknowledgments and Resources

A few articles were essential to explain stacked diffs and help me form my own opinion. I’ve used this blog post extensively as a source for this article.

Links

https://jg.gg/2018/09/29/stacked-diffs-versus-pull-requests/
https://www.phacility.com/phabricator/
https://twitter.com/acdlite/status/1255634586731593728
https://docs.graphite.dev/
https://google.github.io/eng-practices/review/developer/small-cls.html
https://graphite.dev/blog/post/DThX8ffP1gmxWJChEv0y

--

--