🤖 Git Hooks y Automatización
Los Git hooks son scripts que se ejecutan automáticamente en ciertos eventos del flujo de trabajo de Git. Son una herramienta poderosa para automatizar tareas, validar código y mantener la calidad del proyecto.
¿Qué son los Git Hooks?
Los hooks son scripts personalizables que Git ejecuta antes o después de eventos específicos como commits, pushes, merges, etc. Te permiten automatizar tareas repetitivas y establecer políticas de calidad de código.
Tipos de Hooks
Client-side hooks:
pre-commit: Se ejecuta antes de hacer commitprepare-commit-msg: Se ejecuta antes de editar el mensaje de commitcommit-msg: Se ejecuta para validar el mensaje de commitpost-commit: Se ejecuta después de hacer commitpre-push: Se ejecuta antes de hacer push
Server-side hooks:
pre-receive: Se ejecuta cuando se reciben objetospost-receive: Se ejecuta después de recibir objetosupdate: Se ejecuta para cada branch que se actualiza
Configuración de Hooks
Los hooks se almacenan en .git/hooks/ y deben ser ejecutables:
# Ver hooks disponibles
ls .git/hooks/
# Crear un hook pre-commit
touch .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Ejemplo: Hook Pre-commit
#!/bin/sh
# .git/hooks/pre-commit
# Ejecutar linting
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Linting falló. Corrige los errores antes de hacer commit."
exit 1
fi
# Ejecutar tests
npm run test
if [ $? -ne 0 ]; then
echo "❌ Tests fallaron. Corrige los errores antes de hacer commit."
exit 1
fi
echo "✅ Pre-commit hooks pasaron exitosamente."
Herramientas Populares
Husky
Simplifica la gestión de hooks en proyectos Node.js:
# Instalar Husky
npm install --save-dev husky
# Inicializar
npx husky init
# Añadir hook
npx husky add .husky/pre-commit "npm run lint"
lint-staged
Ejecuta linters solo en archivos staged:
{
"lint-staged": {
"*.js": ["eslint --fix", "git add"],
"*.css": ["stylelint --fix", "git add"]
}
}
Casos de Uso Comunes
1. Validación de Código
#!/bin/sh
# Validar sintaxis antes de commit
php -l *.php
2. Formato de Mensaje de Commit
#!/bin/sh
# commit-msg hook
commit_regex='^(feat|fix|docs|style|refactor|test|chore): .{1,50}'
if ! grep -qE "$commit_regex" "$1"; then
echo "❌ Formato de commit inválido."
echo "Usa: type: description"
echo "Ejemplo: feat: añadir nueva funcionalidad"
exit 1
fi
3. Prevenir Push a Master
#!/bin/sh
# pre-push hook
protected_branch='master'
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ $current_branch = $protected_branch ]; then
echo "❌ Push directo a $protected_branch está prohibido."
exit 1
fi
Integración con CI/CD
GitHub Actions
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: npm ci
- run: npm run lint
- run: npm test
GitLab CI
stages:
- test
- deploy
lint:
stage: test
script:
- npm run lint
test:
stage: test
script:
- npm test
Mejores Prácticas
1. Mantén los Hooks Rápidos
# ✅ Bueno: Solo archivos modificados
git diff --cached --name-only | grep '\.js$' | xargs eslint
# ❌ Malo: Todo el proyecto
eslint .
2. Proporciona Retroalimentación Clara
echo "🔍 Ejecutando tests..."
echo "✅ Tests completados exitosamente"
echo "❌ Error: 3 tests fallaron"
3. Permite Bypass en Emergencias
# Permitir bypass con --no-verify
git commit --no-verify -m "hotfix: arreglo crítico"
4. Versiona tus Hooks
# Crear carpeta de hooks en el repo
mkdir .githooks
cp .git/hooks/pre-commit .githooks/
# Configurar Git para usar la carpeta
git config core.hooksPath .githooks
Hooks Avanzados
Hook de Análisis de Performance
#!/bin/sh
# post-commit hook para análisis de performance
bundle_size_before=$(cat .bundle-size)
npm run build
bundle_size_after=$(wc -c < dist/bundle.js)
echo $bundle_size_after > .bundle-size
if [ $bundle_size_after -gt $((bundle_size_before + 10000)) ]; then
echo "⚠️ El bundle creció más de 10KB"
echo "Antes: ${bundle_size_before} bytes"
echo "Después: ${bundle_size_after} bytes"
fi
Hook de Validación de Dependencias
#!/bin/sh
# pre-commit: verificar dependencias vulnerables
npm audit --audit-level high
if [ $? -ne 0 ]; then
echo "❌ Vulnerabilidades críticas encontradas"
echo "Ejecuta: npm audit fix"
exit 1
fi
Herramientas Adicionales
commitizen
Estandariza mensajes de commit:
npm install -g commitizen
npm install -g cz-conventional-changelog
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
conventional-changelog
Genera changelogs automáticamente:
npm install --save-dev conventional-changelog-cli
npx conventional-changelog -p angular -i CHANGELOG.md -s
Resolución de Problemas
Hook No Se Ejecuta
# Verificar permisos
ls -la .git/hooks/pre-commit
# Debe mostrar -rwxr-xr-x (ejecutable)
# Dar permisos
chmod +x .git/hooks/pre-commit
Hook Falla Silenciosamente
# Añadir debugging
echo "🔧 Ejecutando pre-commit hook..." >&2
set -e # Salir en cualquier error
Compartir Hooks en el Equipo
# Crear script de setup
#!/bin/bash
# setup-hooks.sh
cp .githooks/* .git/hooks/
chmod +x .git/hooks/*
echo "✅ Hooks instalados correctamente"
Los Git hooks son una herramienta fundamental para mantener la calidad del código y automatizar workflows. Implementa hooks gradualmente y siempre proporciona documentación clara para tu equipo.
Ejercicios Prácticos
- Hook Pre-commit Básico: Crea un hook que ejecute linting antes de cada commit
- Validación de Mensaje: Implementa validación de formato de mensajes de commit
- Hook de Testing: Configura un hook que ejecute tests antes de push
- Integración con CI: Conecta hooks locales con pipeline de CI/CD
- Hook Personalizado: Crea un hook que valide archivos específicos de tu proyecto