最可靠方式是直接调用 git log --no-pager --pretty=format:"%h|%an|%ae|%ad|%s" --date=iso8601-strict --branches --tags,避免分页、颜色及无效分支干扰,确保结构化输出稳定可解析。

用 git log 提取原始提交数据最可靠
直接调用 Git 命令比依赖第三方库(如 GitPython)更稳定,尤其在 CI 环境或路径含空格/中文时。git log 输出结构清晰,适合后续解析。关键是要固定格式、避免分页和颜色干扰:
- 必须加
--no-pager,否则可能卡住或截断输出 - 用
--pretty=format:"%H|%an|%ae|%ad|%s"控制字段分隔,避免日志内容里出现换行或管道符干扰解析 -
--date=iso8601-strict统一时区和格式,避免夏令时歧义 - 慎用
--all:如果仓库有大量孤立分支或 reflog,会拉出无效提交;建议明确指定--branches --tags
按作者邮箱去重合并贡献量是实际可行的方案
同一个开发者常有多个邮箱(name@company.com / name@gmail.com),单纯按 %an(作者名)统计会导致重复计数。但完全靠人工维护映射表不现实。折中做法是:
- 优先以
%ae(作者邮箱)为 key 统计,覆盖 90%+ 场景 - 对内部团队,可预置一个
alias_map = {"a@old.com": "a@new.com", ...}字典,在解析后做一次归一化 - 避免用正则模糊匹配邮箱(如只取用户名部分),容易误合(
admin@和admin2@) - 注意
git log中的%ce(提交者邮箱)和%ae不同,协作场景下应统一用%ae
统计逻辑要区分“提交数”和“有效代码量”
纯提交次数容易被刷量(比如每改一行就 git commit),而 git diff --shortstat 又太重、无法批量跑。实用平衡点是:
- 统计每个提交的
git show --oneline --shortstat <commit></commit>,提取+X -Y行数,但仅对非 merge 提交执行(加--no-merges) - 跳过自动生成的提交(如
Merge pull request #xxx、chore: release v1.2.3),可用简单关键词过滤:if "merge" not in subject.lower() and "chore" not in subject.lower() - 不做行级去重或空白行过滤——Git 本身不提供该信息,额外 diff 解析开销大且不可靠
脚本运行前必须检查 Git 仓库状态和权限
很多脚本本地能跑,CI 上失败,根源常在环境假设上:
- 确保当前目录是 Git 工作区根目录:
subprocess.run(["git", "rev-parse", "--is-inside-work-tree"], capture_output=True).returncode == 0 - CI 环境常为浅克隆(
git clone --depth=1),需先执行git fetch --unshallow或改用--since="3 months ago"限定范围 - Windows 下用
shell=True调用git命令易出编码问题,推荐始终用text=True, encoding="utf-8"显式声明 - 别把结果硬编码成 CSV 写入当前目录——CI 可能无写权限,应支持
--output path.csv参数或直接 stdout
github-actions[bot] 或 dependabot[bot],是否计入?这得看你们周报口径,脚本里留个 exclude_bots = True 开关比写死逻辑更实在。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











