Husky y lint-staged (Ganchos de pre-commit)
Ejecuta ESLint y Prettier automáticamente en los archivos staged antes de cada commit para detectar problemas temprano.
Receta
Tarjeta de referencia rápida — lista para copiar y pegar.
# Instala husky y lint-staged
npm install --save-dev husky lint-staged
# Inicializa husky
npx husky init
# El comando init crea .husky/pre-commit
# Edítalo para ejecutar lint-staged
echo "npx lint-staged" > .husky/pre-commitCuándo usarlo: Cualquier proyecto en equipo donde quieras garantizar que el código cometido pase los controles de linting y formateo.
Ejemplo de Trabajo
# .husky/pre-commit
npx lint-staged// package.json
{
"scripts": {
"lint": "next lint",
"format": "prettier --write .",
"prepare": "husky"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix --no-warn-ignored",
"prettier --write"
],
"*.{css,json,md}": [
"prettier --write"
]
}
}Lo que demuestra esto:
- Husky se engancha al evento pre-commit de Git
- lint-staged ejecuta ESLint y Prettier solo en archivos que son staged (
git add) - Los archivos TypeScript obtienen linting y formateo; otros archivos solo obtienen formateo
- El script
prepareasegura que husky se instale automáticamente después denpm install
Análisis Profundo
Cómo Funciona
- Husky utiliza ganchos de Git (
.husky/pre-commit) para ejecutar comandos antes de cada commit - lint-staged recopila archivos de
git diff --stagedy los pasa a los comandos configurados - Los comandos se ejecutan en secuencia por patrón glob — si ESLint falla, Prettier no se ejecuta y el commit se bloquea
- Los archivos reparados se revisten automáticamente para que el commit incluya las correcciones
- El script
preparese ejecuta después denpm install, asegurando que los ganchos estén configurados para cada desarrollador
Variaciones
Con Biome en lugar de ESLint + Prettier:
{
"lint-staged": {
"*.{ts,tsx,js,jsx,json,css}": [
"biome check --write --no-errors-on-unmatched"
]
}
}Con revisión de tipos (más lento pero exhaustivo):
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix --no-warn-ignored",
"prettier --write"
]
}
}# .husky/pre-commit
npx lint-staged
npx tsc --noEmitNota: tsc --noEmit revisa el proyecto completo, no solo los archivos staged, porque TypeScript necesita el contexto completo del proyecto.
Linting de mensajes de commit con commitlint:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
echo "npx commitlint --edit \$1" > .husky/commit-msg// commitlint.config.js
export default { extends: ["@commitlint/config-conventional"] };Omitiendo ganchos (escotilla de escape):
# Cuando realmente necesitas eludir (depuración, commits WIP)
git commit --no-verify -m "WIP: trabajo en progreso"Notas de TypeScript
// lint-staged pasa rutas de archivo a ESLint, que funciona con
// archivos TypeScript sin problemas siempre que @typescript-eslint
// esté configurado.
// Nota: ESLint --fix puede corregir automáticamente algunos problemas de TypeScript:
// - Eliminar importaciones no utilizadas
// - Agregar la palabra clave `type` a importaciones solo de tipos
// - Corregir violaciones de consistent-type-importsGotchas
Cosas que te van a morder. Cada gotcha incluye qué sale mal, por qué sucede y la solución.
-
Los ganchos no se ejecutan después de clonar — Los ganchos de Git no se cometieron al repo; viven en
.git/hooks/. Los nuevos desarrolladores deben ejecutarnpm install(que disparaprepare). Solución: Asegúrate de que"prepare": "husky"esté en tus scripts depackage.json. -
Advertencias de ESLint en archivos ignorados — Cuando lint-staged pasa rutas de archivo a ESLint, los archivos que coinciden con tus ignorados de ESLint disparan advertencias. Solución: Agrega la flag
--no-warn-ignoredal comando de ESLint en la configuración de lint-staged. -
Problemas de staging parcial — Si revistes solo parte de un archivo (
git add -p), lint-staged opera en el archivo completo, que puede incluir cambios no staged. Solución: Ten conocimiento de esta limitación. Para casos críticos, reviste el archivo completo. -
Ganchos de pre-commit lentos — Ejecutar revisión de tipos (
tsc) en cada commit puede tomar 10 o más segundos en proyectos grandes. Solución: Ejecutatscsolo en CI. Mantén los ganchos de pre-commit rápidos limitándolos a ESLint y Prettier en archivos staged. -
CI no ejecuta ganchos — Los ganchos de Git son solo locales. Los entornos de CI no ejecutan ganchos de pre-commit. Solución: Siempre ejecuta linting y controles de formateo en CI como red de seguridad. Ver Linting en CI/CD.
Alternativas
Otras formas de resolver el mismo problema — y cuándo cada una es la mejor opción.
| Alternativa | Úsalo Cuando | No lo Uses Cuando |
|---|---|---|
lefthook | Quieres ganchos más rápidos con ejecución paralela, escrito en Go | Husky + lint-staged funciona bien para tu proyecto |
| Linting solo en CI | No quieres ralentizar los commits locales | Quieres retroalimentación instantánea antes de hacer push |
nano-staged | Quieres una alternativa más pequeña y rápida a lint-staged | Necesitas características avanzadas de lint-staged como resolvers personalizados |
| VS Code format-on-save | Desarrollador solo, sin CI | Proyectos en equipo donde la consistencia debe ser reforzada |
FAQs
¿Qué hace el script "prepare" en package.json?
- Se ejecuta automáticamente después de
npm install. - Asegura que los ganchos de Git de Husky estén instalados para cada desarrollador que clone el repo.
- Sin él, los nuevos desarrolladores no tendrían ganchos de pre-commit hasta que ejecuten manualmente
npx husky init.
¿Cómo sabe lint-staged qué archivos procesar?
- Recopila archivos de
git diff --staged(archivos que hasgit add-ado). - Coincide archivos staged contra los patrones glob en tu configuración.
- Solo los archivos staged coincidentes se pasan a los comandos configurados.
¿Qué pasa si ESLint falla durante el gancho pre-commit?
- El commit se bloquea y no se realiza.
- Los comandos se ejecutan en secuencia por glob -- si ESLint falla, Prettier no se ejecuta.
- Corrige los errores de ESLint e intenta hacer commit de nuevo.
¿Cómo omito el gancho pre-commit en una emergencia?
git commit --no-verify -m "WIP: trabajo en progreso"Úsalo con moderación para depuración o commits WIP. CI seguirá atrapando problemas.
Gotcha: ¿Por qué los ganchos no se ejecutan después de un clon fresco?
- Los ganchos de Git viven en
.git/hooks/, que no se comete al repo. - Los nuevos desarrolladores deben ejecutar
npm install, que dispara el scriptprepare. - Asegúrate de que
"prepare": "husky"esté en tus scripts depackage.json.
¿Puedo ejecutar revisión de tipos en el gancho pre-commit?
# .husky/pre-commit
npx lint-staged
npx tsc --noEmit- Sí, pero
tsc --noEmitrevisa el proyecto completo, no solo los archivos staged. - Esto puede tomar 10+ segundos en proyectos grandes.
- Considera ejecutar
tscsolo en CI para mantener los ganchos rápidos.
¿Cómo uso Biome con lint-staged en lugar de ESLint + Prettier?
{
"lint-staged": {
"*.{ts,tsx,js,jsx,json,css}": [
"biome check --write --no-errors-on-unmatched"
]
}
}Gotcha: ¿Qué pasa con el staging parcial (git add -p)?
- lint-staged opera en el archivo completo, no solo los hunks staged.
- Esto significa que los cambios no staged en el mismo archivo también se procesan.
- Para casos críticos, reviste el archivo completo en lugar de staging parcial.
¿Cómo agrego linting de mensajes de commit con commitlint?
npm install --save-dev @commitlint/cli @commitlint/config-conventional
echo "npx commitlint --edit \$1" > .husky/commit-msgEsto refuerza mensajes de commit convencionales como feat:, fix:, docs:.
¿Reviste lint-staged archivos después de repararlos?
- Sí. Los archivos reparados se revisten automáticamente para que el commit incluya las correcciones.
- No necesitas
git addmanualmente archivos después de auto-fix de ESLint o Prettier.
¿Por qué ESLint advierte sobre archivos ignorados cuando se ejecuta a través de lint-staged?
- lint-staged pasa rutas de archivo explícitas a ESLint.
- Los archivos que coinciden con tus patrones de ignorancia de ESLint disparan advertencias cuando se pasan explícitamente.
- Agrega
--no-warn-ignoredal comando de ESLint en tu configuración de lint-staged.
¿Qué problemas de TypeScript puede auto-arreglar ESLint en el gancho pre-commit?
- Eliminar importaciones no utilizadas.
- Agregar la palabra clave
typea importaciones solo de tipos. - Corregir violaciones de
consistent-type-imports. - Reordenar importaciones según las reglas de
import/order.
Relacionado
- Configuración de ESLint para Next.js — Configuración de ESLint para el paso de lint
- Configuración de Prettier — Configuración de Prettier para el paso de formateo
- Integración de ESLint + Prettier — asegurar que no haya conflictos entre los dos
- Linting en CI/CD — Red de seguridad de CI para ganchos
- EditorConfig y Configuración de VS Code — Consistencia a nivel de editor