Gerador de Git post-merge hook
Gera um script post-merge para reinstalar deps quando package-lock muda, atualizar submodules e mostrar comandos novos.
Hooks Git post-merge: automatize o tedioso após todo pull
O hook post-merge dispara localmente, na máquina do desenvolvedor, logo depois de um git merge bem-sucedido — inclusive o merge implícito feito por git pull. Diferente de hooks pre-*, ele não bloqueia nada; o merge já aconteceu. Seu propósito é puramente reativo: reagir ao novo estado da working tree e rodar as tarefas que um humano esqueceria. Recebe um único argumento, $1, que vale 1 se o merge foi squash e 0 caso contrário. A entrada padrão fica vazia.
O caso clássico é a deriva de dependências. Você dá pull, um colega adicionou um pacote, e na próxima vez que sobe a app ela quebra com Cannot find module 'lodash'. Um hook post-merge de duas linhas detecta a mudança e roda o instalador automaticamente.
Esqueleto do script
#!/bin/bash
# .git/hooks/post-merge (chmod +x)
changed_files=$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)
run_if_changed() {
echo "$changed_files" | grep --quiet "$1" && eval "$2"
}
run_if_changed "package-lock.json" "npm ci"
run_if_changed "pnpm-lock.yaml" "pnpm install --frozen-lockfile"
run_if_changed "prisma/schema.prisma" "npx prisma generate"
run_if_changed ".env.example" "echo '.env.example mudou — revise seu .env'"
run_if_changed "docker-compose.yml" "docker compose up -d"
Padrões comuns
- Instalar dependências quando lockfiles mudam (
package-lock.json,pnpm-lock.yaml,yarn.lock,Pipfile.lock,poetry.lock,Gemfile.lock,go.sum,Cargo.lock). - Regenerar clients quando um spec OpenAPI, schema Prisma, schema GraphQL ou arquivo protobuf muda.
- Aplicar migrations automaticamente no banco de dev quando um arquivo novo cai em
migrations/. - Reiniciar serviços de dev (Docker Compose, Tilt, Skaffold) quando seus arquivos de config mudam.
- Alertar sobre drift no
.env.examplepara uma variável faltando aparecer já — e não três horas de debug depois. - Atualizar submodules com
git submodule update --init --recursive.
Detectando o que mudou
Dentro do hook, duas refs são úteis: ORIG_HEAD (onde você estava antes do merge) e HEAD (onde está agora). O idiomatismo padrão é:
git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD
diff-tree é mais rápido que git diff porque ignora a working tree. A flag -r entra em subdiretórios; --name-only reduz a saída para caminhos puros; --no-commit-id evita imprimir os headers de commit antes de cada diff. Encaminhe o resultado para grep ou, por performance, leia para um array bash e cruze localmente sem fork.
Gerenciadores de hook: husky, lefthook, simple-git-hooks, pre-commit
Como o diretório .git/hooks/ não é commitado, todo time eventualmente adota um gerenciador que distribui hooks por arquivos dentro do repo. O Husky (Node, do Typicode) é o líder de mercado em projetos JavaScript; armazena hooks em .husky/ e reconfigura core.hooksPath no npm install. O Lefthook (Go, da Evil Martians) é o mais rápido — um único binário, config YAML, execução paralela de comandos e agnóstico de linguagem. O simple-git-hooks (Anton Krasanov) é zero-dependência e lê os comandos do package.json. O pre-commit (Python) domina repos Python e poliglotas graças a um registry imenso de hooks reutilizáveis.
Seja qual for a escolha, documente no README: os devs precisam rodar o comando de bootstrap do gerenciador uma vez (npx husky install, lefthook install) antes dos hooks ficarem ativos.
FAQ
O post-merge roda depois de git pull? Sim — pull é um fetch seguido de merge, e o passo de merge dispara o post-merge. Se você der pull com --rebase, o hook não dispara; use post-rewrite nesse caso.
O hook pode falhar sem quebrar o merge? O merge já terminou quando o hook roda, então qualquer exit code é apenas informativo. Imprima erros em vermelho gritante para o dev notar.
Husky ou Lefthook? Lefthook se performance de startup importar (binário Go vs startup Node), Husky se o time já estiver imerso no ecossistema Node e você quiser zero ferramenta extra.
O post-merge roda em fast-forward? Sim — o Git ainda registra um evento de merge mesmo sem criar commit de merge.
Vai deixar todo pull lento? Só se você deixar. Envolva comandos pesados em if que dispara apenas quando arquivos relevantes mudaram de fato, e evite chamadas de rede síncronas.
Ferramentas Relacionadas
Gerador de Git pre-receive hook
Gera um script bash pre-receive para Git server-side com validações de branch, autor e tamanho de commit.
Gerador de comando git rebase
Monte comandos git rebase com branch base, --interactive, --onto, --autosquash e --no-verify, prontos para colar.
Gerador de Conventional Commit
Monta uma mensagem de commit no formato Conventional Commits (feat:, fix:, chore:) com escopo opcional, breaking change e issue.