Git Interactive Rebase — A Perfectionist’s Dream
Jac Walker
Senior Developer
Jac Walker
Senior Developer
How you too can achieve every developer’s dream: perfectionism
As a developer, I know that I’m perfect. Well, at least I like to think that I am, and it’s important to me that you think so too.
And yet, I’m all too familiar with the disappointment of discovering you forgot to remove a “TODO” comment, or have managed to somehow break all your integration tests.
But, still, I’d like to think I’m perfect, and I’ve worked hard on maintaining that facade to anyone who comes across my code in the future. How? Git’s Interactive Rebase, that’s how.
Background
Full disclosure — I was a very reluctant adaptor of Git. It was first introduced in my second year of University, and required as part of an assignment. I don’t remember anything about that class other than my dislike of being forced to use this tool.
At the time, I was both a chronic procrastinator and dedicated to the art of updating and appending file names with “_FINAL_LAST_2” with increasingly more dramatic and more final tone until I submitted my work.
Git never clicked for me, and I had an unfair bias against it, which I initially carried into my professional career. Luckily, that didn’t last long. Working with developers who were passionate about Git and were able to communicate just how powerful it can be, reshaped my entire perspective.
The Current Process
You pick up a new feature and start working through it. You change something, then commit that change. You change something else and commit that change. This continues until you’ve completed the work needed. Next comes a pull request, where you get some feedback and consequently make more changes, adding to the long list of commits that came before. A coworker completes their PR so you pull main again, merging those changes into your branch, in yet another commit.
All is well in the Developer team… or is it.
The Problem
Imagine you join a new team, pick up a complex feature, or need to work on a codebase that hasn’t been touched in years. Often, you’d find yourself using Git blame to understand where changes were made and why.
You see commit messages such as “Fix tests”, “Update query” and “Undo previous change”. And while they reflect what happened at the time, they bring you no closer to understanding the code. In standard Git process, the commits often represent what was done chronologically. While this is truthful, it isn’t valuable, and is putting your team at a disadvantage.
Think about it — is there really a scenario where you would need to travel back in time to the “fix typo” commit? Or does anyone really care that there was “PR feedback”?
Solution
Include Interactive Rebase as part of your continuous development strategy. If you effectively utilise rebasing, your commit history transforms into a story, allowing others to easily understand without having to navigate additional noise.
There are plenty of articles that explain just how to Rebase and understanding the risks involved, so instead of focusing on those, I’ve formed my own opinions on the best approach.
Commit as usual
803fae5 Add endpoint to create lists
41fe4a3 Fix typo in endpoint
7931d51 Add create list command
567fe66 Improved validation in lists command
887ce46 Add create lists tests
b980290 Add more logic to command
414894d Update tests
5a64096 Add more tests
As you develop, continue to make commits as usual. Try and keep these to a smaller scope where possible, as it’ll greatly benefit you in the future when it comes to rebasing and handling conflicts.
Squash & Reorder
pick 803fae5 Add endpoint to create lists
squash 41fe4a3 Fix typo in endpoint
pick 7931d51 Add create list command
squash 567fe66 Improved validation in lists command
pick 887ce46 Add create lists tests
pick b980290 Add more logic to command
pick 414894d Update tests
squash 5a64096 Add more tests
This is the time Interactive Rebase comes into play. Start by cleaning up commits — this means squashing related commits into their closest commit parent. Sometimes they might be a few commits away, so you’ll need to move commits to be near that parent.
pick 803fae5 Add endpoint to create lists
pick 7931d51 Add create list command
squash b980290 Add more logic to command
pick 887ce46 Add create lists tests
squash 414894d Update tests
Once the commits are mostly tidied into logical steps, then those remaining commits should be reordered into a logical sequence. This is likely where you will encounter merge conflicts if things are moved out of order. Continue the squash & reordering until the commits tell the story of what was done.
Reword
reword 803fae5 Add endpoint to create lists
reword 7931d51 Add create list command
reword 887ce46 Add create lists tests
Finally, it’s time to amend any commit messages so that they are clear and meaningful. Good commit history is nothing without good commit messages.
803fae5 Add endpoint to handle create new lists
7931d51 Add command to handle creating and validate new lists
887ce46 Add tests for creating new lists
Dealing with Feedback
803fae5 Add endpoint to handle create new lists
7931d51 Add command to handle creating and validate new lists
887ce46 Add tests for creating new lists
c383c15 PR feedback
90d1db6 Change tests
Make and commit the changes you need, and following the same process, these new commits can now be squashed away into their logical commit parent.
pick 803fae5 Add endpoint to handle create new lists
pick 7931d51 Add command to handle creating and validate new lists
squash c383c15 PR feedback
pick 887ce46 Add tests for creating new lists
squash 90d1db6 Change tests
It’s almost as if they were meant to be that way, all along.
803fae5 Add endpoint to handle create new lists
7931d51 Add command to handle creating and validate new lists
887ce46 Add tests for creating new lists
Conclusion
Finally, a warning: Once you start rebasing, you likely won’t be able to stop.
You’ve achieved every developer’s dream: perfectionism. You are a perfect developer. Undeniable, proven by your impeccable commit history — no mistakes, tidy and clean commits.
And even if that isn’t the truth, think about what you would rather see — a tangled mess of excessive commits that reflects what happened, or a logical and concise story of the final work.