gives you the power to run pre-defined scripts as a
git hook with minimal
effort. When used together with
lint-staged, you can really create a
nice developer experience for yourself. I've been using both on most of my
recent projects and I highly recommend them.
husky primarily to run a
pre-commit hook, where I do some linting and
formatting, and even run some tests on changed files. This was working great up
until a few weeks ago when I started to notice that the script defined in the
pre-commit hook was not running.
I spent several frustrating hours trying to debug the issue to no avail. This
led to some anger-induced Googling and a freshly created
GitHub issue. The lone commenter
in that issue suggested taking a look at a
git configuration option,
to potentially solve my problem.
This was helpful for two reasons. For one, it was a spot on suggestion, but
we'll get to that. Second, it forced me to jump into the
which I should've done in the first place.
After digging through the docs I realized my problem. I had recently created a
directory to hold my "global"
git hooks. I then defined the path to that
directory using the
core.hooksPath option in my
~/.gitconfig ... [core] hookspath = /path/to/global/git-hooks
according to the docs,
git where to find my hooks. What I didn't realize, was that if such an
option existed in my
.gitconfig, then those hooks would be used in favor of
any defined at the project level, i.e. in my project's
This includes the hooks that
husky creates when you install the package.
So, having a global
githooks directory affects my usage of
Frustrating. In my ideal world
git would manage this better. 🤷🏼♂
I needed to find a way to use both my global
git hook and the
without creating some complex workaround. Taking the
suggestion of the commenter,
here's what I came up with.
First, I created a
The contents of this directory, as long as they are not prefixed with a dot,
will be copied to the
$GIT_DIR after it's created. The
$GIT_DIR, in my
case, is just my project's
.git directory, which is created when running
In order to tell
git where to find this newly created directory, I defined its
location inside of
.gitconfig using the
~/.gitconfig ... [init] templateDir = /path/to/git-template-dir
I also removed the
core.hooksPath definition inside of
I no longer need it.
At this point, you'll need to move any globally defined
git hooks to the new
template directory underneath a folder named
cd /path/to/git-template-dir mkdir hooks
I ended up re-creating my lone hook instead of "moving" it. If you did the same, make sure to set the proper permissions on the hook so that it is executable:
chmod a+x /hooks/<hook-file>
Now, whenever you run
git init, the contents of your
/path/to/git-template-dir/hooks folder will be copied over to the
folder in your project.
The only caveat here is that this solution won't work with existing projects.
This is because
git will only copy over the contents of your template
directory when you run
If you have an existing project that you want to support, and you don't mind
git, you can remove the
.git directory and run
again. This isn't really ideal, especially if you value your
git history. In
that case, I would suggest manually creating your hooks in the
directory of the project as a one-off type of thing.
To wrap this post up, in order to solve my issue I created a template directory
and defined its location using the
init.templateDir option inside of
.gitconfig. From there, I created a
hooks folder inside of the template
directory, where I can now define my global
git will then copy the contents of this template directory any time I run
git init. This means my global hooks will be accessible inside of any future
projects. I can then install
husky as normal, and the package will create its
git hooks alongside the ones I've defined globally.
I hope this helps any of you who have run into the same problem. Reach out to me on Twitter if you have any questions. Happy coding!