Messy Developments — Or how I learned to stop worrying and love git rebase
Once a developer gets more practise writing their own software projects, they appreciate the importance of using a version control history tool like git. These tools record a logbook of all the code that you’ve written so that it remains consistent and you can re-wind easily, but when it comes time to collaborate with other people, you better make it presentable.
It’s no secret that developing is often a messy process. git
as a tool is great for keeping track of the history of code, but it’s very often great at revealing all the mistakes you’ve made along the way too. For a trivial yet realistic example (start at the bottom):
$ git log -n 6
12349 Forgot to load tests
12348 Added tests
12347 Forgot to load new changes
12346 Spelling error
12345 Added feature A
This is how actual real development works. We all make mistakes, we’ve all had odd times and broken mid-commit builds where the two commits are required to be together no matter what.
But when it comes time to bring in other developers, or if you join a team of other developers, they’re going to have to review their work, and you’re going to have to review theirs. Part of the pain and embarrassment is seeing how many “fix spelling error” git commits there are in your code base.
But there’s an easy way to fix this, and a few different ways to do it, and it involves using git for what it is rather than just committing your changes.
Preliminary work: The basics
- Firstly, understand that git has 3 “working modes” — unstaged, staged, and commited. Sometimes these might be easier to visualise with an editor like VSCode or this handy bash script that I use to track my git status in the terminal.
- Git makes a logbook of “commits” which all apply to each other; So one commit might be to add a function to a file. The next commit will be to write another function to the file that has had the previous commit, or rather, just that commit.
- Git
rebase
is a general “rewind” and “fastforward” tool that can move between git commits.
Option 1. Fixup
If you’ve found a mistake introduced in a previous commit, then this is the most easiest to fix. A great tool for this is called “gitlens” for vscode which will tell you where a particular line of code came from.
$ git log -n 5
130 Some more work done on functions
129 Some tests added for others
128 Made a brand new module <-- Here is our mistake.
fix up the mistake, then commit with the fixup option:
$ git commit -a --fixup=128
This will make the commit a “!fixup” of the previous commit. For what this looks like in real life: 8ebedee
is the erroneous commit.
You can see the latest commit has the fixup!
command infront of it. Now that we have the commit in the history, we need to put it back where it goes.
we can use rebase -i --autosquash HEAD~4
to bring the commit to where it wants to be. This means interactive, autosquash, and 4 commits before where the HEAD
was. we have to go one behind the target commit, because it plays from that commit onwards.
This gives us a menu, and if you notice, it will put the fixup commit close to the commit that it’s meant to be fixing up:
While I was here, I also took the opportunity to use “reword” to change the :W
that I have accidentally put in the commit message for 01c284d
When you save and write the file, it will do what it can, and give you the option to reword commit messages if you asked it to.
Option 2: Squash
This is an option for what you do when you want your code for review. Consider if you have a messy log from our first example, but really you want to break it down to 2–3 whole commits that each do something independently, and which you can then seek feedback on for each commit.
Firstly, we’ll look at our git log:
You can squash commits into one, by using the “squash” wording in the rebase options. Try it now by squashing all the commits except for the first one (at the top of the file) into one, you can then change the final git message into something like “implement feature” and end up with something like this:
This is a much nicer way of presenting your work to other developers.
In future I will update with some more git rebase commands when I can demonstrate them effectively, but for now this should be enough to get you started.