Free

Gérer les workflows git avec les Hooks : que Claude aussi respecte les règles

Utilisez les PreToolUse Hooks pour intercepter les commandes git dans Bash et bloquer les commits directs vers main, les mauvais formats et les opérations dangereuses.


Claude Code a la permission d'exécuter git commit, git push et git checkout directement. C'est pratique, mais cela peut conduire à des commits sur main, des messages en format libre, ou des force push intempestifs. Les Hooks interceptent ces opérations avant qu'elles ne se produisent.


Règle 1 : Bloquer les commits directs sur 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 "Les commits directs sur $current_branch sont interdits. Changez de branche feature d'abord." >&2; exit 2
fi

Règle 2 : Imposer le format des messages 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 "Format du message de commit incorrect. Format : <type>(<scope>): <description>" >&2; exit 2
fi

Règle 3 : Bloquer les opérations dangereuses

#!/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 "Opération dangereuse bloquée. Ajoutez # ALLOW: <raison> pour continuer." >&2; exit 2
  fi
fi

Configuration complète

.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 "Sur $current_branch — commits et pushes directs bloqués. Changez de branche." >&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 "Format incorrect. Format : <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 "Opération dangereuse bloquée. Ajoutez # ALLOW: <raison>." >&2; exit 2
  fi
fi

Résumé

PreToolUse + matcher Bash + détection des commandes git. Trois règles prioritaires : bloquer les commits sur main, valider le format des messages, intercepter force push et reset --hard.