I’m very lucky that some people contributed to my github repositories, in some cases even significant portions of code. But the most parts of the libraries I maintain are written by me. So why is it, that I try to write good comments and good commit messages, even if I might be the only one ever reading them again.
You may have seen this funny code comment.
// Dear maintainer:
// Once you are done trying to 'optimize' this routine,
// and have realized what a terrible mistake that was,
// please increment the following counter as a warning
// to the next guy:
// total_hours_wasted_here = 42
If only someone had described why it was so difficult and why they failed, what constraints where so obscure that they thought they could optimize it easily but in the end couldn’t do it. What would they have wished to be obvious before they started. That’s why comments and commit messages are important. To tell us why.
The code most of the time tells us what and how, but why something is done is not part of the code. Often it is obvious, but maybe even equally often it is not.
The same applies to commit messages. Since I’m not working full time on my open source tools it is often the case that I pick up work on a feature one to two month after I left off. When I pick up work after a while I’ll have a look at the commit history of my feature branch and try to figure out what my thinking process was and how far I’ve implemented it before I had put it aside.
Imagine doing this with a commit history like this:
- Fixed tpyo
- Major fixup
- Best commit ever
No fun… no fun at all! If you find yourself with something like this at work it is even worse. So I try to not cause a headache for my future self as well as my co-workers and write meaningful commit messages. There are some great resources available on how to do commits right and how to write good commit messages. If you are looking for some tips on how and when to commit look at Pauline Vos’s guidelines on atomic commits. She talks about not using the commit history as a quick save history, instead as a log book including meaningful and working steps towards something which is great advice. And if you are looking for some guidelines on how to write good commit messages have a look at Chris Beams rules that he describes in detail in his blog post.
Knowing those resources I know how to behave in theory, but sometimes, more often then I’m willing to admit, I’m catching myself ignoring those best practices and getting ready to kick my future self in the nuts.
For code comments it is a bit more difficult and I think the only viable solution is code reviews. For commit messages code reviews help as well, but there is another fix available. You can write yourself a git `commit-message` hook. Git hooks are scripts that get triggered by git itself whenever a certain event is happening. With a git `commit-message` hook every time you execute git commit the hook script gets executed. You can validate the given commit message and if you come to the conclusion that the message is not good you can fail the whole commit. With something like this in place your repository only accepts commits with commit messages you previously validated. That’s nice!
But git hooks have some quirks to them. You can’t commit them to your repository and if you or someone else clones the repository magically your hooks work. Git doesn’t do this because it would be a security risk to immediately run scripts that you have just cloned. In order to make them work you have to move or symlink the hook scripts to you local .git directory yourself and make sure they can be executed.
Maybe you can accept the install quirks of git hooks but know you have to implement the validation rules yourself. Maybe you want to implement it yourself but what can you do if you dan’t want to do that at all.
CaptainHook to the rescue.
Exactly that problem was the whole premise I implemented CaptainHook for. To make it easy to commit your hooks to your repository and make sure they get executed by installing them to your local .git directory automatically. At the time I started thinking about what eventually would become CaptainHook I wanted to use git hooks at work as well, but in order to do that I had to make it as less painful as possible to get everything up and running. Nobody should have to think about it too much. Best case, they wouldn’t even recognize that something changed. I was talking to a lot of colleagues at work that actually where using git hooks to do all sorts of things for some inspiration. Not one of them did exactly the same thing, some wrote bash hook scripts and make files to install them, some wrote ant tasks and used PHP hook scripts.
I set myself to build something that would leave everybody with their hook implementation of choice and only changed the way how to install and configure them. And in the end build something so convenient they maybe start changing the way they implement their hooks as well so everybody could start sharing hooks.
I let you decide if I succeeded. You may want to give CaptainHook a try. Since composer is used in nearly all PHP projects the decision to create a composer plugin was easily made. So now, all you have to do to install the Cap’n is to install the composer plugin.
composer require --dev captainhook/plugin-composer
This will install CaptainHook and the corresponding plugin that will make sure the hooks are installed to your local .git directory every time you run composer install or update.
If you install it for the first time and you don’t have a CaptainHook configuration file yet, the installer will ask you a series of questions. If you answer the „Do you want to validate your commit messages?“ one with yes, you are already set up and done after the setup has finished.
The CaptainHook installer will create a configuration file called captainhook.json that you should commit to your repository just like your composer.json file. In this file you can configure all your hooks, no need to change your local .git directory anymore. If you answered the validate question with a yes you should already see a commit message hook configuration looking like this.
This configuration will make sure that your commit messages conform to the 7 rules Chris wrote about in his blog post I previously linked … and of course you have already read and eagerly want to use for your commit messages 😉
That’s it! Now you are all set and done to start into the git hook craziness or leave it as is and just use the commit message validation.
To give it a try, commit the captainhook.json to your repository and use the commit message
added captainhook to composer.json require-dev for commit message validation.
This should fail for several reasons.
Enjoy writing good commit messages, your future self will thank you!