本文目录导读:

Git 钩子脚本(特别是 pre-commit 和 commit-msg 钩子)非常适合用于自动化变更管理检查,以下是几种常见的检查策略及对应的钩子脚本实现示例。
变更范围与文件类型检查
禁止提交特定文件类型
#!/bin/bash
# .git/hooks/pre-commit
# 禁止提交 .log、.tmp 文件
for file in $(git diff --cached --name-only); do
if [[ "$file" =~ \.(log|tmp|bak|swp)$ ]]; then
echo "错误:禁止提交临时文件:$file"
exit 1
fi
done
检查文件大小限制
#!/bin/bash
# .git/hooks/pre-commit
MAX_SIZE=$((10 * 1024 * 1024)) # 10MB
git diff --cached --name-only -z | xargs -0 stat --format='%s %n' | while read size file; do
if [ "$size" -gt "$MAX_SIZE" ]; then
echo "错误:文件过大 (>10MB):$file"
exit 1
fi
done
代码质量与规范检查
ESLint 检查(JavaScript/TypeScript)
#!/bin/bash
# .git/hooks/pre-commit
# 获取暂存区中修改的 JS/TS 文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|tsx|jsx)$')
if [ -n "$STAGED_FILES" ]; then
echo "运行 ESLint 检查..."
npx eslint $STAGED_FILES
if [ $? -ne 0 ]; then
echo "ESLint 检查失败,请修正后重新提交"
exit 1
fi
fi
Python 代码规范检查
#!/bin/bash
# .git/hooks/pre-commit
STAGED_PY=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')
if [ -n "$STAGED_PY" ]; then
echo "运行 Flake8 检查..."
flake8 $STAGED_PY
if [ $? -ne 0 ]; then
echo "Python 代码规范检查失败"
exit 1
fi
fi
提交信息规范检查
提交信息格式验证
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# 检查提交信息格式: [类型]: 描述
# 类型: feat|fix|docs|style|refactor|test|chore
if ! echo "$COMMIT_MSG" | grep -qE '^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}$'; then
echo "错误:提交信息格式不正确"
echo "正确格式: [类型]: 描述"
echo "示例: feat: 添加用户登录功能"
echo "类型: feat|fix|docs|style|refactor|test|chore"
exit 1
fi
变更日志检查
检查变更文件是否更新了 CHANGELOG
#!/bin/bash
# .git/hooks/pre-commit
# 检查是否有除 CHANGELOG 外的文件被修改
STAGED_FILES=$(git diff --cached --name-only)
HAS_CHANGES=$(echo "$STAGED_FILES" | grep -v "CHANGELOG.md" | wc -l)
HAS_CHANGELOG=$(echo "$STAGED_FILES" | grep "CHANGELOG.md" | wc -l)
if [ "$HAS_CHANGES" -gt 0 ] && [ "$HAS_CHANGELOG" -eq 0 ]; then
echo "警告:您修改了代码但未更新 CHANGELOG.md"
echo "是否继续提交?(y/n)"
read -r response
if [ "$response" != "y" ]; then
exit 1
fi
fi
分支命名规范检查
#!/bin/bash
# .git/hooks/pre-commit
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
# 允许的分支命名模式
# feature/xxx, bugfix/xxx, hotfix/xxx, release/xxx
if [[ "$BRANCH_NAME" =~ ^(feature|bugfix|hotfix|release)/[a-z0-9_-]+$ ]]; then
# 根据分支类型添加额外的检查
case "$BRANCH_NAME" in
feature/*)
# 功能分支检查
;;
bugfix/*)
# 修复分支检查:确保有关联的 Issue 编号
if [[ ! "$BRANCH_NAME" =~ -[0-9]+$ ]]; then
echo "错误:bugfix 分支应包含 Issue 编号"
echo "示例: bugfix/fix-login-123"
exit 1
fi
;;
esac
else
echo "警告:当前分支名称 '$BRANCH_NAME' 不符合命名规范"
echo "推荐格式: feature/xxx, bugfix/xxx, hotfix/xxx"
fi
综合示例:完整变更管理检查脚本
#!/bin/bash
# .git/hooks/pre-commit
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
ERRORS=0
WARNINGS=0
echo "=== 变更管理检查开始 ==="
# 1. 获取所有变更文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
echo "变更文件数量: $(echo "$STAGED_FILES" | wc -l)"
# 2. 检查禁止提交的文件类型
echo -e "\n[检查1] 文件类型检查..."
for file in $STAGED_FILES; do
if [[ "$file" =~ \.(log|tmp|bak|swp|DS_Store)$ ]]; then
echo -e "${RED}错误:禁止提交临时文件:$file${NC}"
((ERRORS++))
fi
done
# 3. 检查文件大小
echo -e "\n[检查2] 文件大小检查..."
MAX_SIZE=$((5 * 1024 * 1024))
while IFS= read -r file; do
if [ -f "$file" ]; then
size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
if [ "$size" -gt "$MAX_SIZE" ]; then
echo -e "${RED}错误:文件过大 (>5MB):$file (大小: $((size/1024/1024))MB)${NC}"
((ERRORS++))
fi
fi
done <<< "$STAGED_FILES"
# 4. 检查敏感信息
echo -e "\n[检查3] 敏感信息检查..."
for file in $STAGED_FILES; do
if [ -f "$file" ] && [[ ! "$file" =~ \.(png|jpg|jpeg|gif|ico)$ ]]; then
# 检查常见的敏感信息模式
if grep -qP '(password|api_key|secret|token|credential|private_key)' "$file" 2>/dev/null; then
echo -e "${YELLOW}警告:文件可能包含敏感信息:$file${NC}"
((WARNINGS++))
fi
fi
done
# 5. 检查是否有 TODO/FIXME 注释
echo -e "\n[检查4] TODO/FIXME 检查..."
for file in $STAGED_FILES; do
if [ -f "$file" ] && [[ "$file" =~ \.(py|js|ts|java|go|rb|php)$ ]]; then
if grep -qP '(TODO|FIXME|HACK|XXX)' "$file" 2>/dev/null; then
echo -e "${YELLOW}警告:文件包含 TODO/FIXME 标记:$file${NC}"
((WARNINGS++))
fi
fi
done
# 6. 检查分支命名
echo -e "\n[检查5] 分支命名检查..."
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
if [[ "$BRANCH_NAME" == "main" || "$BRANCH_NAME" == "master" ]]; then
echo -e "${RED}错误:禁止直接在主分支上提交${NC}"
((ERRORS++))
fi
# 汇总结果
echo -e "\n=== 检查完成 ==="
echo -e "${RED}错误: $ERRORS${NC}"
echo -e "${YELLOW}警告: $WARNINGS${NC}"
if [ $ERRORS -gt 0 ]; then
echo -e "${RED}由于存在错误,提交被终止${NC}"
exit 1
fi
echo -e "${GREEN}所有检查通过,允许提交${NC}"
exit 0
钩子脚本部署建议
-
赋予执行权限:
chmod +x .git/hooks/pre-commit chmod +x .git/hooks/commit-msg
-
团队共享配置:将钩子脚本放在项目仓库中
mkdir -p .githooks cp .git/hooks/* .githooks/
-
全局配置:设置全局钩子路径
git config --global core.hooksPath /path/to/global/hooks
-
使用 Husky(Node.js 项目):
// package.json { "husky": { "hooks": { "pre-commit": "npm run test && npm run lint", "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } } }
最佳实践建议
-
渐进式执行:先以警告形式运行,待团队适应后再改为强制检查
-
提供跳过机制:
git commit --no-verify # 跳过钩子检查
-
性能优化:避免在钩子中执行耗时操作(如完整测试套件)
-
错误信息清晰:提供明确的错误信息和修复建议
-
版本控制:将钩子脚本纳入版本管理,确保团队一致
通过合理配置 Git 钩子,可以有效实施变更管理策略,提高代码质量和团队协作效率。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播