git log 导出的是可验证、可归档的审计线索,需用 --pretty=format:"%h | %an | %ae | %ad | %s | %g?" --date=iso --all 保留签名状态与全分支记录,配合 reflog 和 fsck 补全不可达提交,并存入不可变存储以满足合规要求。

git log 导出的不是“快照”,而是可验证、可归档的审计线索——只要格式对、签名开、路径准,离线分析就能直接对接合规流程。
导出带 GPG 签名验证状态的完整提交日志
合规审计最怕“谁改的、改没改过、验没验过”三连问。只用 git log --oneline 会丢掉签名信息,git log --pretty=format 必须显式包含 %G? 才能标记签名状态(G 表示验证通过,N 表示无签名,U 表示坏签名)。
git log --pretty=format:"%h | %an | %ae | %ad | %s | %G?" --date=iso --all > audit_$(date +%F).log- 务必加
--all,否则漏掉未合并分支的提交,破坏可追溯性 - 输出中每行末尾的
G/N是审计链关键证据,不能靠事后人工补 - 如果仓库没启用 GPG 签名,
%G?全是N,此时导出日志仅满足“形式归档”,不满足 SOX 或 ISO/IEC 27001 的“可验证性”要求
用 reflog + git fsck 做不可抵赖的历史补全
git log 只显示可达提交,而 git reflog 和 git fsck 能找回被 reset --hard 或 rebase 删除但尚未 GC 的记录——这对调查人为误操作或异常删改至关重要。
Conventional Commits v1.0.0 分支、工作树命名及提交信息规范,适用于 GitHub 与 GitLab 项目,用于创建分支和命名工作树等场景。
-
git reflog --format="%h | %gs | %gd | %aE | %ad" --all > reflog_$(date +%F).log(%gs记录操作类型,如checkout: moving from main to feature) -
git fsck --unreachable --no-reflogs | grep commit | cut -d' ' -f3 | xargs -I{} git show -s --format="%H | %an | %ae | %ad | %s" {} 2>/dev/null提取悬空提交元数据 - 这两类输出必须和
git log结果分开归档,因为它们生命周期短(默认 30 天后被git gc清理) - 生产环境建议每天定时执行并推送到不可变存储(如 S3 Object Lock 或 Azure Immutable Blob),否则“历史存在过”无法举证
VS Code 插件导出 vs CLI 导出:别混淆“浏览”和“归档”
VS Code 的 Git History 插件点几下就能导出 CSV,但它只导出当前视图所见提交(比如只限 main 分支、只限最近 50 条),且不包含 %G?、%P 等审计字段——它适合快速排查 Bug,但不能用于合规存档。
- 插件导出路径通常为
./history-export-2026-06-15.csv,内容是表格化界面渲染结果,非原始 Git 对象引用 - CLI 导出必须用
git log直接读取对象数据库,才能保证哈希、签名、父提交等字段与 Git 内部一致 - 如果审计方要求提供“与 Git 仓库二进制一致的日志”,插件导出文件会被直接拒收
- 插件导出的 CSV 缺少时间戳时区信息(常为本地时间),而
--date=iso输出带+0800偏移,满足 GDPR 的“时间可比对”要求
离线分析时绕不开的三个硬约束
把日志拷到离线环境后,分析脚本很容易踩坑:时间格式错、字段分隔符冲突、签名状态误判。这些不是“功能问题”,而是合规失效的起点。
- 别用空格当分隔符——提交消息里可能含空格;
|或\t更安全,但需在解析脚本里统一转义 -
%ad输出的 ISO 时间含空格和冒号,Python 的datetime.fromisoformat()能直解,但旧版 pandas 需先替换:为. - 签名状态字段
%G?是单字符,但某些终端会把U(坏签名)和N(无签名)都显示为?,必须用git log原生命令重跑验证 - 离线机器若没装 Git,就无法用
git verify-commit复验签名——意味着你只能信“导出时的状态”,所以导出动作本身必须在可信环境中执行










