You don't need husky for git-hooks!
 
 When going mono-repo, I noticed that the Node.js package "husky" can actually be replaced by a single line of code. And it works for people that do not have Node.js installed.
The title sounds like a clickbait, and I may be wrong. Maybe husky is actually doing more than I think. But I really thought: “Why do I need this package at all?”.
When I converted Gachou to a mono-repo, I wondered what I
should to about the pre-commit hooks and lint-staged for linting and
formatting. Since I had to run it in multiple sub-repositories, with only one
commit hook, I thought about installing husky in the root repository as well.
I did not like this idea. Maybe some Java-developer wants to do something in the
backend. Even if she does not touch anything in the Node.js repositories, she
has to install Node.js. So I went and I tried to figure out what husky
actually does.
What does husky do?
Usually, git looks for hooks in the .git/hooks directory, but of course, this
is not committed to the repository, so you cannot use it to share your hooks.
Husky configures git to use a different directory for this repository. If you
look at .git/config, you will see
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
        hooksPath = .husky    <---- This is it!The hooksPath is set to the .husky directory, and that is where a
pre-commit-script is placed by husky.
Do it yourself!
For my mono-repo, I added a simple script bin/init-repo.sh with the following
content.
#!/bin/bash
git config core.hooksPath .git-hooksThen I added a file .git-hooks/pre-commit to the repository:
#!/bin/bash
set -e
( cd e2e-testing && npx lint-staged )
( cd web-ui && npx lint-staged )I also had to make this file executable, otherwise git will just ignore it with a warning.
chmod a+x .git-hooks/pre-commitWhen a new user clones the mono-repo, she can run init-repo.sh and the hooks
will be setup just fine. But she still needs Node.js to run the hook itself,
because npx lint-staged does not work otherwise.
Restrict pre-commit checks to relevant sub-directories
As long as my potential Java-dev does not do changes in web-ui or
e2e-testing, she does not need to execute lint-staged, so how can we check
that?
git diff --quiet --cached e2e-testingwill look for staged (“cached”) differences in the repository inside
e2e-testing. It will not print anything (“quiet”), but it will return with a
non-zero exit-code if changes are found. We can use that in our pre-commit hook:
#!/bin/bash
set -e
if ! git diff --quiet --cached e2e-testing ; then
  ( cd e2e-testing && npx lint-staged )
fi
if ! git diff --quiet --cached web-ui ; then
  ( cd web-ui && npx lint-staged )
fiThis will only run lint-staged if there are changes in the given
subdirectories.
Replacing husky
Assuming, you don’t have a mono-repo, but just a simple Node.js project. I think, instead of husky, you can also do the following:
- 
create a file .git-hooks/pre-commit
- 
make it executable 
- 
add a script to your package.json{ "scripts": { "prepare": "git config core.hooksPath .git-hooks" } }
This should have the same effect.
Conclusion / Disclaimer
I haven’t had a thorough look at the husky source-code. Maybe there other things that I don’t know. And if you are using Node.js anyway, you might as well use it. It has no dependencies after all.
But I was glad to find out, that I could very simply have the same thing without making the root-project in my mono-repo a Node.js project.