本文目录导读:

Git 钩子脚本可以通过检查特定文件(如决策记录文件)的变更,来确保新增或修改的决策记录符合特定规范,以下是几种常见的检查方式:
检查决策记录文件是否存在
使用 commit-msg 钩子,确保每次提交都包含决策记录文件:
#!/bin/bash
# .git/hooks/commit-msg
# 检查暂存区中是否有决策记录文件
if git diff --cached --name-only | grep -q "^decisions/"; then
echo "✓ 决策记录文件已包含在提交中"
else
echo "⚠️ 警告:本次提交未包含任何决策记录文件"
echo "建议在执行重大变更时记录决策:docs/decisions/"
fi
验证决策记录文件格式
使用 pre-commit 钩子,检查决策记录文件的命名和元数据格式:
#!/bin/bash
# .git/hooks/pre-commit
# 获取所有暂存的决策记录文件
DECISION_FILES=$(git diff --cached --name-only | grep "^decisions/.*\.md$")
for file in $DECISION_FILES; do
# 检查文件命名格式 (YYYY-MM-DD-title.md)
if [[ ! $file =~ ^decisions/[0-9]{4}-[0-9]{2}-[0-9]{2}-.*\.md$ ]]; then
echo "❌ 错误:决策记录文件命名不符合规范"
echo "格式应为:decisions/YYYY-MM-DD-title.md"
echo "当前文件:$file"
exit 1
fi
# 检查文件内容是否包含必需的元数据
if [ -f "$file" ]; then
# 检查状态字段
if ! grep -q "^# Status" "$file"; then
echo "❌ 错误:决策记录文件缺少状态字段"
echo "文件:$file"
exit 1
fi
# 检查决策标题
if ! grep -q "^# Decision" "$file"; then
echo "❌ 错误:决策记录文件缺少决策描述"
echo "文件:$file"
exit 1
fi
# 检查日期字段
if ! grep -q "^# Date" "$file"; then
echo "❌ 错误:决策记录文件缺少日期字段"
echo "文件:$file"
exit 1
fi
fi
done
echo "✓ 所有决策记录文件格式检查通过"
exit 0
检查决策记录的唯一性
使用 pre-commit 钩子,防止重复的决策记录:
#!/bin/bash
# .git/hooks/pre-commit
# 获取当前暂存的决策记录文件
STAGED_DECISIONS=$(git diff --cached --name-only | grep "^decisions/.*\.md$")
for file in $STAGED_DECISIONS; do
# 提取决策标题
DECISION_TITLE=$(head -n 1 "$file" | sed 's/^# //')
# 检查历史记录中是否有相同标题的决策
if git log --all --pretty=format: --name-only | grep "^decisions/" | sort -u | while read -r hist_file; do
if [ -f "$hist_file" ]; then
HIST_TITLE=$(head -n 1 "$hist_file" | sed 's/^# //')
if [ "$HIST_TITLE" == "$DECISION_TITLE" ] && [ "$hist_file" != "$file" ]; then
echo "❌ 错误:检测到重复的决策记录标题"
echo "当前文件:$file"
echo "历史文件:$hist_file"
exit 1
fi
fi
done
done
exit 0
高级检查:验证决策记录的完整性
使用 Python 脚本进行更复杂的检查:
#!/usr/bin/env python3
# .git/hooks/pre-commit (Python 版本)
import os
import re
import sys
import subprocess
def get_staged_files():
"""获取暂存区中的文件列表"""
result = subprocess.run(
['git', 'diff', '--cached', '--name-only'],
capture_output=True,
text=True
)
return result.stdout.strip().split('\n')
def validate_decision_record(filepath):
"""验证单个决策记录文件"""
errors = []
# 检查文件命名
if not re.match(r'^decisions/\d{4}-\d{2}-\d{2}-.*\.md$', filepath):
errors.append(f"文件命名不符合规范: {filepath}")
if not os.path.exists(filepath):
return errors
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# 检查必需的部分
required_sections = [
'# Status', # 状态 (Accepted/Deprecated/Superseded)
'# Decision', # 决策描述
'# Date', # 决策日期
'# Context', # 决策背景
'# Consequences' # 影响和结果
]
for section in required_sections:
if section not in content:
errors.append(f"缺少必需部分: {section}")
return errors
def main():
staged_files = get_staged_files()
decision_files = [f for f in staged_files if f.startswith('decisions/')]
if not decision_files:
print("✓ 本次提交不涉及决策记录文件")
sys.exit(0)
all_errors = []
for file_path in decision_files:
errors = validate_decision_record(file_path)
all_errors.extend(errors)
if all_errors:
print("❌ 决策记录文件检查失败:")
for error in all_errors:
print(f" - {error}")
sys.exit(1)
else:
print(f"✓ {len(decision_files)} 个决策记录文件检查通过")
sys.exit(0)
if __name__ == "__main__":
main()
安装和使用
将脚本保存到 .git/hooks/ 目录并赋予执行权限:
# 保存脚本 cat > .git/hooks/pre-commit << 'EOF' #!/bin/bash # 你的脚本内容 EOF # 设置执行权限 chmod +x .git/hooks/pre-commit
最佳实践建议
- 渐进式实施:先从基础检查开始,逐步添加更多规则
- 提供帮助信息:当检查失败时,提供清晰的错误信息和修复建议
- 允许跳过:在特殊情况下允许使用
--no-verify跳过钩子检查 - 版本控制:将钩子脚本放在项目仓库中统一管理
这些钩子脚本可以根据你的具体需求进行调整和扩展。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播