Pre-commit hooks com Husky
1. Introdução aos Pre-commit Hooks e ao Husky
Hooks do Git são scripts que o Git executa automaticamente em momentos específicos do ciclo de vida de um repositório. O hook pre-commit é disparado imediatamente antes de um commit ser criado, permitindo que você valide ou modifique o conteúdo que será commitado.
Problemas comuns que hooks resolvem incluem:
- Commits com erros de lint não detectados
- Código com formatação inconsistente
- Testes quebrados sendo commitados acidentalmente
- Mensagens de commit mal formatadas
O Husky é uma ferramenta que simplifica drasticamente o gerenciamento de hooks Git. Em vez de editar manualmente a pasta .git/hooks/ (que não é versionada), o Husky cria uma pasta .husky/ versionável e fornece uma interface amigável para criar e gerenciar hooks.
2. Instalação e Configuração Inicial do Husky
A instalação pode ser feita via npm, yarn ou pnpm. O método mais rápido é usando o comando de inicialização:
npx husky-init && npm install
Para yarn:
npx husky-init && yarn
Para pnpm:
pnpm exec husky-init && pnpm install
Esse comando cria a estrutura de pastas necessária:
.husky/
pre-commit
_
.gitignore
O arquivo pre-commit inicial contém:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm test
Após a instalação, é necessário habilitar os hooks no repositório. O Husky já configura isso automaticamente no package.json:
{
"scripts": {
"prepare": "husky install"
}
}
O script prepare garante que husky install seja executado sempre que alguém rodar npm install no projeto.
3. Criando seu Primeiro Hook pre-commit
Vamos criar um hook que executa o linter antes de cada commit. Primeiro, adicione o script de lint no package.json:
{
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"prepare": "husky install"
}
}
Agora, modifique o arquivo .husky/pre-commit:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
Para testar o hook, tente fazer um commit com código que viole as regras do ESLint:
git add .
git commit -m "teste: hook deve impedir commit com erro de lint"
Se o lint falhar, o commit será abortado e você verá os erros no terminal. Para verificar se o hook está ativo, use:
git config core.hooksPath
A saída deve mostrar .husky (ou o caminho configurado).
4. Ferramentas Populares para Usar com Husky
lint-staged
O lint-staged permite rodar linters apenas nos arquivos que estão staged, economizando tempo em projetos grandes. Instale:
npm install --save-dev lint-staged
Configure no package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{css,scss}": ["stylelint --fix", "prettier --write"],
"*.{json,md}": ["prettier --write"]
}
}
Atualize o hook pre-commit:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
Prettier
O Prettier formata automaticamente o código. Combinado com lint-staged, ele corrige a formatação dos arquivos staged antes do commit.
ESLint / Stylelint
ESLint para JavaScript/TypeScript e Stylelint para CSS podem ser configurados juntos no lint-staged, como no exemplo acima.
5. Boas Práticas na Escrita de Hooks
Mantenha hooks rápidos: hooks demorados frustram a equipe. Evite rodar a suíte completa de testes no pre-commit; deixe isso para o CI.
Tratamento de erros: sempre forneça mensagens claras sobre o que falhou:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo "🔍 Rodando validações pré-commit..."
npx lint-staged
if [ $? -ne 0 ]; then
echo "❌ Validações falharam. Corrija os erros antes de commitar."
exit 1
fi
echo "✅ Validações passaram!"
Controle de saída: use exit 0 para permitir o commit e exit 1 para abortá-lo.
Ignorar hooks temporariamente: use git commit --no-verify em situações excepcionais (commits de emergência, por exemplo).
6. Personalização e Hooks Adicionais
Além do pre-commit, o Husky permite criar hooks para outros eventos:
Hook commit-msg com commitlint
Instale o commitlint:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
Crie o arquivo .husky/commit-msg:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no -- commitlint --edit $1
Crie o arquivo de configuração commitlint.config.js:
module.exports = {
extends: ['@commitlint/config-conventional']
};
Hook pre-push
Para rodar testes antes de enviar para o repositório remoto:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run test
Usando variáveis de ambiente
Você pode acessar variáveis do Git nos hooks. Por exemplo, no commit-msg, $1 contém o caminho do arquivo de mensagem de commit.
7. Integração com Workflows em Equipe
Versionando a pasta .husky/: adicione .husky/ ao repositório. Isso garante que todos tenham os mesmos hooks.
Script postinstall: configure no package.json:
{
"scripts": {
"postinstall": "husky install",
"prepare": "husky install"
}
}
O postinstall garante que hooks sejam instalados mesmo se o prepare falhar.
Resolução de conflitos: em diferentes sistemas operacionais, problemas comuns incluem:
- Permissões de execução (no Windows, use git config core.hooksPath .husky)
- Caminhos de shell (use sh em vez de bash para compatibilidade)
8. Resolução de Problemas e Debug
Hooks não executando: verifique as permissões do arquivo:
chmod +x .husky/pre-commit
Verificar instalação do Git: confirme que o Git está configurado corretamente:
git config core.hooksPath
Modo debug do Husky:
npx husky --debug
Logs de erro: verifique a saída do terminal ao executar um commit. O Husky exibe erros diretamente lá.
Comando útil para diagnóstico:
git config --list | grep hooks
Se precisar resetar a configuração de hooks:
git config --unset core.hooksPath
Referências
- Documentação oficial do Husky — Guia completo de instalação, configuração e todos os hooks suportados
- lint-staged - Run linters on git staged files — Repositório oficial com exemplos de configuração e integração com Husky
- Documentação oficial do Git Hooks — Referência completa sobre todos os hooks nativos do Git e seus comportamentos
- commitlint - Lint commit messages — Guia de instalação e configuração do commitlint para validação de mensagens de commit
- Prettier - Opinionated Code Formatter — Tutorial oficial de como integrar Prettier com hooks pré-commit usando Husky e lint-staged
- ESLint - Integrating with Husky — Documentação do ESLint sobre como configurar validação automática via Husky