I have a project with a frontend in JS and backend in Python. Frontend had been configured with husky pre-commit hook. Today I've configured Pylint with pre-commit library but husky hooks had been overwritten by that move. Is it possible to combine pre-commit and husky libraries? If not... what's the best way to solve the problem?
2 Answers
pre-commit has a "migration mode" for running other existing hook frameworks. It seems that husky is slightly too clever in their hook implementation for detecting what hook you're running -- they base it on the filename that's being executed
the way pre-commit's migration mode works is it takes any existing hook script (in this case, the hook script written by husky to .git/hooks/pre-commit
) and adds the extension .legacy
. then during execution it runs that script.
but to husky, it looks like the pre-commit.legacy
hook is running (!)
a little hack is to define pre-commit.legacy
in package.json
which seems to work:
package.json
{
"husky": {
"hooks": {
"pre-commit.legacy": "echo hello world"
}
},
"dependencies": {
"husky": "^4.3.0"
}
}
.pre-commit-config.yaml
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
$ git commit -m "both"
husky > pre-commit.legacy (node v12.18.3)
hello world
Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Passed
Check Yaml...........................................(no files to check)Skipped
Check for added large files..............................................Passed
[master 7bd8807] both
1 file changed, 1 insertion(+), 1 deletion(-)
that said, this seems fragile. pre-commit is designed to support many different programming languages (even though it is written in python, it has native support for 10+ programming languages (including javascript))
A first place replacement might be to just call husky from a local
pre-commit hook:
package.json
{
"husky": {
"hooks": {
"pre-commit": "echo hello world"
}
},
"dependencies": {
"husky": "^4.3.0"
}
}
.pre-commit-config.yaml
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: local
hooks:
- id: husky-run-pre-commit
name: husky
language: system
entry: node_modules/.bin/husky-run pre-commit
pass_filenames: false
always_run: true
execution
$ pre-commit run --all-files --verbose
Trim Trailing Whitespace.................................................Passed
- hook id: trailing-whitespace
- duration: 0.03s
Fix End of Files.........................................................Passed
- hook id: end-of-file-fixer
- duration: 0.03s
Check Yaml...............................................................Passed
- hook id: check-yaml
- duration: 0.05s
Check for added large files..............................................Passed
- hook id: check-added-large-files
- duration: 0.05s
husky....................................................................Passed
- hook id: husky-run-pre-commit
- duration: 0.07s
husky > pre-commit (node v12.18.3)
hello world
this solution however doesn't take advantage of pre-commit's js support, it just invokes the already-existing husky hooks
a more native solution would be to install js hooks directly with pre-commit, for example if you're using eslint:
repos:
- repo: https://github.com/pre-commit/mirrors-eslint
rev: 'v7.9.0' # Use the sha / tag you want to point at
hooks:
- id: eslint
$ pre-commit run --all-files
[INFO] Initializing environment for https://github.com/pre-commit/mirrors-eslint.
[INFO] Initializing environment for https://github.com/pre-commit/mirrors-eslint:eslint@7.9.0.
[INFO] Installing environment for https://github.com/pre-commit/mirrors-eslint.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
eslint...................................................................Passed
disclaimer: I am the author of pre-commit

- 61,815
- 15
- 148
- 207
-
hehe :)) Thank you for very useful and comprehensive answer. I've tried to install eslint directly via pre-commit but it was complaining weirdly... smth like `Configuration for rule "react/jsx-boolean-value" is invalid`... That's why I've decided to take an old-good duck tape from the shelf :D – Aleksandr Zakharov Sep 22 '20 at 14:04
-
ah you probably want to [include your plugins](https://github.com/pre-commit/mirrors-eslint#using-eslint-with-pre-commit) – anthony sottile Sep 22 '20 at 16:41
-
How can I get the native solution (3rd option) to run a command from the package.json? In husky I run lint and lint:fix to autocorrect linting issues when you check in. Also does the native solution use the project's `.eslintrc.json` for linting? – afriedman111 Mar 16 '22 at 13:25
A solution that works better for me, with the latest version of pre-commit (2.14.0) and husky (7.0.2) is to integrate pre-commit into husky, rather than the other way around.
In the ./husky/_/pre-commit
file, I added pre-commit run
.
See below:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
npx pretty-quick --staged
pre-commit run

- 1,184
- 11
- 5