Coming from CVS, we have a policy that commit messages should be tagged with a bug number (simple suffix "... [9999]"). A CVS script checks this during commits and rejects the commit if the message does not conform.
The git hook commit-msg does this on the developer side but we find it helpful to have automated systems check and remind us of this.
During a git push, commit-msg isn't run. Is there another hook during push that could check commit messages?
How do we verify commit messages during a git push?
You didn't mention what is your bug tracker, but if it is JIRA, then the add-on named Commit Policy can do this for without any programming.
You can set up a commit condition which requires the commit message to match a regular expression. If it doesn't, the push is rejected, and the developer must amend (fix) the commit message, then push again.
You could do it with the following
pre-receive
hook. As the other answers have noted, this is a conservative, all-or-nothing approach. Note that it protects only the master branch and places no constraints on commit messages on topic branches.It requires all commits in a push to have a bug number somewhere in their respective commit messages, not just the tip. For example:
Say we fix the problem by squashing the two commits together and pushing the result:
You need made a script on your pre-receive.
In this script you receive the old and new revision. You can check all commit and return false if one of this is bad.
Using the update hook
You know about hooks - please, read the documentation about them! The hook you probably want is update, which is run once per ref. (The pre-receive hook is run once for the entire push) There are tons and tons of questions and answers about these hooks already on SO; depending on what you want to do, you can probably find guidance about how to write the hook if you need it.
To emphasize that this really is possible, a quote from the docs:
And the specifics:
So, for example, if you want to make sure that none of the commit subjects are longer than 80 characters, a very rudimentary implementation would be:
Of course, that's a toy example; in the general case, you'd use a log output containing the full commit message, split it up per-commit, and call your verification code on each individual commit message.
Why you want the update hook
This has been discussed/clarified in the comments; here's a summary.
The update hook runs once per ref. A ref is a pointer to an object; in this case, we're talking about branches and tags, and generally just branches (people don't push tags often, since they're usually just for marking versions).
Now, if a user is pushing updates to two branches, master and experimental:
Suppose that X is the "bad" commit, i.e. the one which would fail the commit-msg hook. Clearly we don't want to accept the push to master. So, the update hook rejects that. But there's nothing wrong with the commits on experimental! The update hook accepts that one. Therefore, origin/master stays unchanged, but origin/experimental gets updated:
The pre-receive hook runs only once, just before beginning to update refs (before the first time the update hook is run). If you used it, you'd have to cause the whole push to fail, thus saying that because there was a bad commit message on master, you somehow no longer trust that the commits on experimental are good even though their messages are fine!
This is a python version of
pre-receive
, which took me a while to finish, hope it could help others. I mainly use it with Trac, but it could be easily modified for other purposes.I have also put down the instructions to modify back the historical commit message, which is a little more complicated than I thought.