These are my personal conventions, mix and match or ignore, but at least have some form of convention for yourself and your team! :)
Respect Existing Project Conventions
This is one I don’t see applied too often, but when you’re committing to an open source project that you either have direct access to — or are patching, take a minute to glance at previous commits and get an idea of how the author(s) are structuring things.
Prefix Common Verbs In Commit Messages
When committing to a main branch (one that won’t be squashed) it’s very helpful to prefix all, or at least most of the commit messages with some normalized set of verbs. The tense and casing is totally up to you but keeping them normalized makes it very easy to scan. I like to use “add”, “remove”, “update”, “refactor”, “fix”, and so on as shown here:
* bafaeac TJ Holowaychuk — add mixin property array support
* e9df63a TJ Holowaychuk — remove opacity plugin. Closes #29
* c5b1e85 TJ Holowaychuk — remove media macros. Closes #36
Updating Dependencies With a Note
When updating a dependency in your project you might be tempted to just commit “update foo”, but if there’s a specific reason you’re updating a dependency it can be really helpful to your collaborators (and your future self) to make note of why you bumped the dep.
Nothing too special here, I typically just use the same convention as commit messages for branches like “add/my-feature”, “remove/old-feature”, “fix/crazy-bug”.
In your own codebase and when contributing to other projects, it’s pretty important to keep a clean commit history, at least as clean as you can without driving yourself mad. One important aspect of this is “squashing” commits when appropriate, to form a single commit.
This is a bit of a controversial topic since squashing several commits into one can make bisecting more difficult, but for small focused changes which you should be aiming for anyway this often increases clarity.
For example if someone was to send a pull-request to your project fixing a single bug, but the pull-request contains 3 commits as shown below. Chances are you don’t really care about the top and bottom two, really you just want a single commit with both the test and fix, making it easy to revert, easy to scan in your main branch, and equally easy to bisect as long as the changes are focused.
- fix typo
- fix something. Closes #123
- add test for fixing something
What you really want is:
- fix something. Closes #123
To do this you can use the git-squash(1) command in git-extras, although I’m sure one of the GIT gods out there could point to a built-in solution!
EDIT: @defunctzombie suggested just using a simple reset —soft here and then re-commit the staged changed. The only difference then between this and git-squash(1) is that the latter will squash an entire branch (be careful!!).
EDIT 2: turns out there’s a git-merge —squash flag that effectively does what git-squash does, so there’s not much point in using that. Here’s the snippet from the manpage:
Produce the working tree and index state as if a real merge happened (except for the merge information), but do not
actually make a commit or move the HEAD, nor record $GIT_DIR/MERGE_HEAD to cause the next git commit command to
create a merge commit. This allows you to create a single commit on top of the current branch whose effect is the
same as merging another branch (or more in case of an octopus).
For short-lived branches that I’m confident about squashing I drop feature related prefixing. For example where two regular commits may be “fix facebook oauth integration”, and “add test for facebook oauth integration bug”, in a branch named fix/facebook-oauth I would typically just make commits like “add test”, “fix integration” so they still make sense but you’re not wasting a lot of time.
Keep a Changelog
Most people do this but it’s definitely something I would consider very important, telling your user-base to “just read the commit log” is not fun and no one wants to do that. When you issue a release people just want the gist of changes, ordered neatly so they can see what has been added, fixed, removed, etc.
I use git-changelog(1) in git extras to generate the changelog, however if you were strict about conventions you could use something more strict that doesn’t require any manual massaging like git-changelog(1) does.
Closing and Referencing Tickets
I think most GitHub-ers know this and take advantage of it but it’s worth mentioning. When you commit with a string like “Closes #123" GitHub sees this and will actually close the issue for you, along with referencing the commit in the issue.
The same goes for referencing, just place “#123" in the commit message or body to thread things along, this is a small but awesome feature of GitHub that you should definitely consider taking advantage of.
This isn’t something I do often myself, but I’d like to get started tagging my commits more often. For example when you produce a changelog you often still need to weed out these “real” changes, because no one has a perfect commit log — but if you were to tag relevant changes with #change or [change], then this would be trivial.
Some people also use feature or aspect related tags like #ui, #ux and similar, I think these could be pretty helpful from a stats point of view but also adds clarity to changes.
One thing we did at Cloudup is prefix all commits with the module’s name. This is a nice side-effect of having a truly modular application, it’s a lot harder for people to step on each other’s feet. For example instead of “add gravatar support to signup”, we would use “signup: add gravatar support”, making things even more obvious for someone scanning the log.
Those are my main suggestions but I’d love to hear others as well if you find a particular convention you use is critical to your work flow.