Enforce Code Standards at Commit with husky + lint-staged
This article explains how to use husky and lint-staged to automatically run ESLint and Prettier on staged files before each Git commit, preventing non-compliant code from entering the repository, with step-by-step setup for husky v9, configuration details, common pitfalls, and the complete commit workflow.
Why Enforce Checks at Commit Time
Relying on teammates to manually run linting is unreliable; manual npm run lint is easily forgotten; running lint on the entire project becomes slow as the codebase grows. The solution combines husky to manage Git hooks and lint-staged to run checks only on staged files, making the process automatic, fast, and precise.
husky Version Differences
husky acts as a Git hooks manager, avoiding manual shell scripts in .git/hooks. A key version difference exists:
v4 and below: Configuration via package.json under husky.hooks.
v5+ (current mainstream, v9 used here): Command-line initialization creates a .husky/ directory where hook scripts live.
Pitfall: Old tutorials showing husky.hooks in package.json do not work with v9. Verify version with npm view husky version before installing.
Complete Installation Steps (husky v9)
# 1. Install husky and lint-staged
npm install -D husky lint-staged
# 2. Initialize (creates .husky/ folder at project root)
npx husky initInitialization typically adds npm pkg set scripts.prepare="husky" to package.json. The core work is editing .husky/pre-commit to contain a single line:
# .husky/pre-commit content
npx lint-stagedThis ensures that on every commit, only staged files are passed to lint-staged.
Configuring lint-staged: Check Only Staged Files
Add a lint-staged section to package.json mapping file patterns to commands:
{
"lint-staged": {
"*.{js,vue,jsx,ts}": "eslint --fix --cache",
"*.{js,vue,jsx,ts,css,md}": "prettier --write"
}
}Line-by-line meaning:
JavaScript, Vue, JSX, TypeScript files → run eslint --fix --cache (auto-fix what it can, error on the rest).
Those plus CSS and Markdown → run prettier --write to enforce formatting. --cache speeds up subsequent runs by only checking changed files.
lint-staged's advantage: it only processes files that have been git add ed, so a small change stays fast and avoids re-linting untouched legacy code.
Full Commit Workflow
git add .
git commit -m "feat: add button component"At commit time:
The pre-commit hook is triggered by husky.
lint-staged collects the staged files.
It runs ESLint and Prettier sequentially on those files.
If any unfixable errors appear, the commit is aborted ; the terminal shows file paths and line numbers. Fix, re-add, and commit again.
If all pass, the commit succeeds.
Typical experience: ESLint auto-fixes quotes/semicolons, files are modified, and the terminal prompts to re-add and commit.
Common Pitfalls and Fixes
Windows hook not executing / permission issues: Ensure .git/hooks belongs to the current project. New husky uses npx so manual permission changes are rarely needed; on Mac/Linux run chmod +x .husky/pre-commit if Permission denied occurs.
lint-staged config changes not taking effect: Verify npx lint-staged exists in pre-commit; commit once to test.
Temporarily skipping checks: Use git commit --no-verify -m "..." for emergencies, but restrain from routine use.
Leftover old husky configuration: When migrating to v9, remove the husky.hooks section from package.json and rely solely on the .husky/ directory.
Summary
husky: manages hooks → npx husky init generates .husky/
pre-commit contains npx lint-staged
lint-staged: checks only staged files, runs commands per extension
Result: code that fails ESLint / formatting cannot enter the repoWith this, the loop ESLint/Prettier config → editor format-on-save → pre-commit enforced checks is closed. To further standardize commit messages, add commitlint for a complete engineering standard.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Farmer Manor Chronicle
A heart like drifting clouds, ever at ease; a mind like flowing water, free to roam.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
