tl;dr version

Rule #1: write commit comments before coding

Rule #2: write what the software should be supposed to do, not what you did

Long version

Dan North changed my life

You should read Dan North’s epic post Introducing BDD. It might be a little of an oversimplification, but the whole (revolutionary) Behavior Driven Development thing began with the simple attempt to replace the word “test” with “should“.

Words do matter.

After being introduced to BDD (and the Clean Code‘s chapter about methods’ names) I started taking more care of the words used in comments, in commits messages, in test and in method names. The more I tried to adopt the end-user’s perspective, and to focus on what the code was doing, rather than on how. the more things were making sense.

My tests were sentences such as

when_this_occurs_the_user_should_experience_that()

or the like.

I started thinking that I could use the same approach for my commits’ comments as well.

Tell me what the software does (not what you did)

When I check out a commit, I’m interested in what I will find in it.

I’m aware that someone has worked on the code in order to let the software expose some features, but I’m not really that interested in what they did: instead, I’m more compelled to know what the software does in that specific snapshot.

I want an answer to the question

What’s the project behavior in this snapshot?

rather than to

What did the programmers do, in their coding session?

Hence, comments like

Fixed Gitk and Git Gui [spdr870]

(I took a random commit comment from the GitExtensions project)

is of much less significance of something like

When history is over 10k commits, gitk doesn't crash trying to display it



Welcome back!

A colleague of mines came back after 1 week of holidays. We needed to update her with all the changes we made to the code base.

Put yourself in her shoes and try to regain contact with the project, reading this git log:

Now, do it again, supposing we wrote our commit comments like they were items in a “What’s News” post:

Which one conveys more valuable information?

Dan North, again

As an experiment, we began to write comments describing the behavior of the software, rather than the implementation, or a description of what we did.

And we found that it was lading to a more readable history of the project.

Commit comments started to look much more like BDD’s methods name, or short versions of a tiny requirement: a description of a behavior.

The principles my colleagues and I started to follow were:

Talk about the feature, not about yourself : don’t write what you have done; describe what the software does (thanks to what you did)

: don’t write what you have done; describe what the software does (thanks to what you did) Don’t refer to the past : don’t describe what the state of the software was : tell what the state is right now. Use the present tense.

: don’t describe what the state of the software : tell what the state is right now. Use the present tense. I know it’s now: the commit has a datetime: you don’t need to specify “now” or any other time reference.

Here comes Eric Willeke

Then, unexpectedly, I read this tweet by Eric Willeke

This is what my idea was missing! This is what BDD and TDD are actually prescribing: first assert the behaviour with a test, then code. If my commits comments are like BDD assertions, they should be written before coding. Eric must be right.

We tried.

Know what? It worked pretty well.

Write Pre-Emptive Comments

Just like you write tests before you implement a feature, you should write commit comments before you start coding.

Here’s a list of benefits we noticed:

More focus while developing : I love pairing. I like how the navigator can take a note on a to-do list whenever the pair finds a reason to digress; when this happens, the navigator just writes down a note and takes the focus back to the feature to be implemented. Navigator’s notes may eventually be the next technical tasks to be performed. No matter the distraction, the behaviour described in the test is the center of gravity.

Just like a good BDD test, a preemptive commit comment can help the pair to focus on the specific task to be performed. A preemptive commit comment acts pretty much like a preemptive test. It’s just much easier to be written.With preemptive commits a pair is less prone to digressions. Commit review is easier : I’m used to carefully review each diff before committing my changes. Once I started writing commit comments before coding, code review was much simpler. Commit review becomes a let’s-confirm-we-did-what-promised task rather than let’s-discover-what-we-did activity. Less cognitive load : I am used to write a failing test before quitting the office. It helps me quickly switch to the work context the next day. As a matter of fact, one of TDD’s nice side effects it the less cognitive load on the team: after an interruption, if a failing test communicates the developers what’s the next step to perform, they are easier introduced back in the workflow.

Preemptive commit comment does the same, with a greater granularity.Every time I come back from lunch, I just read my preemptive commit comment, and my brain quickly switches to what I was doing 1 hour before. When I don’t remember with enough details, I launch the test suite, looking for red tests.



More accurate and faithful comments : since you have to write them before coding, you want to be just enough specific; a commit comment becomes a declaration of intent , just like a BDD method name.Isn’t it ironic that a Git check-in is called commit? You are, in fact, making a commitment , an engagement. It is just natural that you anticipate what you’re going to do with a declaration of intent.Once you have written down your declaration of intent, you will just want to develop code adhering to what the comment claims, abstraining from other goals; you will not want to be too much specific or too much generic. Comments and commit content naturally end to better match. No more “ Bug fixing “, “ Just changed file Main.cs “, “ Improvements ” or “ I made [foo], [bar], [baz] and also [quz] ” comments.



Each preemptive comment triggers a micro design session : before writing a commit comment, you will start desiring to discuss the exact word to describe a specific behavior, or the exact name to give to a domain concept.; you will want to know which module has the responsibility to send the PDF file by email in your gorgeous ERP plugin, since you have to decide if it’s better to write “ PDF Exporter sends a copy of the document by email ” rather than “ Email Notifier detects files exported by PDFExporter and sends them by email “. In order to write a commit comment, you must be able to describe the feature: this will lead to make you stop for a while and do a nice, light, old-fashioned brain-storming design session.



A preemptive comment sets a micro goal : the mere act of writing a commit comment helps you focus a goal to reach. Since the goal the pair is committing on has been defined from the beginning, it’s simpler for the pair to realize when the goal has been reached and the job is finished. A well defined commit comment embodies a little definition-of-done.

Without preemptive comments, I often used to go on coding, always asking myself: “ Should I commit now? Have I reached a stable state which I could consider a good commit? “.I found that I can define micro-goals through preemptive comments, and a macro-goal through the feature branch name (which is also pre-emptive by design).



A preemptive comment creates a little timebox : I found that with practice, I could divide a coding session into several micro-timeboxes. This is because I have a moment when I start working from a stable state and a clear goal to reach. I am encouraged and pushed to reach the goal.Can you believe it? Just because of a stupid comment. Human brain is weird…



Writing comments preemptively puts the agreement between the pair members to a test : driver and navigator must agree on the comment, that is, the goal to reach. I found that very often the mere fact we must write the goal before coding requires us to discuss and share our points of view. And it’s awesome. The moment you will start coding, you will be much in accord with your pair on what you will want to achieve.



The commit history gains a very balanced granularity: each commit has a precise goal. A feature branch becomes a collection of evolutionary commits each of which has usually a 1:1 binding with tests; each test has its commit. It’s also very easy to find which commit introduced a bug, since each commit is related to a single new goal/feature. You could say that each commit honors the Single Responsibility Principle.

The experiment was originally conducted by Arialdo Martini, Mattia Piccinetti, Gian Marco Gherardi, Guglielmo Brasile, Francesco Pichierri and Giuseppe Mariano.

We are now using this technique on a regular basis.

(Should you decide to give a try to this practice, please, write me a note with your outcomes: I would love to share your opinions and ideas)

Cheers