Category Archives: Husky

Pre-commit linting with husky and lint-staged

You’ve got your JavaScript or TypeScript project, you’ve added eslint and set-up all the rules and you’re happily coding, committing and pushing changes to GIT, the only problem is you’re ignoring your lint results or worse still, not even running lint prior to committing changes.

Enter, Husky and link-staged.

Note: I’m describing using Husky on a Windows machine, installation may vary depending on OS.

Let’s add them to our project using

  • yarn add -D husky lint-staged

Now, within package.json (after the scripts section is as good a place as any) add the following

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*.{js,jsx,ts,tsx}": [
    "eslint"
  ],
  "*.{js,jsx,ts,tsx,json}": [
    "prettier --write",
    "git add"
  ]
},

Note: Husky also supports it’s own configuration files .huskyrc, .huskyrc.json or .huskyrc.js

Husky adds the ability to run applications/code on various GIT hooks. The most useful, from the perspective of this post, is the pre-commit hook as we want to stop any commits until all lint failures are fixed.

In the configuration, above, we call lint-staged when GIT commit is executed. The commit hook will run husky and husky will then run lint-staged with the previously defined configuration.

Lint-staged runs the linter (in this configuration, eslint) over our various staged files and also executes prettier against the same files (as well as JSON) adding these changes.

With these two tools set-up, we no longer have the option to forget to run the linter or ignore it as it’s now part of the commit process. Ofcourse we only fail a commit on staged files, so in situations where we add these applications to an existing project we’re not force to fix all linting issues until we attempt to actually stage and commit the files.

I’ve merged or rebased and don’t want to fix everything

Obviously all’s great until you find old code that may need to be merged or we rebase and now have staged files which fail the lint process and we don’t want to fix them.

In such cases, simple set the environment variable HUSKY_SKIP_HOOKS to true or 1 prior to running a git command, for example

HUSKY_SKIP_HOOKS=1 git rebase ...

See Skip all hooks (rebase).

Beware the formatting infinite fix then fail circle

One thing to be aware of, if you’re using prettier, as per the configuration above, make sure your eslint and prettier adhere to the same rules – initially I found that eslint would complain about some formatting (I cannot recall which at the moment) so would fail the commit, upon changing the offending code to pass eslint, the prettier command ran as part of lint-staged and changed the format back, meaning it then failed the lint and would fail the commit again.

However, running prettier and having it write changes in obviously a great way to (at least try) to enforce consistency on our code format.