Husky and lint-staged Configuration and Usage
This document covers how Husky and lint-staged are configured and used in this project to enforce code quality and standards through Git hooks.
Overview
- Husky: A tool that enables Git hooks in your project
- lint-staged: A tool that runs linters on staged Git files
- Purpose: Ensures that only linted and properly formatted code gets committed
Configuration
Husky Configuration
Husky is configured in the project with the .husky
directory containing Git hook scripts. If not yet configured, you can set it up with:
# Initialize Husky
npx husky init
This will create a .husky
directory with a pre-commit hook. The pre-commit hook should be configured to run lint-staged:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
lint-staged Configuration
The lint-staged configuration is defined in the package.json
file:
"lint-staged": {
"*.{js,jsx,ts,tsx,mjs}": [
"eslint --fix",
"prettier --write"
],
"*.{json,css}": [
"prettier --write"
]
}
This configuration runs ESLint and Prettier on JavaScript/TypeScript files, and just Prettier on JSON and CSS files.
How It Works
- Pre-commit Hook: When you run
git commit
, Husky triggers the pre-commit hook - lint-staged: The pre-commit hook runs lint-staged
- Linting and Formatting: lint-staged runs ESLint and Prettier only on the files that are staged for commit
- Commit Result: If all checks pass, the commit proceeds; if any check fails, the commit is aborted
Adding Custom Git Hooks
You can add additional Git hooks to enforce different rules:
Add a Pre-push Hook for Tests
Create a file at .husky/pre-push
with:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm test
Make it executable:
chmod +x .husky/pre-push
This will run your tests before pushing changes.
Add a Commit Message Hook
Create a file at .husky/commit-msg
with:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no -- commitlint --edit "$1"
This requires additional setup with commitlint
to enforce commit message conventions.
Customizing lint-staged Configuration
You can customize the lint-staged configuration to perform different actions on different file types:
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"jest --findRelatedTests"
],
"*.md": "prettier --write",
"*.css": [
"stylelint --fix",
"prettier --write"
]
}
Bypassing Hooks
In emergency situations, you can bypass hooks with Git's --no-verify
flag:
git commit --no-verify -m "Emergency fix"
However, this should be used sparingly.
Troubleshooting
Hooks Not Running
If hooks are not running:
-
Check if the hooks are executable:
chmod +x .husky/*
-
Ensure Husky is installed:
npm install husky --save-dev
-
Check if Git hooks path is set correctly:
git config core.hooksPath
It should point to
.husky
.
ESLint or Prettier Errors
If you're getting ESLint or Prettier errors that prevent commits:
- Run
npm run lint
andnpm run format
to see the errors - Fix the errors manually
- Stage the changes and try committing again
Best Practices
- Commit Small Changes: Smaller commits are easier to validate and fix if there are issues
- Keep Hooks Fast: Ensure your hooks run quickly to maintain a good developer experience
- Don't Skip Validation: Avoid using
--no-verify
as it defeats the purpose of the hooks - Run Tests Locally: Run
npm test
before pushing to ensure all tests pass - Include in CI: Include the same checks in your CI pipeline to catch issues that bypass hooks
Updating Hook Scripts
To update existing hook scripts:
- Edit the files in the
.husky
directory - Make sure they remain executable after editing
- Commit the changes to version control