我来详细介绍Git钩子脚本如何检查改进计划,这是一个很好的实践,可以在代码提交前自动验证和改进代码质量。

基本检查框架
预提交钩子(pre-commit)
#!/bin/bash
# .git/hooks/pre-commit
echo "🔍 开始改进计划检查..."
# 收集变更文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
if [ -z "$STAGED_FILES" ]; then
echo "✅ 没有需要检查的文件"
exit 0
fi
# 初始化结果变量
ERRORS=0
WARNINGS=0
代码质量检查
语法和风格检查
# 语法检查函数
check_syntax() {
local file=$1
local ext="${file##*.}"
case $ext in
py)
python -m py_compile "$file" 2>/dev/null || {
echo "❌ Python语法错误: $file"
return 1
}
;;
js|jsx)
node -c "$file" 2>/dev/null || {
echo "❌ JavaScript语法错误: $file"
return 1
}
;;
ts|tsx)
npx tsc --noEmit "$file" 2>/dev/null || {
echo "❌ TypeScript语法错误: $file"
return 1
}
;;
sh)
bash -n "$file" 2>/dev/null || {
echo "❌ Shell语法错误: $file"
return 1
}
;;
esac
return 0
}
代码复杂度检查
# 检查函数复杂度
check_complexity() {
local file=$1
local max_lines=100
local max_nesting=3
# 检查文件行数
local lines=$(wc -l < "$file")
if [ $lines -gt $max_lines ]; then
echo "⚠️ 文件过长 ($lines行): $file"
WARNINGS=$((WARNINGS + 1))
fi
# 检查嵌套深度(示例:Python)
if [[ "$file" == *.py ]]; then
local max_depth=$(python3 -c "
import ast
with open('$file') as f:
tree = ast.parse(f.read())
def get_depth(node, current=0):
depths = [current]
for child in ast.iter_child_nodes(node):
if isinstance(child, (ast.If, ast.For, ast.While, ast.FunctionDef)):
depths.extend(get_depth(child, current + 1))
return depths
depths = get_depth(tree)
print(max(depths) if depths else 0)
" 2>/dev/null)
if [ "$max_depth" -gt "$max_nesting" ]; then
echo "⚠️ 嵌套过深 (深度$max_depth): $file"
WARNINGS=$((WARNINGS + 1))
fi
fi
}
安全检查
# 硬编码密码检查
check_secrets() {
local file=$1
# 检查常见的敏感信息模式
patterns=(
"password\s*=\s*['\"][^'\"]+['\"]"
"api_key\s*=\s*['\"][^'\"]+['\"]"
"secret\s*=\s*['\"][^'\"]+['\"]"
"token\s*=\s*['\"][^'\"]+['\"]"
"-----BEGIN (RSA|OPENSSH) PRIVATE KEY-----"
)
for pattern in "${patterns[@]}"; do
if grep -qE "$pattern" "$file" 2>/dev/null; then
echo "❌ 发现可能的敏感信息: $file"
ERRORS=$((ERRORS + 1))
return 1
fi
done
return 0
}
测试覆盖检查
# 检查测试文件
check_test_coverage() {
local file=$1
local filename=$(basename "$file")
local dir=$(dirname "$file")
# 跳过测试文件本身
if [[ "$filename" == test_* ]] || [[ "$filename" == *_test.* ]]; then
return 0
fi
# 查找对应的测试文件
local test_file="${dir}/test_${filename}"
if [[ ! -f "$test_file" ]]; then
test_file="${dir}/tests/test_${filename}"
fi
if [[ ! -f "$test_file" ]]; then
echo "⚠️ 缺少测试文件: $file"
WARNINGS=$((WARNINGS + 1))
fi
}
文档和注释检查
# 检查文档字符串
check_docs() {
local file=$1
if [[ "$file" == *.py ]]; then
python3 -c "
import ast
with open('$file') as f:
content = f.read()
tree = ast.parse(content)
# 检查函数和类的文档
for node in ast.walk(tree):
if isinstance(node, (ast.FunctionDef, ast.ClassDef)):
if not ast.get_docstring(node):
print(f'缺少文档: {node.name} at line {node.lineno}')
" 2>/dev/null | while read -r msg; do
echo "⚠️ $msg (in $file)"
WARNINGS=$((WARNINGS + 1))
done
fi
}
依赖检查
# 检查依赖更新
check_dependencies() {
local file=$1
# Python requirements.txt
if [[ "$file" == "requirements.txt" ]]; then
while IFS= read -r package; do
if [[ "$package" == *">="* ]] || [[ "$package" == *"=="* ]]; then
echo "⚠️ 考虑使用精确版本: $package"
WARNINGS=$((WARNINGS + 1))
fi
done < "$file"
fi
# Node.js package.json
if [[ "$file" == "package.json" ]]; then
if grep -q '"version": "\^' "$file" 2>/dev/null; then
echo "⚠️ 存在^版本依赖,建议锁定版本"
WARNINGS=$((WARNINGS + 1))
fi
fi
}
主检查流程
# 主执行函数
main() {
echo "=== 改进计划检查报告 ==="
echo "检查时间: $(date)"
echo "检查文件数: $(echo "$STAGED_FILES" | wc -l)"
echo ""
for file in $STAGED_FILES; do
echo "--- 检查: $file ---"
# 只检查代码文件
case "$file" in
*.py|*.js|*.ts|*.sh|*.go|*.java|*.rb|*.php)
check_syntax "$file" || ERRORS=$((ERRORS + 1))
check_complexity "$file"
check_secrets "$file" || ERRORS=$((ERRORS + 1))
check_test_coverage "$file"
check_docs "$file"
;;
requirements.txt|package.json|Gemfile)
check_dependencies "$file"
;;
esac
done
# 生成报告
echo ""
echo "=== 检查结果 ==="
echo "❌ 错误: $ERRORS"
echo "⚠️ 警告: $WARNINGS"
echo ""
# 改进建议
if [ $ERRORS -gt 0 ] || [ $WARNINGS -gt 0 ]; then
echo "💡 改进建议:"
[ $ERRORS -gt 0 ] && echo "- 请修复所有错误后再提交"
[ $WARNINGS -gt 0 ] && echo "- 建议处理警告以提升代码质量"
echo "- 考虑使用 'git commit --no-verify' 跳过检查(不推荐)"
else
echo "✅ 代码质量良好,可以提交!"
fi
# 根据错误数量决定是否阻止提交
[ $ERRORS -gt 0 ] && exit 1
exit 0
}
main
进阶功能
集成静态分析工具
# 集成多种检查工具
run_static_analysis() {
local file=$1
case "${file##*.}" in
py)
# Pylint
pylint --rcfile=.pylintrc "$file" 2>/dev/null || true
# Flake8
flake8 --max-line-length=100 "$file" 2>/dev/null || true
;;
js|ts)
# ESLint
npx eslint "$file" 2>/dev/null || true
;;
go)
# Golangci-lint
golangci-lint run "$file" 2>/dev/null || true
;;
esac
}
性能检查
# 检查性能问题
check_performance() {
local file=$1
if [[ "$file" == *.py ]]; then
# 检查常见性能模式
if grep -q "for.*in.*range(len" "$file" 2>/dev/null; then
echo "⚠️ 建议使用enumerate代替range(len()): $file"
fi
if grep -q "^import \*" "$file" 2>/dev/null; then
echo "⚠️ 避免使用通配符导入: $file"
fi
fi
if [[ "$file" == *.js ]]; then
if grep -q "== " "$file" 2>/dev/null; then
echo "ℹ️ 建议使用===代替==: $file"
fi
fi
}
安装和使用
- 安装钩子脚本:
#!/bin/bash # setup-hooks.sh
HOOKS_DIR=".git/hooks" mkdir -p "$HOOKS_DIR"
cat > "$HOOKS_DIR/pre-commit" << 'EOF'
这里是上面的完整pre-commit脚本内容
EOF
chmod +x "$HOOKS_DIR/pre-commit" echo "✅ Git钩子安装完成"
2. **跳过检查**(紧急情况):
```bash
git commit --no-verify -m "紧急修复"
这个检查系统可以根据项目需求进行定制,比如添加特定的业务规则检查、集成更多工具,或者根据团队规范调整警告级别,关键是要在保护代码质量和不影响开发效率之间找到平衡。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播