Like most other makers of Internet, we at Connective DX use Git as our version control software of choice. And while we’ve gotten pretty adept at maintaining our repos, manually resolving merge conflicts, and repeatedly typing “git bisect” into a terminal to see where everything went sideways, one aspect of our workflow that we’ve been looking to improve is the quality of our messages attached to all those code commits. How should we write them? What information should they provide? What purpose should they serve? The following is intended to provide some general guidelines and start a conversation toward increasing uniformity and value in the many messages we send up to our repos every day.
It’s worth repeating that the following aren’t intended to be actual rules, though they’re called out as rules. If they don’t fit what you’re doing, fine. If they need refinement or expansion, great. They’re being presented in an axiomatic tone for the simple fact that not doing so leads to syntactic hoop jumping and conditional throat clearing, and none of us want that.
Rule 1: Commits should be as fine-grained and focused as possible.
You’re likely already thinking about the code you’re writing in terms of small, focused pieces: Class X performs purpose X, not Y and Z; a _lists.scss partial deals only with styling lists, not lists plus the typography in your footer. This same single responsibility principle should be applied to your Git commits as well. Commit that Sass partial by itself, rather than in a clump of files containing all of the work you did for the day. This will make your commit message more meaningful—“Adds a new lists.scss partial” versus “Work on homepage”—which in turn will make the commit logs more helpful in the future. It’s often true that one focused change will happen over multiple files and including them together in a single commit makes sense—that’s fine. So long as the work represented in the commit can easily be summed up without using “and,” you’re in the clear. A good rule: if you write “and” in a commit message, it’s probably a good indication you could benefit from multiple commits.
Commit messages, like code comments, are as much for the next developer as they are for ourselves. Keeping commits brief and focused allows for easy searching and scanning through logs and, most importantly, makes it easier for you to meaningfully describe what it is you’ve done. Adhering to the guideline of committing early and often usually takes care of this.
Rule 2: Commits should start with a verb.
Specifically, every commit message should start with a present tense action verb. If we think of a commit message as a sentence with the implied subject of “This commit…” , it is our role to write the rest of that sentence. With that in mind, we’d write “adds,” not “added”; “fixes,” not “fixed”; and so on. Thus: “Adds vertical-align mixin,” “Fixes default template layout bug,” “Removes all traces of IE 6 support.”
Having these verbs at the start of commits not only makes them grammatically uniform, it also makes scanning through commit logs easier. When you want to find where some code was removed, for instance, you can just run your eyes down the left edge of the logs until you hit “removes” or “deletes” and ignore all the “adds” or “extends.” While it’s a seemingly small advantage, it can add value pretty quickly—especially on large teams or on projects with long development cycles generating a high volume of commits. Ultimately it saves time, and that alone is valuable.
There are a number of arguments floating around in favor of using the imperative case for verbs: “Fix bug” instead of “Fixes bug” or “Add widget x logic” instead of “Adds widget x logic.” The argument goes that this language matches Git’s internal syntax (merge, pull, fetch, etc.) and is therefore a good fit. But the logic here is flawed. As wonderful a piece of software as Git is, we should not be taking language lessons from it. Commit messages are mostly speaking to the next developer; chances are pretty good that developer won’t be a piece of software. Neither are you.
Rule 3: Commit messages should be short.
A commit message is not the place to be verbose. Be terse and to the point. You’ve got about 50-70 characters to be clear. That’s half a tweet max. If you need more space, use the commit body. If we think of the commit message as an email, the initial commit message is like the subject line and the body is like, well, the body.
Rule 4: Don’t be afraid of the commit body.
It’s there waiting for you so you might as well, right? Here are some valid reasons to use the commit body:
- if it wouldn’t be obvious to someone later what the commit is doing without explaining context
- if there’s some other piece of information or instruction that might be useful for a code reviewer
- if you can link to an associated Jira ticket, GitHub issue, Basecamp to-do, etc.
Most desktop Git clients have clear separation between message line and body in their GUI. Tower and the official GitHub clients, for instance, present them as two distinct text fields. SourceTree allows you to add in a hard line break after the first line and start in on the body.
SourceTree’s method mirrors how you’d do it in a text editor or from the command line. Git simply requires an empty line between the commit message and the body to properly parse them. If you’re anti-GUI (thanks for reading, Vim fans), you could use the -m flag twice in your commit from the command line ("git commit -m 'Subject line' -m ‘Body…'"), but this is a really bad idea, so you almost certainly shouldn’t do it. Aside from simply being a terrible practice, writing commit bodies in this way can easily lead to mistakes and—since no one wants to write at length in a terminal prompt—puts you in the mindset of being terse at all cost, defeating the point of using the commit body in the first place.
Instead, you can set the global GIT_EDITOR variable to your editor of choice, either in your bash profile or global git config. For me, using Sublime Text, that would look something like this:
- in .bash_profile: export GIT_EDITOR='/usr/local/bin/sublime -w’
- for git config: git config --global core.editor “subl"
With this set up, when you enter git commit from the terminal, your editor of choice will fire up and you can write your messages there. Denote the subject/body split with a blank line between them, just like in SourceTree, and Git will do the rest.
Pull Request Messages
Rule 1: Titles can be more generic
The same basic rules apply to writing pull requests as they do single commit messages: write a clear title with a descriptive body below it as needed. The difference with pull requests is that you’re (most likely) grouping a series of commits together. And since you’re hopefully already doing that work on a clearly titled feature or bug branch, it makes sense to use the name of that branch as the title for your PR, with a bit of description added for clarity. Something like “feature/CLIENTX-3678 — Calendar widget” or “bug/ACME-123 — right channel template layout bug fix.”
Rule 2: PR bodies should summarize the commit(s) the PR contains
The goal in summarizing your PR should be to provide enough information that someone reviewing your code can easily get a sense of what’s happening and why by reading just your summary. At the same time, you need to avoid including so much information that it becomes overwhelming. That’s a totally subjective line, yes, but you’ll likely know when you’ve crossed it.
If the PR title is clear and adequately summarizes what’s happening, there’s no reason why the body can’t be brief or, if appropriate, empty. For instance:
The process of generating these messages starts with reading over the commits you’re looking to merge in. If the branch is more than a couple of hours old, you’ll probably have forgotten something. And, because you’re writing really good, granular, pointed commit messages already, you’ll know exactly what you’ve done by reading through your commits.
Some questions to ask yourself while you’re reviewing your commits:
- What changes does this work make?
- What issue or request makes this change necessary?
- How does this work address that issue?
- Are there any non-obvious effects of this change?
- Is there any information a reviewer would need in order to test these changes?
Briefly answering the first two questions will give you a summary of the code being merged in and the context for its existence. Preferably, it should also give you a link to include in the message that points to a feature request, bug report, GitHub issue, etc., to track the work against.
With these guidelines as a part of our workflow, we hope to make Git an even more helpful and powerful tool, make our team communication a little better, and continue to evolve our process. We’d love to hear any suggestions or improvements you have as these guidelines become part of your daily practice.
Get useful insights, tools and best practices to delight customers and grow your business.
Keep up to date with our latest perspective, news and events.
You’re all set.
Look for our Connective Thinking newsletter on every full moon, as well as occasional news and other updates. In the meantime, check out our work or connect with us on social.
- © 2017 Connective DX
- All Rights Reserved