Stacked Pull Requests on Github

Patrick Shuff
eFuse Engineering
Published in
4 min readMar 26, 2021

At eFuse we write a lot of code which is all peer reviewed by at least one other member of the engineering team. Research has shown that the larger a pull request, the longer it takes to review, the review is less effective, and the more likely it is to break something. As such, when working on large features that span many files and many lines of code, we prefer to break down into small chunks of code that build off of each other. This has many benefits for our team:

  1. It allows the engineering team to see the thought process of the author along each step of the implementation
  2. It allows for more efficient reviews of PRs as each pull request is limited in scope size
  3. Allows for feedback much earlier in the implementation process
  4. Huge efficiency for the authors as it allows them to put a portion of their code up for review while continuing to build it in a stacked branch (as opposed to putting it all up for review once it is complete)
  5. The code being merged is much smaller in scope and less likely to cause issues. If something breaks it is much easier to identify the faulty code path

1. Install git-town

The first step is to install git-town with is a workflow layer on top of vanilla git. It makes creating stacked pull requests incredibly simple and has some additional functionality for keeping your stack of PRs in sync.

brew install git-town

More details/other platform instructions here:
https://www.git-town.com/install.html

2. Create a new feature branch, commit changes, open pull request

To create a new feature_branch it is as simple as:

git town hack new_feature-new_db_model

This will pull in latest changes from origin/main and create a new branch off of it.

Next, make some changes to your code, and commit them:

git commit -m "Adding new database models for new feature"

Then, use git town to create a new pull request:

git town new-pull-request

This will sync your local branch to github and open the new PR creation in your browser.

3. Create a stacked PR dependent on your first one

The workflow is the exact same as above, except you use git town append :

# Create new dependent branch
git town append new_feature-add_express_controller
# Commit it
git commit -m "Adding the express controllers for new feature"

4. Continue writing code and creating new PRs

….same as #3

Once you have done this, you’ll have a stack of pull requests:

If you look at the first PR the upstream branch is main :

But the subsequent PRs are now stacked on top of this one:

Once your code reviewed, start merging in order!

Once your code is reviewed, you can start merging. Once you have merged a parent branch and deleted it, github will automatically rebase the PR on top of main.

Branches are automatically rebased to main upon it’s parent base branch being deleted.

NOTE: You _must_ delete the branch for github to automatically rebase to main. I recommend that you set your repository to automatically delete branches upon merge.

That’s it!

Appendix: How do I keep all of my PRs in sync if I change one of my upstream branches?

This is where the git-town workflow tool really shines.

Continuing with our example above, say you have changes to make to the first:

git checkout new_feature-new_db_modelgit commit -m "Updating XX based on PR feedback"# This will keep your local changes consistent with origin
git town sync

To make sure every single branch in your stack receives these changes, just checkout the last branch in your pull request, and run git town sync

# Checkout the last PR in the stackgit checkout new_feature-last_pr_branch# Synchronize every single PR in the stack with latest changes
git town sync

That’s it! 💯

--

--