Free

Gerenciando fluxos de trabalho git com Hooks: fazendo o Claude seguir as regras também

Use PreToolUse Hooks para interceptar comandos git no Bash e bloquear commits diretos ao main, formatos incorretos e operações perigosas.


Claude Code tem permissão para executar git commit, git push e git checkout diretamente. Na maioria das vezes é conveniente, mas também significa que ele pode fazer commits no main, escrever mensagens em formato livre ou fazer force push quando não deveria. Os Hooks interceptam essas operações antes que aconteçam.


Abordagem: PreToolUse para interceptar comandos git no Bash

Todas as operações git no Claude Code passam pela ferramenta Bash. O ponto de interceptação é "matcher": "Bash" no PreToolUse.


Regra 1: Bloquear commits diretos no main

#!/bin/bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')

echo "$cmd" | grep -qE '^git (commit|push)' || exit 0
current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)

if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
  echo "Commits diretos em $current_branch não são permitidos. Mude para uma branch feature primeiro." >&2
  exit 2
fi

Regra 2: Forçar formato da mensagem de commit

#!/bin/bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')

echo "$cmd" | grep -qE '^git commit' || exit 0
msg=$(echo "$cmd" | grep -oP '(?<=-m )["\x27].*?["\x27]' | tr -d '"'"'" || true)
[[ -z "$msg" ]] && exit 0

if ! echo "$msg" | grep -qE '^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{3,}'; then
  echo "Formato da mensagem de commit incorreto." >&2
  echo "Formato: <type>(<scope>): <description>" >&2
  echo "Exemplo: feat(auth): add OAuth login" >&2
  exit 2
fi

Regra 3: Bloquear operações perigosas

#!/bin/bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')

if echo "$cmd" | grep -qE 'git push.*--force|git reset --hard|git push.*--delete'; then
  if ! echo "$cmd" | grep -q '# ALLOW:'; then
    echo "Operação perigosa bloqueada. Adicione # ALLOW: <motivo> ao final do comando para prosseguir." >&2
    exit 2
  fi
fi

Configuração completa

.claude/hooks/git-guard.sh:

#!/bin/bash
set -e
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // empty')

[[ -z "$cmd" ]] && exit 0
echo "$cmd" | grep -q '^git' || exit 0

current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")

if echo "$cmd" | grep -qE '^git (commit|push)'; then
  if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
    echo "Atualmente em $current_branch — commits e pushes diretos bloqueados. Mude para uma branch feature." >&2
    exit 2
  fi
fi

if echo "$cmd" | grep -qE '^git commit.*-m'; then
  msg=$(echo "$cmd" | grep -oP '(?<=-m )["\x27][^\x27"]*["\x27]' | tr -d '"'"'" || true)
  if [[ -n "$msg" ]] && ! echo "$msg" | grep -qE '^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{3,}'; then
    echo "Formato de mensagem incorreto. Formato: <type>(<scope>): <description>" >&2
    exit 2
  fi
fi

if echo "$cmd" | grep -qE 'git push.*--force|git reset --hard|git push.*--delete'; then
  if ! echo "$cmd" | grep -q '# ALLOW:'; then
    echo "Operação perigosa bloqueada. Adicione # ALLOW: <motivo> para continuar." >&2
    exit 2
  fi
fi

Resumo

Gerenciar fluxos de trabalho git com Hooks se resume a: PreToolUse + matcher Bash + detecção de comandos git. Três regras prioritárias: bloquear commits no main, validar formato das mensagens, interceptar force push e reset --hard.