Have you ever come across or been the perpetrator of a PR with a commit history that looks like this?
This was commonly how I addressed fixes for my PRs years before working at Distru. I thought this might have been my own naivete, but to my surprise, many engineers far more capable than myself have joined Distru since then, and they too addressed review comments in such a manner.
Over time we’ve come to avoid these types of “fix-up” commits at Distru for a couple of reasons:
- To keep a clean commit history of your code. Code is communication for both other engineers and your future self. The cleaner it is, the more sane the readers will be.
- To utilize `git blame` to its full potential. `git blame` is a tool often used to try and figure out the latest change made to a piece of code and trace back to the commit that made the change. If there are many “fix-up” commits obfuscating the actual commit that changed the code’s behavior, it makes it very hard to understand the author’s original intention.
At Distru, whenever we address an issue in a PR, we resolve them in the original commit that introduced the change, to begin with. We accomplish this by using interactive rebasing.
Interactive Rebasing to Edit Commits
Interactive rebasing is a powerful tool in git that allows you to locally traverse back in history to previous commits, make changes, and essentially rewrite history.
A word of warning: Your main git branch should act as a historical ledger (and thus not change) once work has been merged in. Interactive rebasing should only be done on open WIP branches that have yet to be merged into the main branch.
Let’s take an example. We have an open PR consisting of the following commits:
- Commit A
- Commit B
- Commit C
Creative naming right? Now let’s assume that we’ve received commentary on Commit B that something needs to be changed. Let’s use interactive rebasing to make this change without additional “fix-up” commits.
Find the hash of the commit you’d like to change by running git log
:
Then you’ll want to make sure that all current changes (if any) are stashed via git stash
before then trying to rebase back to this commit.
To make changes to Commit B, we’ll need to issue the following command:
git rebase -i 400d63a771fc0eefd7409da4bfa6a1f37bfff17b^
You’ll need to add a ^
at the end of the commit hash to include that particular commit as a part of your interactive rebase.
After you run this command, you should be at the interactive rebase screen, here you can change pick
to edit
for Commit B”:
Now you should be able to save the interactive rebase file ( :wq
on vim), and git will rewind you back in history to being in the midst of Commit B:
Save & quit this file (:wq
on vim), and the changes you made will now be included as a part of Commit B.
When you’re done with all the changes you’d like to amend, run git rebase --- continue
, and it’ll fast-forward you to the latest branch head.
Now, if you run git log
, you can see that your commit history is still as clean as ever while having made amendments to previous commits!
Did you notice how the commit hash for Commit B and any children (in this case, Commit C) change? It changed because you’ve overwritten those commits by altering history. So to push this up to remote origin, you’ll need to do a force push via git push -f
.
That’s it! You’ve just fixed up a previous commit without having to compromise the integrity of your commit history.
Exploring Other Options
Interactive rebasing is a powerful tool. Editing old commits in place is just one of the many things you can do with it; you can also:
- Make “fix up commits” as you would, and then later squash them into your original commit
- Reorder your commit messages
- Interject commit(s) in between two commits
All in all, interactive rebasing is a must-have tool to keep your commit history clean; your teammates and your future self will thank you for producing such easily traversable work!
—
I hope this looks into how we keep our commit history clean at Distru has been helpful enough for you to start practicing on your own! If you have more to add to this topic, please reach out to me via johnny@distru.com. We’re always trying to learn and improve as a company, and any thought exchange in that effort is greatly appreciated!
Lastly, Distru is currently hiring product-minded engineers, product designers, product managers, and engineering managers that want to build software powering the future of the Cannabis supply chain. If you’re interested in learning more, please check out our Glassdoor and reach out via our careers page and I’d be happy to jump on a call with you!