本文目录导读:

Git 钩子脚本可以通过多种方式检查防抵赖策略,主要利用 Git 的签名验证机制和提交信息审计,以下是具体的实现方法:
强制 GPG 签名验证
pre-commit 钩子 - 检查用户 GPG 密钥配置
#!/bin/bash
# .git/hooks/pre-commit
# 检查是否配置了 GPG 签名
if ! git config --get user.signingkey > /dev/null 2>&1; then
echo "错误: 未配置 GPG 签名密钥"
echo "请使用: git config --global user.signingkey <KEY_ID>"
exit 1
fi
# 检查是否启用了提交签名
if [ "$(git config --get commit.gpgsign)" != "true" ]; then
echo "错误: 未启用提交签名"
echo "请使用: git config --global commit.gpgsign true"
exit 1
fi
echo "GPG 签名配置检查通过"
exit 0
commit-msg 钩子 - 验证提交签名
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
# 检查是否是 git commit 操作 (非 merge, rebase 等)
if [ -z "$COMMIT_SOURCE" ] || [ "$COMMIT_SOURCE" = "message" ]; then
# 获取提交的哈希值
if git rev-parse HEAD > /dev/null 2>&1; then
# 检查当前最新提交是否已签名
if ! git verify-commit HEAD 2>/dev/null; then
echo "警告: 提交应该使用 GPG 签名"
echo "请使用: git commit -S -m 'your message'"
exit 1
fi
echo "签名验证通过"
fi
fi
exit 0
提交信息完整性检查
pre-commit 钩子 - 检查作者信息
#!/bin/bash
# .git/hooks/pre-commit
# 检查作者信息
AUTHOR_NAME=$(git config --get user.name)
AUTHOR_EMAIL=$(git config --get user.email)
if [ -z "$AUTHOR_NAME" ] || [ -z "$AUTHOR_EMAIL" ]; then
echo "错误: 作者信息不完整"
echo "请配置: git config user.name 'Your Name'"
echo "请配置: git config user.email 'your.email@example.com'"
exit 1
fi
# 检查是与公司域名的邮箱
if [[ ! "$AUTHOR_EMAIL" =~ @company\.com$ ]]; then
echo "警告: 请使用公司邮箱提交"
echo "当前邮箱: $AUTHOR_EMAIL"
exit 1
fi
echo "作者信息检查通过"
exit 0
commit-msg 钩子 - 签名验证增强版
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
# 1. 检查提交信息格式
if ! head -1 "$COMMIT_MSG_FILE" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|perf|ci|build)(\(.+\))?: .{1,50}$"; then
echo "错误: 提交信息格式不正确"
echo "格式: <type>(<scope>): <subject>"
echo "示例: feat(login): 添加登录功能"
exit 1
fi
# 2. 强制使用 -S 选项签名
if [ -z "$(git config --get commit.gpgsign)" ]; then
echo "错误: 必须使用签名提交"
echo "请使用: git commit -S"
exit 1
fi
# 3. 检查提交信息长度
BODY=$(tail -n +3 "$COMMIT_MSG_FILE")
if [ ${#BODY} -gt 1000 ]; then
echo "错误: 提交信息正文过长 (最大1000字符)"
exit 1
fi
echo "提交信息完整性检查通过"
exit 0
服务端钩子 - 加强防抵赖
pre-receive 钩子 - 服务端签名验证
#!/bin/bash
# hooks/pre-receive (服务端)
# 读取推送的引用
while read oldrev newrev refname; do
# 跳过删除分支的操作
if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then
continue
fi
# 遍历所有新提交
for commit in $(git rev-list "$oldrev..$newrev" 2>/dev/null); do
# 检查提交是否已签名
if ! git verify-commit "$commit" 2>/dev/null; then
echo "拒绝推送: 提交 $commit 没有有效的 GPG 签名"
echo "请使用: git commit -S -m 'your message'"
exit 1
fi
# 获取提交者信息
COMMITTER=$(git log -1 --format='%cn <%ce>' "$commit")
AUTHOR=$(git log -1 --format='%an <%ae>' "$commit")
# 检查签名者与提交者是否一致
SIGNER=$(git verify-commit "$commit" 2>&1 | grep "Good signature from" | sed 's/.*from "//;s/"//')
if [ "$SIGNER" != "$AUTHOR" ]; then
echo "拒绝推送: 签名者与提交者不一致"
echo "签名者: $SIGNER"
echo "提交者: $AUTHOR"
exit 1
fi
done
done
echo "所有提交签名验证通过"
exit 0
完整的防抵赖策略配置
将以下脚本保存为 .git/hooks/pre-commit 并设置执行权限:
#!/bin/bash
# 综合防抵赖检查
echo "=== 防抵赖策略检查开始 ==="
# 1. GPG 签名检查
echo "1. 检查 GPG 配置..."
if ! git config --get user.signingkey > /dev/null 2>&1; then
echo "错误: 未配置 GPG 签名密钥"
exit 1
fi
if [ "$(git config --get commit.gpgsign)" != "true" ]; then
echo "错误: 未启用提交签名"
exit 1
fi
# 2. 作者信息检查
echo "2. 检查作者信息..."
AUTHOR_NAME=$(git config --get user.name)
AUTHOR_EMAIL=$(git config --get user.email)
if [ -z "$AUTHOR_NAME" ] || [ -z "$AUTHOR_EMAIL" ]; then
echo "错误: 作者信息不完整"
exit 1
fi
if [[ ! "$AUTHOR_EMAIL" =~ @company\.com$ ]]; then
echo "错误: 必须使用公司邮箱"
exit 1
fi
# 3. 提交信息格式检查
echo "3. 检查提交信息格式..."
COMMIT_MSG=$(cat "$1" 2>/dev/null || echo "")
if [ -n "$COMMIT_MSG" ]; then
if ! echo "$COMMIT_MSG" | head -1 | grep -qE "^(feat|fix|docs|style|refactor|test|chore|perf|ci|build)(\(.+\))?: .+"; then
echo "错误: 提交信息格式不正确"
echo "格式: <type>(<scope>): <subject>"
exit 1
fi
fi
echo "=== 防抵赖策略检查通过 ==="
exit 0
配置步骤
- 创建钩子脚本:
# 进入项目目录 cd /path/to/your/repo
创建钩子文件
touch .git/hooks/pre-commit touch .git/hooks/commit-msg
设置执行权限
chmod +x .git/hooks/pre-commit .git/hooks/commit-msg
2. **配置 GPG 签名**:
```bash
# 生成 GPG 密钥
gpg --full-generate-key
# 配置 Git 使用签名
git config --global user.signingkey <your-key-id>
git config --global commit.gpgsign true
- 对于已有项目:
# 在项目根目录创建钩子目录 mkdir -p .git/hooks
复制钩子脚本
cp /path/to/scripts/pre-commit .git/hooks/ cp /path/to/scripts/commit-msg .git/hooks/
设置执行权限
chmod +x .git/hooks/*
如果使用 husky (Node.js 项目)
npx husky install npx husky add .husky/pre-commit "bash .git/hooks/pre-commit"
## 注意事项
1. **钩子不能绕过**:用户可以通过 `--no-verify` 跳过后端钩子,但服务端钩子无法绕过
2. **性能考虑**:在大型仓库中,检查所有提交可能会影响推送速度
3. **错误处理**:确保脚本有完善的错误处理机制
4. **兼容性**:考虑不同操作系统的兼容性 (Windows vs Linux)
通过以上配置,可以有效地实现 Git 提交的防抵赖策略,确保每次提交都有可追溯的签名信息。