Small, Distinct Commits Say You Care

As programmers, we revel in the details. We’ll pour our time and money into growing our craft for the sheer joy of it. That’s why we’re incredible. We discover the pricelessness of version control systems and services early in our careers. Tools like Git give us the feeling of invincibility!

These tools are much more than a safety net. They are communication devices. They communicate the story of a project, the programmers involved, the purpose for decisions made and even the programmer’s disposition. In this post I want to review some ways we can improve our use of version control and why this really does matter. I prefer Git, so my examples will be given as such.

The Future You is Tired (and lazy)

Have you ever looked at a piece of code and said to yourself “What were they thinking when they wrote this?!” I certainly have. Unfortunately “they” is usually me. Thanks to git we can get to the bottom of it.

For this post, I created an example repository. The example follows the development of the critically important class Mug. Over time we’ve added a number of features to Mug, including the ability to drink from it by sips and gulps. If you attempt to take a drink from an empty mug, an error is raised. Why would we want to go as far as raising an error for this condition? Let’s find out!

The Right Way

In an ideal world, commits are small and focused. Under pressure, we might take some shortcuts. Let’s first look at the good case:

Aha, we want to be unable to drink from an empty mug because we don’t think air is worth drinking. Additionally, the commit message reveals that it is associated with an issue, story or some other additional information specific to the project which is numbered 1337. Following that back to your tracking system may reveal even more information about the feature.

Yay, that’s quite helpful!

The Wrong Way

What if the commits weren’t so nicely tailored? The blame might have landed you with something like 0826c3f3.

It’s notably more difficult to figure this one out. First, the diff is large, so it’s unclear what all has changed. Luckily, the commit message attempts to cover the changes, but unfortunately it does fall short as the error condition goes completely unmentioned. If your commits look like this while you’re actively working on a feature, all is not lost! Below we’ll jump in our time machine and make history do our bidding.

No Fear of Commitment

Does commitment scare you? Don’t sweat it. Git provides the ability to warp history into the story you want to tell. We have git-rebase, which isn’t just about changing the base of a branch, as its name suggests. I use it in combination with git-add –patch on a daily basis to manipulate my commits into a meaningful story before pushing them to a remote (and sometimes even after, if I’m working in a feature branch). I inevitably find myself wanting to remove, squash, split or reword experimental commits that are unclear or unneeded for the feature.

Pro tip: If you use GitHub, the compare view is a really handy way to review the your commits. tig is also a handy command line git interface that can enable you to quickly walk the commit history.

Warning: You probably don’t want to rewrite the history of a “shared” branch. Doing this can cause issues for other users of the branch. Typically, you will only want to rewrite history on local or feature branches that you own.

Summary

There are a number of benefits from commiting code in small, distinct changesets: