Free

Hooks로 git 워크플로 관리하기: Claude의 커밋도 규칙을 따르게

PreToolUse Hook으로 Bash의 git 명령을 가로채 main 직접 커밋, commit message 형식 위반, 위험한 작업을 차단한다.


Claude Code는 git commit, git push, git checkout을 직접 실행할 권한이 있습니다. 대부분 편리하지만, 다음과 같은 문제가 생길 수 있습니다:

  • main 브랜치에 직접 커밋
  • 형식이 제멋대로인 커밋 메시지
  • co-author 서명 누락
  • 부적절한 시점의 force push

Hooks는 이런 작업이 실행되기 전에 개입할 수 있습니다 — 가로채기, 검증, 규약 강제, 또는 위험한 작업 차단.


접근 방식: PreToolUse로 Bash의 git 명령 가로채기

Claude Code의 모든 git 작업은 Bash 도구를 통해 실행됩니다. 가로채기 지점은 여기입니다:

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [...] }
    ]
  }
}

규칙 1: 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 "$current_branch 브랜치에 직접 커밋하는 것은 금지입니다. feature 브랜치로 전환하세요." >&2
  exit 2
fi

규칙 2: 커밋 메시지 형식 강제

#!/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 "커밋 메시지 형식이 올바르지 않습니다." >&2
  echo "형식: <type>(<scope>): <description>" >&2
  echo "예시: feat(auth): add OAuth login" >&2
  exit 2
fi

규칙 3: 위험한 git 작업 차단

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

if echo "$cmd" | grep -qE 'git push.*--force(-with-lease)?.*\b(main|master)\b'; then
  echo "main/master에 force push는 금지입니다." >&2; exit 2
fi

if echo "$cmd" | grep -qE 'git reset --hard'; then
  if ! echo "$cmd" | grep -q '# ALLOW:'; then
    echo "git reset --hard는 위험한 작업입니다. # ALLOW: <이유>를 추가하세요." >&2; exit 2
  fi
fi

완전한 통합 설정

.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 "현재 $current_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 "커밋 메시지 형식이 올바르지 않습니다." >&2
    echo "형식: <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 "위험한 작업이 차단됨: $cmd" >&2
    echo "실행하려면 # ALLOW: <이유>를 명령 끝에 추가하세요." >&2
    exit 2
  fi
fi

요약

Hooks로 git 워크플로우를 관리하는 핵심: PreToolUse + Bash matcher + git 명령 감지.

우선 설정할 3가지 규칙:
1. main 브랜치 직접 커밋 차단
2. 커밋 메시지 형식 검증
3. force push, reset --hard 등 위험한 작업 차단

감사 로그와 함께 사용하면 Claude의 모든 git 작업을 추적할 수 있습니다.