Are you gitting comfortably? Then I’ll Begin

Ben Forrest
5 min readSep 25, 2020

I hope we all agree that the primary objective of clean code is to communicate the intent of our code to other humans and not to the computer?

I’ve been programming for over 30 years and in that time I’ve seen great code and I’ve seen atrocious code. I’ve certainly written plenty of the latter. And maybe — hopefully — once or twice I’ve managed to write some of the former too. But how do you know the difference?

Well, there are two ways usually:

  • Someone else tells you in a code review; hopefully in a kind and sympathetic manner.
  • You read some code 6 months later and scream ‘What idiot wrote this crap!?’, whilst almost simultaneously realizing ‘Oh, wait, I did’.

However experienced we are as a developers, we sometimes write code that is crystal clear at the time, but makes no sense at all in the future. The trouble is, when writing code, we’re in a state of mind that contains a whole lot of contextual information that is not stored in the code. That context is not necessarily reconstituted when we are reading code, especially when there’s a considerable time lapse. It’s also not available to anyone reviewing the code, unless they’ve been part of the development process.

We work so hard to write clean code, then very often throw away vital information about that code — and the context and thought processes surrounding it — when we commit it to the annals of history (Git, if you prefer).

Once upon a time, I worked on production systems with no source control at all! Moving on via the likes of Visual SourceSafe (pessimistic file locking!); through CVS (forget about branching); and on to Subversion (just a better CVS really). If you’ve only ever used Git you may not be aware of what a miraculous innovation it is. Before Git there was no GitHub; no distributed repositories; no pull requests; no trivially disposable branches; no interactive rebasing. OK, there may have been some of these features in other systems I didn’t use (and probably some I did); but there is a reason Git took over the world. And it’s not just the incredible productivity it enables. There is an orthogonal dimension to using Git beyond just the technicalities of handling merge conflicts; and that is how we thing about the structure of code changes

Human society has evolved through storytelling. The purpose of a story is to transmit understanding (and also entertainment of course; but here I mean from an ‘evolutionary’ perspective). Humans are capable of understanding systems of incredible complexity; but not all in one go. It takes a culmination of many discrete, smaller understandings to reach the whole. Many stories.

If only Pull Requests could be a bit more like stories…

Everyone uses Git slightly in their own way, but there are things we can all do to get even more benefit from this incredible tool. One such thing is to use Git to help your code tell a story. Take a large pull request for example. What if each commit was a ‘paragraph’ in that story, which built on the paragraph before, layering on context and understanding, leading to the final denouement: a complete chapter (the pull request)? Not only would this make the PR easier to review, it would make the code easier to understand in future. There is no downside…

Except that writing pull requests in this way is a skill; and like other skills, it takes practice. You may need to develop a slightly different approach to organizing your code. You will almost certainly find yourself rebasing locally multiple times. Yes, naming things is already hard enough without having to be disciplined about every commit message too! But trust me; it will pay off. And once you get used to it, it will become second nature.

So what, specifically, can we do to improve our storytelling?

  • Ensure each commit introduces only one conceptual change. This could affect multiple files (indeed, many if renaming a common concept), but these should all be changing in a related way.
  • The title of each commit message must not exceed 72 characters. This can be a real challenge, but it is essential for readability on GitHub.
  • After the title, add a description. Lots of description. That’s what the commit message is for. Include some of that context which would otherwise get lost in a max-72-character title. The why is so often missing when reading code. And the beauty of Git is that context will be attached to those changes forever. When you look back at the code in years to come, you’ll be able to see not just the diff, but what you were thinking about when you made it!
  • Use git rebase frequently. The ability to rewrite history is just like a writer’s ability to go back and edit a chapter, move paragraphs around, add a missing sentence; so the reader can better understand the story. It’s a gift — use it!
  • Avoid a change in one commit that is contradicted by a change in a subsequent commit. Because, if — like me — you prefer to review a PR on a commit-by-commit basis; it’s frustrating to make a comment about e.g. a new method name in one commit, only to find it renamed a few commits later!
  • (Corollary to the above) If you decide to rename something introduced in an earlier commit in the same PR; use git rebase to fix-up that rename back to the original commit as if it never happened…
  • Prune WIP commits with prejudice. They are fine on your local branch; sometimes helpful even. But they should never make it into a pull request. If you spent 10 commits going back and forth testing ideas (or trying to fix that damn bug!), then keep it to yourself! Squash those 10 commits, or distribute them across your other commits so that they disappear into the story and follow the rules above.

There are lots of good blogs on how to write great commit messages, e.g. https://chris.beams.io/posts/git-commit/

All of the above should apply before you request a review on your PR. After a review, however, you should try to avoid rebasing requested changes into earlier commits, because it’s then harder for the reviewer to see these in isolation. However, you should certainly continue to use best practice in your commit messages; i.e.

  • Avoid commit titles like just apply feedback, or code review . Be descriptive; include a summary of the PR discussion in the commit message if it’s useful (as this is only stored in GitHub and is not otherwise available when looking at the commit history locally).
  • Don’t lump all the changes into one commit; group them conceptually as you would prior to review.

Finally, no good story is complete without its beginning, middle and end. So what’s the ending here? Perhaps just my hope that you’ll enjoy writing beautifully descriptive pull requests, and your reviewers will enjoy reading them; all will be well in the world, and there will be much rejoicing.

The End.

--

--