Toward better git hygiene
My first experience with git was when I was an intern at my first job. I knew very little about programming. I knew even less about git.
The extent of my knowledge on version control software was the time I had to use TortoiseSVN to download source code for a robotics project back in college. I never “committed” anything, whatever that meant. To me, version control software was just a fancier way to download stuff to my computer.
With that background on VCS, during my internship, I committed a week’s worth of code with the message “Update some stuff”. Someone who wasn’t even my manager rejected it and said, simply, “no omnibus commits”.
Since that point I made a concerted effort to practice good git hygiene. This involves knowing why git, or any kind of version control, is useful.
Version control is critical for understanding how a project evolves over time.
Likewise, it enables the treatment of features and fixes as atomic units of change. It should be easy to revert a commit (or to find a set of related commits) and know exactly how that affects the project.
So how do you from “Update some stuff” to being a model of git cleanliness?
First, and this has been beaten to death numerous times, but use the imperative mood for the first line. Imagine you’re in school and your instructor is telling you what to do for a project to grow it. This is that mood:
- Add pagination to the users endpoint
- Fix the memory leak in the factory controller factory
- Update the version to 2.3.4
The imperative mood signals a command that is to be taken. One thing I’ve done for my commits is to use a simple set of starting words: Add, Fix, Update, Remove. It’s incredible how many changes map into these four words, and contrary to what you might initially think, it’s actually easier to write the rest of the commit message when you aren’t agonizing over how to start it.
Second, use tooling that enables line by line staging. Back in the day, any time I had changes in a file, I would always throw all of those changes into a single commit and be done with it. This often results in unwieldy and non-atomic changes in the git history.
I don’t blame my laziness for this, I blame my insufficient tooling. It was just too difficult stage changes interactively with the vanilla git command line. I’ve since upgraded to using tig, an ncurses-based interface to git. The first few weeks using it felt awkward, but it was definitely worth it.
It doesn’t matter how many changes I make to a file, I can always hop right into tig and stage exactly which lines should go into which commit. This both lets me write code in whatever cadence feels right at the moment, and later preserve it in a natural way for the project as it grows.
Doing these two things helped me avoid making omnibus commits and improved my git hygiene immensely. In fact, even with just these changes, you could be a cleaner programmer than 90% (this is a totally made up but not entirely untrue number) of contributors on GitHub.
Don’t wait, git clean!