1001Ferramentas
🪝Geradores

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.example para 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