Git hooks com Husky e lint-staged: qualidade automática antes do commit
1. Introdução aos Git Hooks e Automação de Qualidade
Git hooks são scripts executados automaticamente em pontos específicos do ciclo de vida do Git, como antes de um commit (pre-commit) ou antes de um push (pre-push). Eles funcionam como gatilhos que podem validar, transformar ou impedir operações no repositório. Quando combinados com ferramentas de qualidade de código, os hooks se tornam uma barreira eficiente contra erros comuns, garantindo que apenas código padronizado e funcional seja versionado.
Automatizar verificações antes do commit reduz drasticamente a introdução de bugs, elimina debates sobre formatação em code reviews e força a adoção de padrões de forma consistente. Duas ferramentas se destacam nesse ecossistema: o Husky, que gerencia a instalação e execução de hooks de forma simplificada, e o lint-staged, que executa linters e formatadores apenas nos arquivos que serão commitados (staged), otimizando o tempo de verificação.
2. Configuração Inicial do Husky no Projeto
O Husky moderno (versão 9+) utiliza uma abordagem baseada em arquivos de configuração no diretório .husky/. Para iniciar, instale o pacote via npm:
npm install husky --save-dev
Após a instalação, ative os hooks no repositório:
npx husky init
Esse comando cria o diretório .husky/ com um hook pre-commit de exemplo. A estrutura gerada será similar a:
.husky/
pre-commit
_
.gitignore
O arquivo pre-commit contém o script que será executado antes de cada commit. Edite-o para incluir a verificação desejada:
npx lint-staged
Para garantir que o Husky funcione corretamente em ambientes CI, adicione o script de preparação no package.json:
"scripts": {
"prepare": "husky"
}
3. Integração do lint-staged para Verificações Seletivas
O lint-staged permite executar linters apenas nos arquivos que estão na área de staging (preparados para commit). Isso evita verificar todo o código-fonte a cada commit, tornando o processo rápido e escalável.
Instale o pacote:
npm install lint-staged --save-dev
Configure as regras no package.json:
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{css,scss}": ["stylelint --fix", "prettier --write"],
"*.{json,md}": ["prettier --write"]
}
Nesta configuração:
- Arquivos JavaScript/TypeScript passam por ESLint com correção automática e depois por Prettier.
- Arquivos CSS/SCSS são verificados pelo Stylelint e formatados pelo Prettier.
- Arquivos JSON e Markdown são apenas formatados pelo Prettier.
Cada entrada define um padrão de arquivo (glob) e uma lista de comandos a executar. Se algum comando falhar, o commit é interrompido.
4. Exemplos Práticos de Regras com lint-staged
Linting de JavaScript/TypeScript com correção automática
"lint-staged": {
"*.{js,jsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
],
"*.{ts,tsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
]
}
A flag --max-warnings=0 faz o ESLint falhar se houver qualquer aviso, não apenas erros.
Validação de CSS com Stylelint
"lint-staged": {
"*.css": [
"stylelint --fix",
"prettier --write"
]
}
Execução de testes nos arquivos modificados
Para projetos com testes unitários, é possível rodar apenas os testes relacionados aos arquivos alterados:
"lint-staged": {
"*.{js,ts}": [
"eslint --fix",
"jest --findRelatedTests --passWithNoTests"
]
}
O parâmetro --findRelatedTests do Jest identifica automaticamente os arquivos de teste associados aos arquivos modificados.
5. Personalização de Hooks Além do pre-commit
Hook commit-msg para validar mensagens de commit
Crie o arquivo .husky/commit-msg:
npx --no -- commitlint --edit $1
Instale o commitlint para validar conventional commits:
npm install @commitlint/cli @commitlint/config-conventional --save-dev
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
Isso força mensagens no formato tipo(escopo): descrição, como feat(auth): adiciona login social.
Hook pre-push para testes completos
Crie o arquivo .husky/pre-push:
npm test
Esse hook executa a suíte completa de testes antes de enviar commits ao repositório remoto.
Combinação de hooks customizados
É possível criar hooks adicionais, como post-commit para notificações ou post-merge para instalar dependências:
.husky/post-merge
npm install
6. Resolução de Problemas Comuns e Boas Práticas
Tratamento de falhas no hook
Se um hook falha, o commit é interrompido e o Git exibe a saída do erro. Para depurar, execute o hook manualmente:
npx lint-staged --verbose
Como ignorar hooks temporariamente
Em situações de emergência, é possível pular os hooks com a flag --no-verify:
git commit -m "hotfix: corrige crash" --no-verify
Use com moderação — o ideal é que hooks nunca sejam ignorados.
Versionamento da configuração
Mantenha o diretório .husky/ e as configurações do lint-staged no package.json versionados no repositório. Isso garante que todos os membros da equipe usem as mesmas regras. Adicione apenas o arquivo .husky/_/husky.sh ao .gitignore, pois ele é gerado automaticamente.
7. Comparação com Alternativas e Considerações Finais
O Husky é a ferramenta mais popular para gerenciamento de Git hooks em projetos Node.js, mas existem alternativas:
- Lefthook: Escrito em Go, é mais rápido que o Husky e oferece paralelismo nativo. Ideal para projetos grandes.
- pre-commit (Python): Framework focado em Python, mas suporta múltiplas linguagens. Exige um arquivo
.pre-commit-config.yaml.
O lint-staged tem limitações em projetos monolíticos com milhares de arquivos — a varredura de globs pode se tornar lenta. Nesses casos, considere usar ferramentas como nx ou turborepo que oferecem cache e execução seletiva.
Para adoção gradual em equipes existentes, comece apenas com formatação (Prettier) e depois adicione linters. Comunique as mudanças e ofereça um período de adaptação. A automação de qualidade antes do commit não é apenas uma prática técnica — é um compromisso com a sustentabilidade do código.
Referências
- Documentação oficial do Husky — Guia completo de instalação, configuração e hooks disponíveis.
- Repositório do lint-staged no GitHub — Código-fonte, exemplos de configuração e soluções para problemas comuns.
- Documentação do ESLint — Regras de linting, integração com Git hooks e opções de correção automática.
- Conventional Commits — Especificação para mensagens de commit padronizadas, usada com commitlint.
- Artigo: Automatizando qualidade com Husky e lint-staged — Tutorial prático com exemplos reais de configuração em projetos React e Node.js.