A simple Git pre-commit hook running PHP_CodeSnifferLast updated: 2020-07-14 :: Published: 14/07/2020 :: [ history ]
Git hooks are scripts that are run every time a specific Git-related event happens, like a commit or a checkout.
They can be used to do a lot of different things; a common use case is to scan the code which is about to be committed in search for violations of a coding standard, so they are fixed before the code is pushed to the repository, which is way quicker than letting the build pipeline flag them (or worse, a peer reviewer, who'd rather spend their time focussing on more important issues).
This is the kind of hook I was looking for for one of my projects, and since I couldn't find something simple enough I ended up writing my own.
PHP has a few coding standards flying around, but for the past few years the ones from the PHP Framework Interop Group (PHP-FIG) seem to have gained the most traction. They currently offer three different levels:
Each one builds on the previous one; PSR-12 was approved in September 2019 and supersedes PSR-2, which is now deprecated.
PHP_CodeSniffer is a tool composed of two different scripts:
phpcs, which detects violations of a defined coding standard;
phpcbf, which automatically fixes some of them.
My goal was to trigger the first script at every commit, and to offer to run the second script if some violations were detected. Whether or not the second script is run, if some violations remain the commit does not happen, unless a specific option is used.
Make sure it is executable:
$ chmod +x pre-commit
Install PHP_CodeSniffer following one of the suggested methods – I personally like to install it on a per-project basis as a Composer dependency, but it's really up to you:
$ composer require --dev squizlabs/php_codesniffer
Once you've done that, you can update the
STANDARD variable at the top of the
pre-commit file to change the coding standard, or leave
PSR12 by default.
The hook also assumes that PHP_CodeSniffer's
bin folder is at the same level as the
.git folder by default, but depending on the chosen installation that might not be the case. You can set a different location simply by updating the
#!/bin/bash STANDARD="PSR12" BIN="./vendor/bin"
That's it! For other standards and options, please visit PHP_CodeSniffer's usage page.
All you have to do now is commit some new code; PHP_CodeSniffer will analyse it, flag the violations if it finds any and ask you whether you want it to fix them for you:
It will also automatically stage the files it updates, and if it cannot fix them all, it will ask you to address the remaining ones manually.
If you want to commit anyway, all you have to do is to use the
--no-verify option to skip the hook altogether:
$ git commit --no-verify
Of course Git hooks are nothing new, and there are plenty of open source projects leveraging them, for all sorts of languages and purposes. In my case I was looking for something simple since I only needed a single hook anyway, but once you've got multiple hooks, managing them can become a bit of a pain.
I reviewed a number of tools and found this one that looked quite good, although I must admit I was a little confused by the concept of templates in introduces. This project also comes with a blog post explaining it in a bit more detail.