Mathieu Larose

Rethinking Git Pre-Commit Hooks

December 2025

I've worked on many projects where, as part of the development setup, tools like Husky are used to automatically inject git pre-commit hooks. Once installed, these hooks run locally on the developer's machine and force every commit to pass whatever checks the team has enabled. If a commit doesn't pass, git will reject it, preventing you from saving a local checkpoint of your work. Common checks include enforcing code formatting, checking for untracked files, or even running unit tests.

This post looks at why enforcing Git pre-commit hooks doesn't work for every developer and explores a more flexible alternative.

First, why is enforcing checks on every commit a bad thing? Because some developers, like me, make lots of draft commits that are never meant to be shared. I use commits as checkpoints. I might be experimenting with something risky and want an easy rollback point, or it might be the end of the day and I want to save my work. None of these commits will be reviewed by others. They only exist for me.

So the last thing I want when I'm trying to save my work is a tool deciding whether I'm allowed to do so. Just let me commit. Yes, I know I can skip the hooks with --no-verify, manually remove them (though they will be automatically reinstalled the next time you run npm install, for example), or set HUSKY=0 for Husky, but having to do this every time is annoying. Why create the problem in the first place? I don't want to bypass checks. I want to decide when to run them, when I know my code is ready, not every time I create a checkpoint.

A better alternative is this. Instead of enforcing checks in pre-commit hooks, expose those same checks as explicit commands. For example: make test, make test.types, make test.unit, etc. Developers are then free to run these commands when it makes sense for them, and they can still wire them into pre-commit hooks if they want.

An added bonus is that these same commands can be reused in CI/CD pipelines to enforce checks before merging a pull request.

Like this article? Get notified of new ones: