本文目录导读:

我们可以通过Git钩子(Hook) 来检查“月度任务”是否完成,但需要先明确:Git钩子是针对每次提交、推送等操作触发的,无法主动按月轮询,通常的实现思路是:在提交或推送时,检查本月是否满足特定条件(如本月已完成某个任务、生成了月度报告文件等)。
以下是几种常见场景的脚本实现方案:
核心逻辑
在 pre-commit 或 pre-push 钩子中:
- 获取当前日期(年、月)。
- 检查是否存在该月的“任务完成标记”(文件、Git标签、数据库记录等)。
- 如果未完成,则拒绝提交/推送并给出提示。
示例 1:检查本月是否存在特定文件(如月度报告)
假设团队约定:每月必须在仓库根目录提交一个 report-YYYY-MM.md 文件。
脚本:.git/hooks/pre-commit(需赋予执行权限 chmod +x)
#!/bin/bash
# 获取当前年月
year=$(date +%Y)
month=$(date +%m)
expected_file="report-${year}-${month}.md"
# 检查工作区或最新提交中是否存在该文件
# 方法A:检查工作区(未提交的文件也算,适合要求本地生成后再提交)
if [ ! -f "$expected_file" ]; then
echo "❌ 月度任务未完成:缺少本月报告文件 $expected_file"
echo "请先生成该文件再提交。"
exit 1
fi
# 方法B:检查最新提交的HEAD中是否存在(适合已提交过的远程校验)
# if ! git show HEAD:$expected_file > /dev/null 2>&1; then
# echo "❌ 月度任务未完成:HEAD提交中缺少 $expected_file"
# exit 1
# fi
echo "✅ 月度文件检查通过"
exit 0
示例 2:检查本月的Git标签是否存在(如发布标记)
场景:每月需要打一个 release-YYYY-MM 标签才能进行代码推送。
脚本:.git/hooks/pre-push
#!/bin/bash
# 获取当前年月
tag_name="release-$(date +%Y-%m)"
# 检查本地或远程是否存在该标签
if ! git tag -l | grep -q "^${tag_name}$"; then
echo "❌ 月度任务未完成:缺少标签 $tag_name"
echo "请先创建标签: git tag $tag_name && git push origin $tag_name"
exit 1
fi
echo "✅ 月度标签检查通过"
exit 0
示例 3:检查外部API或数据库记录(高级)
如果月度任务状态存储在外部的服务器或数据库中,可在钩子中调用API检查。
#!/bin/bash
month=$(date +%Y-%m)
check_url="https://your-task-tracker.com/api/check?user=$(git config user.email)&month=$month"
# 模拟HTTP请求(需要curl)
response=$(curl -s --max-time 5 "$check_url")
if [ "$response" != "completed" ]; then
echo "❌ 本月任务状态:$response"
echo "请完成月度任务后再提交。"
exit 1
fi
exit 0
重要注意事项
-
钩子保存在本地:
.git/hooks/目录不会被git推送,需要团队手动部署。- 解决办法:将脚本放在仓库的
scripts/hooks/目录下,团队成员通过make setup-hooks或符号链接同步。
- 解决办法:将脚本放在仓库的
-
客户端钩子易绕过:用户可用
--no-verify跳过pre-commit钩子,或通过git push --no-verify跳过pre-push。更严格的校验需要服务端钩子(如GitHub Actions、GitLab CI、Gitee Webhook)配合。
-
时区问题:
date命令依赖系统时区,跨时区团队建议统一使用UTC时间。 -
性能影响:若钩子调用外部API,需设置超时避免阻塞。
更完善的方案:结合服务端钩子
如果希望强制检查,更可靠的是在服务端(如GitLab的自定义钩子或GitHub的Actions) 进行校验:
GitLab 服务端 pre-receive 钩子示例:
#!/bin/bash
# 部署在服务端 hooks/pre-receive
while read oldrev newrev refname; do
month=$(date +%Y-%m)
# 检查推送的提交中是否包含月度文件
if ! git diff-tree --no-commit-id -r "$newrev" --name-only | grep -q "report-${month}.md"; then
echo "❌ 拒绝推送:缺少本月报告文件 report-${month}.md"
exit 1
fi
done
exit 0
| 需求场景 | 推荐钩子类型 | 检查方式 |
|---|---|---|
| 每月需提交固定文件 | pre-commit |
检查工作区或HEAD中是否存在该月文件 |
| 每月需打标签 | pre-push |
检查是否存在本月的标签 |
| 任务状态在外部系统 | pre-push |
调用外部API |
| 强制团队遵守 | 服务端钩子/CI | 服务端 pre-receive或CI脚本 |
选择哪种方式取决于你的强制力要求和基础设施,对于团队内部规范,客户端钩子 + 文档说明通常足够。