Humans make mistakes - that’s why we write tests for our code. Automatically running tests or other checks when committing code is a useful way to catch mistakes and prevent committing bad code. Git provides many different hooks that can be used to automatically run such checks: there’s a good introduction at https://githooks.com/ with links to many different tools for configuring and managing Git hooks. Originally I decided not to use them because the hooks they provide weren’t useful to me, but recently I checked out https://pre-commit.com/ again and there are many more hooks available so I have migrated to that.
There are many packaged hooks available; I’ve used those for complex checks, but for simpler checks I’ve found it easier to just write a hook config, e.g. running shellcheck requires just 5 lines of config. My bin directory has the most checks because it has the biggest mix of code.
If you’re interested in writing your own hooks Link to heading
- You can get the files being committed using
git diff --cached --name-only, and you can further filter the list down using
--diff-filter=ACMto only output files that have been Added, Copied, or Modified; see
git help difffor more filter and output options. This can make your checks faster, and allow you to skip checks for files you’re not trying to commit yet. https://pre-commit.com/ only runs checks for files being committed.
- Annoyingly, hooks are not versioned or tracked in any way :( You can deal with
this by putting the hook in the root of the repository and symlinking it into
.git/hooks/directory; this gives version control for the hook code but still requires manual action every time the repository is cloned to create the symlink. https://pre-commit.com/ also requires manual action when the repository is cloned.
- A warning about git pre-commit hooks: they run with whatever contents are in
your local directory, so if you’re partially committing they might pass
incorrectly. E.g. if you modify
foo_test.go, but you’re only committing
go testwill pass in a pre-commit but won’t pass on the committed code because your changes to
foo.gowon’t have been committed. This is one of the problems that https://pre-commit.com/ saves you from - it stashes uncommitted changes so that checks run against only the code being committed.