Image from xkcd # 1296
I love commit descriptions in Git. When used correctly, they can be called one of the most powerful tools for documenting the evolution of the code base during its existence. I want to illustrate my point of view with the example of my favorite description.
This commit dates back to when I worked at Government Digital Service. Its author is a developer named Dan Carley , and it has a rather unremarkable title: " Converted the template to US-ASCII to fix the error ."
“I have implemented several tests in the feature branch to match the contents of` / etc / nginx / router_routes.conf`. They worked well if run with the commands `bundle exec rake spec` or` bundle exec rspec modules / router / spec`. But when running `bundle exec rake`, each should-block failed:
ArgumentError: invalid byte sequence in US-ASCII
In the end, I found that after the exception to the expression `.with_content (//)`, all errors go away. That there are no strange characters in the specification file. And also that it can be reproduced by calling Puppet in the same interpreter:
rake -E 'require "puppet"' spec
This template seems to be the only file in our codebase encoded with 'utf-8'. All other files in 'us-ascii':
dcarley-MBA:puppet dcarley$ find modules -type f -exec file --mime {} \+ | grep utf modules/router/templates/routes.conf.erb: text/plain; charset=utf-8
An attempt to transcode it into US-ASCII failed because of a single character that looks like a space:
dcarley-MBA:puppet dcarley$ iconv -f UTF8 -t US-ASCII modules/router/templates/routes.conf.erb 2>&1 | tail -n5 proxy_intercept_errors off; # Set proxy timeout to 50 seconds as a quick fix for problems # iconv: modules/router/templates/routes.conf.erb:458:3: cannot convert
After replacing it (manually), the file again became 'US-ASCII':
dcarley-MBA:puppet dcarley$ file --mime modules/router/templates/routes.conf.erb modules/router/templates/routes.conf.erb: text/plain; charset=us-ascii
Now the tests work! The whole hour of my life cannot be returned ... "
In original
Convert template to US-ASCII to fix error
I introduced some tests in a feature branch to match the contents of
`/ etc / nginx / router_routes.conf`. They worked fine when run with `bundle exec
rake spec` or `bundle exec rspec modules / router / spec`. But when run as
`bundle exec rake` each should block failed with:
ArgumentError: invalid byte sequence in US-ASCII
I eventually found that removing the `.with_content (//)` matchers made the
errors go away. That there weren't any weird characters in the spec file. And
that it could be reproduced by requiring Puppet in the same interpreter with:
rake -E 'require "puppet"' spec
That particular template appears to be the only file in our codebase with an
identified encoding of `utf-8`. All others are `us-ascii`:
dcarley-MBA:puppet dcarley$ find modules -type f -exec file --mime {} \+ | grep utf modules/router/templates/routes.conf.erb: text/plain; charset=utf-8
Attempting to convert that file back to US-ASCII identified the offending
character as something that looked like a whitespace:
dcarley-MBA:puppet dcarley$ iconv -f UTF8 -t US-ASCII modules/router/templates/routes.conf.erb 2>&1 | tail -n5 proxy_intercept_errors off; # Set proxy timeout to 50 seconds as a quick fix for problems # iconv: modules/router/templates/routes.conf.erb:458:3: cannot convert
After replacing it (by hand) the file identifies as `us-ascii` again:
dcarley-MBA:puppet dcarley$ file --mime modules/router/templates/routes.conf.erb modules/router/templates/routes.conf.erb: text/plain; charset=us-ascii
Now the tests work! One hour of my life I won't get back ..
A small digression: one of the benefits of open source development practiced in GDS is that you can share examples like this outside the organization that created them. I don’t know who first proposed this concept to GDS — by the time I joined the organization, it was already widely used — but I am infinitely grateful to this person.
Why i like this commit
Countless times, I have cited it as an example of what commit descriptions are capable of. It is somewhat amusing because of the correlation of changes in the code and the size of the description, but I don’t like it at all for this reason.
In another company, with another developer, the entire message of the commit could be reduced to phrases like “replaced the gap”, “fixed the error” or (depending on the team’s culture) to attacks towards the inventor of inextricable spaces. Instead, Dan took the time to create a detailed description useful to others. I would like to dwell on the reasons why I consider this commit to be a really good example.
Discloses the reason for the changes made.
The best description of commits not only tell us about what has changed, but also to explain why. In our case:
I have implemented several tests in the feature branch to match the contents of `/ etc / nginx / router_routes.conf`. They worked well if run with the commands `bundle exec rake spec` or` bundle exec rspec modules / router / spec`. But when running `bundle exec rake`, each should-block failed:
ArgumentError: invalid byte sequence in US-ASCII
Without such a level of detail, we could assume that the commit corrected the parsing error in a particular tool. Thanks to the description of the commit, we know what kind of tool it was.
This kind of information can be really valuable, and it is too easy to lose, because people tend to forget the intricacies of their work, move to other teams and ultimately leave the company.
Good for searching
One of the key elements of this description is the error itself, with which further searches began:
ArgumentError:
invalid byte sequence in US-ASCII
Anyone who encounters this error can search the code base, either by running
git log --grep "invalid byte sequence"
, or using the GitHub commits search . In fact, judging by the search results, many have already done so and found out who and when faced with this problem and how it was finally solved.
Provides a complete picture
The commit message details how the problem looked like, how it was investigated and resolved. For example:
In the end, I found that after the exception to the expression `.with_content (//)`, all errors go away. That there are no strange characters in the specification file. And also that it can be played by calling Puppet in the same interpreter.
This is one of the areas in which messages at commits are really able to show themselves, because they describe the change itself, and not some file, function or line of code. This makes them a great place to store this kind of additional code base adventure information.
Makes everyone a little smarter
Dan did one thing here that I really appreciate: brought all the teams that I performed at each stage. This is a great and affordable way to disseminate knowledge in a team. Reading his description of the commit, you can learn a lot about Unix tools:
- you can pass the
-exec
argument tofind
to execute a command with each file found; - adding
\+
at the end of the command does something very interesting (passes several file names to thefile
command, and does not execute the command once for each file); -
file --mime
allowsfile --mime
to find out the MIME type of the file; - there is a utility
iconv
.
A person viewing a description can learn about all these things. Anyone who stumbles upon this commit later will also learn about these things. If you multiply this approach to commits for a long time and a sufficient number of them, it can become a powerful incentive-helper for the team.
Develops empathy and trust
Now the tests work! The whole hour of my life cannot be returned ...
The last paragraph adds a modicum of humanity. Reading these words, it is difficult not to feel the disappointment of Dan, who had to spend an entire hour searching for a hidden error, and the satisfaction of correcting it.
Now imagine a similar message attached to a temporary hack or piece of prototype code that got into production and “took root” (as is often the case with such fragments). Such a description of the commit reminds everyone that behind each change is a person who makes the best decision possible considering the information available at that time.
Good commits matter
I admit that this is an extreme example, and I do not expect all commits (especially of such scope) to boast the same level of detail. However, I still think that this is a great example of explaining the reason for the change, helping others to learn new things and contributing to the collective mental model associated with the code base.
If you want to know a little more about the pros of good descriptions of commits and some tools that make structuring edits easier, I can recommend the following materials:
- “ Telling stories through your commits ” by Joel Chippindale;
- " A branch in time " by Tekin SĂĽleyman.
PS from the translator
Read also in our blog: