Free

Quản lý quy trình git với Hooks: bắt Claude cũng phải tuân thủ quy tắc

Dùng PreToolUse Hooks để chặn các lệnh git trong Bash — ngăn commit thẳng vào main, sai định dạng commit message và các thao tác nguy hiểm.


Claude Code có quyền chạy git commit, git push, git checkout trực tiếp. Điều này tiện lợi nhưng cũng có thể dẫn đến commit thẳng vào main, viết message tùy tiện, hoặc force push không đúng lúc. Hooks chặn các thao tác này trước khi chúng xảy ra.


Cách tiếp cận: PreToolUse để chặn lệnh git trong Bash

Tất cả thao tác git trong Claude Code đều chạy qua tool Bash. Điểm chặn là "matcher": "Bash" trong PreToolUse.


Quy tắc 1: Chặn commit trực tiếp vào 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 "Không được commit trực tiếp vào $current_branch. Hãy chuyển sang branch feature trước." >&2
  exit 2
fi

Quy tắc 2: Bắt buộc định dạng commit message

#!/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 "Định dạng commit message không đúng." >&2
  echo "Định dạng: <type>(<scope>): <description>" >&2
  exit 2
fi

Quy tắc 3: Chặn thao tác nguy hiểm

#!/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 "Thao tác nguy hiểm đã bị chặn. Thêm # ALLOW: <lý do> vào cuối lệnh để tiếp tục." >&2
    exit 2
  fi
fi

Cấu hình đầy đủ

.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 "Đang ở nhánh $current_branch — commit và push trực tiếp bị chặn. Chuyển sang feature branch." >&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 "Định dạng message sai. Định dạng: <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 "Thao tác nguy hiểm bị chặn. Thêm # ALLOW: <lý do> để tiếp tục." >&2
    exit 2
  fi
fi

Tóm tắt

Quản lý git với Hooks: PreToolUse + Bash matcher + phát hiện lệnh git. Ba quy tắc ưu tiên: chặn commit vào main, kiểm tra định dạng message, chặn force push và reset --hard.