In Software Engieerning, we all have seen this meme:
It’s not only about writing the code, but also being able to be reviewed effectively by peers.
Therefore, pull requests with smaller diffs are always preferred.
However, developers face many challenges when actually practicing this approach, especially when doing it with as-of-now the most popular code collaboration mode, trunk-based development. In particular, smaller diffs means more pull requests for a serie of changes that are dependent on top of the other. We refer to them as stacked pull requests. Now, we have a dependency management issue with Git branches. Not only that, whenever the depended branch gets merged, there is a serie of “merges” or “rebases” for all the dependent pull requests.
It is not impossible to use vanilla Git commands for managing the dependencies between Git branches, but there is a more pleasant way.
Graphite, it seems to be built as a code review dashboard via its web UI, but what I found more interesting is, its CLI works pretty well in standalone for managing stacked pull requests. You can use its web UI to take the full advantage of features, but I still very much prefer the GitHub UI for doing my code reviews, so… sorry creators!
Alright, let’s get straight to the point. Once installed, the CLI is available as gt
.
There are essentially four commands that I use to manage stacked pull requests with Graphite CLI in my workflow.
gt create
- To create a new Git branchgt sync
- To sync branch updates from remote, and prompt for deleting merged branches, as well as automatically restack branches 🌟gt restack
- To manually trigger a restackgt log short
- To look at the dependency tree
The best part? The gt
works seamlessly with all the native Git commands, it’s not vendor lock-in.
Here is a typical scenario at my work:
gt create
to create a new branch (feature/database
) from themain
branch- Code something up, push it up, submit for review
gt create
another branch (feature/router
) on top of thefeature/database
branch- Code something up, push it up, submit for review. On GitHub UI, choose the
feature/database
branch as the “base” so the diff becomes correct - New branches goes on, for an end-to-end feature development
- The pull request for
feature/database
is approved and merged tomain
gt sync
to sync the updates, it prompts me to deletefeature/database
locally and automatically restacks all dependent branches
Great, there is only one problem left.
While I can always use gt log short
to check for the dependency tree, it is not fast enough, I want to be able to know the dependencies way faster than that.
So, I came up with a stupid naming mechanism for my branches.
They all start with two digits, e.g. 00-feature-database
, 01-feature-router
.
The first digit represents a serie of changes, and the second digit is the sequence in the same serie, the number indicates the dependency. Yes, it can only support up to 10 changes in a serie, but in practice, that has never happened to me, and even when that happens, using 010-
would be just fine.
That’s it, happy coding!