Setting Up Husky, Commitlint, and Lint-Staged for Git Hooks

Sabbir Mohammad Sami
March 25, 2025ยท10 min read
Share:

Setting Up Husky, Commitlint, and Lint-Staged
1. Install Required Packages
Run the following commands to install Husky, Commitlint, and related tools:
# Install Husky and Commitlint
npm install husky @commitlint/config-conventional @commitlint/cli --save-dev
# Install lint-staged for running linters on staged files
npm install lint-staged --save-dev
npx husky init
2. Set Up Husky
Initialize Husky in your project:
npx husky install
3. Configure Commitlint
Open .husky/commit-msg
and add the following script:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx commitlint --edit --config=.commitlintrc.ts ||
(
echo '๐ค๐ค๐ค๐ค Looks like your message format is not right ๐ค๐ค๐ค๐ค
Commit Lint failed: Reformat your commit message according to convention.
'
false;
)
4. Configure Pre-Commit Hook
Open .husky/pre-commit
and add the following script:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo '๐๏ธ๐ท Styling, testing and building your project before committing'
# Check staged files
npx lint-staged ||
(
echo '๐คข๐คฎ๐คข๐คฎ Its FOKING RAW - Your styling looks disgusting. ๐คข๐คฎ๐คข๐คฎ
Staged files Check Failed. Run npm run format, add changes and try commit again.';
false;
)
# Check Prettier standards
npm run format ||
(
echo '๐คข๐คฎ๐คข๐คฎ Its FOKING RAW - Your styling looks disgusting. ๐คข๐คฎ๐คข๐คฎ
Prettier Check Failed. Run npm run format, add changes and try commit again.';
false;
)
# Check ESLint Standards
npm run lint ||
(
echo '๐ค๐๐๐ค Get that weak shit out of here! ๐ค๐๐๐ค
ESLint Check Failed. Make the required changes listed above, add changes and try to commit again.'
false;
)
# Check tsconfig standards
npm run type-check ||
(
echo '๐คก๐โ๐คก Failed Type check. ๐คก๐โ๐คก
Are you seriously trying to write that? Make the changes required above.'
false;
)
## Run tests
#pnpm run test ||
#(
# echo '๐คก๐โ๐คก Failed Test. ๐คก๐โ๐คก
# Are you seriously trying to write that? Make sure you pass all tests and try to commit again.'
# false;
#)
# If everything passes... Now we can build
echo '๐ค๐ค๐ค๐ค... Alright.... Code looks good to me... Trying to build now. ๐ค๐ค๐ค๐ค'
npm run build ||
(
echo 'โ๐ท๐จโ Better call Bob... Because your build failed โ๐ท๐จโ
Next build failed: View the errors above to see why.
'
false;
)
# If everything passes... Now we can commit
echo 'โ
โ
โ
โ
You win this time... I am committing this now. โ
โ
โ
โ
'
5. Create Commitlint Configuration
Create a .commitlintrc.ts
file and add the following configuration:
import type { UserConfig } from '@commitlint/types';
const commitConfig: UserConfig = {
extends: ['@commitlint/config-conventional'],
};
module.exports = commitConfig;
6. Update package.json
Add the following scripts and configuration to your package.json
:
{
"name": "stationery-shop-backend",
"version": "1.0.0",
"main": "dist/server.js",
"scripts": {
"start": "node ./dist/server.js",
"start:prod": "node ./dist/server.js",
"start:dev": "ts-node-dev --respawn --transpile-only src/server.ts",
"build": "tsc",
"deploy-vercel": "vercel --prod",
"test": "echo "Error: no test specified" && exit 1",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint src/**/*.ts --fix",
"format": "prettier --write .",
"prepare": "husky",
"type-check": "tsc --pretty --noEmit"
},
"lint-staged": {
"src/**/*.{ts,js}": [
"eslint --fix",
"git add"
]
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.1",
"mongoose": "^8.8.2",
"zod": "^3.23.8"
},
"devDependencies": {
"@commitlint/cli": "^19.6.0",
"@commitlint/config-conventional": "^19.6.0",
"@eslint/js": "^9.15.0",
"@types/cors": "^2.8.17",
"@types/eslint__js": "^8.42.3",
"@types/express": "^5.0.0",
"eslint": "^9.14.0",
"eslint-config-prettier": "^9.1.0",
"globals": "^15.12.0",
"husky": "^9.1.7",
"lint-staged": "^15.2.10",
"prettier": "^3.3.3",
"ts-node-dev": "^2.0.0",
"typescript": "^5.6.3",
"typescript-eslint": "^8.15.0"
}
}
7. Commit Types
Here are the supported commit types and their descriptions:
Type | Description | Example |
---|---|---|
feat: |
Adding a new feature. | feat(auth): add user authentication module |
fix: |
Fixing a bug. | fix(login): resolve token validation issue |
build: |
Changes to the build system or dependencies. | build: upgrade TypeScript to version 5.6.3 |
chore: |
Routine tasks like dependency updates or configs. | chore: update eslint configuration |
ci: |
Continuous integration (CI/CD) changes. | ci: add GitHub Actions for testing |
docs: |
Documentation changes only. | docs: add API documentation for user endpoints |
style: |
Code style changes that donโt affect functionality. | style: format code with Prettier |
refactor: |
Code refactoring without adding new features or fixing bugs. | refactor: optimize data fetching logic |
perf: |
Performance improvements. | perf: reduce database query execution time |
test: |
Adding or updating tests. | test: add unit tests for user service |
revert: |
Reverting a previous commit. | revert: undo feat: add user authentication module |
hotfix: |
Urgent fixes in production (*not part of the formal spec, but commonly used*). | hotfix: patch critical security vulnerability |
DevelopmentFrontendDevelopment