Spotlight
2019-08-13

Software Spotlight: Husky, git hooks made easy

Feature image

I stumble upon great open source libraries or tools nearly every day - some of them having thousands of stars of GitHub and I've still never heard of them. I guess the fact that there are more than 100 million repositories just on GitHub somehow explains that.

Nevertheless, I've always liked to do some kind of series on my blog - and I guess showing some of my findings is a pretty good way to do so - especially since some of them have become an important element of my very own workflow.

So here's the first (of hopefully many!) software spotlight, featuring Husky by typicode, an open source library to ease the process of creating git hooks.

Husky, Git hooks made easy

Husky is a simple tool which makes it possible to easily create git hooks in your package.json.

What it does

Instead of manually creating git hooks within your .git directory Husky allows you to simply add your hooks within your package.json, e.g.:

{
  ... your package.json
  "husky": {
    "hooks": {
      "pre-push": "npm test"
    }
  }
}

This would execute npm test before every git push and if npm test fails the push will not be executed.

Sometimes you might want to skip hooks (e.g. when working on a WIP branch) - this can easily be done by adding the --no-verify flag to your git command.

Hooks created by Husky are removed when Husky is uninstalled.

How it works

Under the hood Husky just creates normal git hooks when it's installed. If you take a look at in your .git/hooks/pre-pull for example you'll find a generated file by Husky:

#!/bin/sh
# husky

# Hook created by Husky
#   Version: 3.0.1
#   At: 8/2/2019, 9:53:34 AM
#   See: https://github.com/typicode/husky#readme

# From
#   Directory: /<your-project>/node_modules/husky
#   Homepage: https://github.com/typicode/husky#readme

scriptPath="node_modules/husky/run.js"
hookName=`basename "$0"`
gitParams="$*"

[...]

This generated files are responsible for executing proper hooks (in this case: pre-push) for the executed command (in this case: git push).

As mentioned above these files are removed when Husky is removed.

Why to use it

One could say that a proper CI setup would probably do the same as Husky - which I partially agree with. But there's one thing which lead us (which means the company I work for) to use Husky, even if our CI setup runs all tests, linting and related stuff: our CI takes a pretty long time to get done. One build takes between 30 and 60 minutes - and you don't want to wait that long to get a notification which tells you essentially:

Your build failed because you've forgotten a space. Noob.

Our pre-push hook just runs npm run lint (which lints all .ts and .scss files) to prevent exactly such cases. npm test takes a bit too much time for a git hook which is why we've gone just for the linting.

An additional advantage is that it makes it very easy to share git hooks within your team without having to change any git configuration.