本文目录导读:

- 使用 pre-commit 钩子检查文件编码和换行符
- 使用 pre-receive 钩子检查 API 兼容性
- 使用 prepare-commit-msg 钩子检查提交信息格式
- 综合互操作性检查脚本(pre-commit)
- 使用 Git 钩子管理工具
- 最佳实践
Git 钩子脚本可以用来在提交或推送之前检查代码的互操作性(Interoperability),确保代码不会破坏跨平台、跨语言或跨系统的兼容性。
以下是几种常见的 Git 钩子脚本实现方式,用于检查互操作性门禁:
使用 pre-commit 钩子检查文件编码和换行符
#!/bin/bash
# .git/hooks/pre-commit
# 检查文件是否包含 Windows 换行符 (CRLF)
errors=0
for file in $(git diff --cached --name-only); do
if [[ -f "$file" ]]; then
# 检查换行符一致性
if file "$file" | grep -q "CRLF"; then
echo "错误: $file 包含 CRLF 换行符,请转换为 LF"
errors=$((errors + 1))
fi
# 检查 UTF-8 BOM
if head -c 3 "$file" | od -c | grep -q "357 273 277"; then
echo "错误: $file 包含 UTF-8 BOM,请移除"
errors=$((errors + 1))
fi
fi
done
if [ $errors -gt 0 ]; then
exit 1
fi
使用 pre-receive 钩子检查 API 兼容性
#!/bin/bash
# .git/hooks/pre-receive (服务端钩子)
while read oldrev newrev refname; do
# 获取变更的文件列表
for file in $(git diff --name-only $oldrev $newrev); do
# 检查 API 版本声明
if [[ "$file" == *.json ]] || [[ "$file" == *.yaml ]]; then
# 检查是否更新了 API 版本号
if grep -q "apiVersion" "$file" 2>/dev/null; then
old_version=$(git show $oldrev:$file 2>/dev/null | grep "apiVersion" | cut -d: -f2)
new_version=$(git show $newrev:$file | grep "apiVersion" | cut -d: -f2)
if [ "$old_version" != "$new_version" ] && [ -z "$new_version" ]; then
echo "错误: $file 缺少 apiVersion 声明"
exit 1
fi
fi
fi
# 检查接口定义文件
if [[ "$file" == *.proto ]] || [[ "$file" == *swagger* ]]; then
# 运行兼容性检查脚本
if ! check_interface_compatibility.sh $oldrev $newrev $file; then
echo "错误: $file 存在不兼容的变更"
exit 1
fi
fi
done
done
使用 prepare-commit-msg 钩子检查提交信息格式
#!/bin/bash
# .git/hooks/prepare-commit-msg
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
# 检查提交信息是否包含互操作性相关信息
if [ -z "$COMMIT_SOURCE" ]; then
# 对于新提交,检查是否包含互操作性影响说明
if grep -qi "interop\|compatibility\|breaking" "$COMMIT_MSG_FILE"; then
# 要求填写详细的互操作性影响说明
echo -e "\n\n## 互操作性影响说明:" >> "$COMMIT_MSG_FILE"
echo "# 请描述本次变更对互操作性的影响:" >> "$COMMIT_MSG_FILE"
echo "# - 是否破坏了向后兼容性? [是/否]" >> "$COMMIT_MSG_FILE"
echo "# - 是否需要更新其他系统? [是/否]" >> "$COMMIT_MSG_FILE"
echo "# - 是否需要升级客户端版本? [是/否]" >> "$COMMIT_MSG_FILE"
fi
fi
综合互操作性检查脚本(pre-commit)
#!/bin/bash
# .git/hooks/pre-commit
ERRORS=0
WARNINGS=0
echo "运行互操作性检查..."
# 获取暂存的文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
for file in $STAGED_FILES; do
if [[ ! -f "$file" ]]; then
continue
fi
case "$file" in
*.java|*.kt|*.scala)
# 检查 Java/Kotlin 代码的包名规范
if grep -q "package.*\.impl\|package.*\.internal" "$file"; then
echo "警告: $file 包含内部实现包,外部系统可能无法直接调用"
WARNINGS=$((WARNINGS + 1))
fi
;;
*.py)
# 检查 Python 代码的类型提示
if grep -q "def " "$file"; then
if ! grep -q "->" "$file"; then
echo "警告: $file 缺少返回类型注解,影响跨语言互操作"
WARNINGS=$((WARNINGS + 1))
fi
fi
;;
*.proto)
# 检查 Protocol Buffers 文件的兼容性
if ! protoc --lint_out=. "$file" 2>/dev/null; then
echo "错误: $file 存在 protobuf 兼容性问题"
ERRORS=$((ERRORS + 1))
fi
;;
*.json|*.yaml)
# 检查配置文件是否符合规范
if grep -q "version\|apiVersion" "$file"; then
current_version=$(grep "version" "$file" | head -1)
if [[ -z "$current_version" ]]; then
echo "错误: $file 缺少版本号"
ERRORS=$((ERRORS + 1))
fi
fi
;;
esac
# 通用检查:文件名编码
if echo "$file" | grep -q '[^\x20-\x7E]'; then
echo "错误: $file 包含非 ASCII 字符,可能导致跨平台问题"
ERRORS=$((ERRORS + 1))
fi
# 检查文件大小
file_size=$(stat -f%z "$file" 2>/dev/null || stat --printf="%s" "$file" 2>/dev/null)
if [ "$file_size" -gt 1048576 ]; then # 1MB
echo "警告: $file 文件过大 (>1MB),可能影响分布式系统同步"
WARNINGS=$((WARNINGS + 1))
fi
done
# 检查是否有改动配置文件但未更新文档
if echo "$STAGED_FILES" | grep -q "config\|settings\|properties"; then
if ! echo "$STAGED_FILES" | grep -qi "readme\|documentation\|docs"; then
echo "警告: 配置文件已变更,但未更新相关文档"
WARNINGS=$((WARNINGS + 1))
fi
fi
# 输出检查结果
echo "互操作性检查完成: $ERRORS 个错误, $WARNINGS 个警告"
if [ $ERRORS -gt 0 ]; then
echo "存在互操作性错误,提交被拒绝"
exit 1
fi
exit 0
使用 Git 钩子管理工具
更推荐使用如 husky (npm) 或 pre-commit (Python) 等工具来管理钩子:
# .pre-commit-config.yaml (Python pre-commit 工具)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-json
- id: check-yaml
- id: end-of-file-fixer
- id: mixed-line-ending
args: ['--fix=lf']
- id: trailing-whitespace
- repo: https://github.com/grpc-ecosystem/protoc-gen-openapiv2
rev: v2.19.0
hooks:
- id: protoc-lint
args: ['--lint_out=.', '--proto_path=protos']
- repo: local
hooks:
- id: api-compatibility-check
name: API 兼容性检查
entry: scripts/check_api_compatibility.sh
language: script
files: '\.(proto|json|yaml|yml)$'
最佳实践
- 分阶段检查:pre-commit 检查基本格式,pre-receive 检查更严格的兼容性
- 提供清晰的错误信息:说明违反的具体规则和修复方法
- 允许跳过检查:使用
--no-verify参数,但要记录日志 - 定期更新规则:随着系统演化更新检查规则
- 结合 CI/CD:Git 钩子作为第一道防线,CI 系统做更全面的检查
这些脚本可以根据具体需求进行调整,例如添加对特定框架、库或协议的检查规则。