JordanNewell/git-hygiene

GitHub: JordanNewell/git-hygiene

git-hygiene 是一组零依赖的 Git hooks,用于自动剥离提交信息中的 AI 归因尾注并在提交前扫描密钥泄露。

Stars: 1 | Forks: 0

git-hygiene — Tools don't get co-author credit. Strip AI-attribution trailers and catch secrets before they land in your object store.
License: MIT release platform dependencies

## 落地页 静态站点,带有相同的数据表核心展示:**https://jordannewell.github.io/git-hygiene/** (在仓库设置 → main 分支根目录中启用 Pages,参见 `docs/superpowers/plans/2026-07-30-git-hygiene-site-branding.md` 任务 7)。 源码:`index.html` + `assets/site.css`。使用 `python tools/render_brand_assets.py` 重新生成品牌资产。 我工作过的每个仓库都在日志中慢慢积累了 `Co-Authored-By: Claude` 和 `🤖 Generated with Claude Code` 尾注。有时设置被还原了,有时是协作者的设置不同。提交历史是未来的雇主、收购方和协作者用来评估你工作方式的唯一产物——一个充满 AI 尾注的日志看起来像是表演性质的,这与资深技术人员彰显品味的方式截然相反。**你不会在你用他们的电钻建造的棚子上感谢 DeWalt。** 对于受监管的行业(国防、金融、医疗),AI 辅助编写的代码正成为一个真实的披露问题。干净的历史可以避开这个问题;而脏的历史则会引发问题。 两个 git hooks,除了 `bash`/`grep`/`awk`/`git` 之外零依赖。[gitleaks](https://github.com/gitleaks/gitleaks) 是可选的——安装后会增加约 700 个密钥检测器。 - **`commit-msg`** 会剥离 AI 归因尾注(`Co-Authored-By`、`Generated with`、`AI-assisted`)。保留合法的人类共同作者。 - **`pre-commit`** 分三层扫描暂存文件:高精度正则表达式、gitleaks(如果已安装),以及针对机器级标识符的可选 OPSEC 内容扫描。 在你的机器上针对你的暂存文件本地运行。无遥测,无 SaaS,无第三方扫描。 ## 策略 三个坚定的立场: 1. **AI 工具就是工具。** Claude、Copilot、Cursor、Gemini、ChatGPT——它们是完成工作的手段,而不是完成工作的人。作者是人类;工具就是工具。 2. **密钥绝不进入 git。** API keys、tokens、密码——pre-commit 会在它们进入你的 object store 之前捕获这些高精度模式。 3. **本地执行,无 SaaS 依赖。** hooks 在你的机器上针对你的暂存文件运行。无遥测,无云端调用,无第三方扫描。 ## 实际运行

git-hygiene in action — git commit triggers commit-msg strip (3 AI trailers removed) + pre-commit credential scan (7 files clean)

## 包含内容 ``` hooks/ ├── commit-msg # Strips AI-attribution trailers + OPSEC scan on subject ├── pre-commit # Scans staged files: credential patterns + OPSEC content ├── opsec-scan.sh # Sourceable library: builds $opsec_patterns from .local files └── opsec-patterns.local.example # Template for user's gitignored opsec-patterns.local ``` ### `commit-msg` 剥离匹配以下任何模式(不区分大小写)的行: - `Co-Authored-By: Claude/Copilot/Cursor/Gemini/ChatGPT/GitHub Copilot/anthropic` - `Co-Authored-By: `)将被保留。正文中将 Claude Code 作为工具引用的内容(例如“the Claude Code agent was mangling whitespace”)也会被保留——只有符合尾注格式的模式才会被剥离。 ### `pre-commit` 三层扫描:凭证模式、广泛的密钥检测和 OPSEC 内容扫描。 **第 1 层 — regex(始终开启,无依赖)。** 针对已知密钥格式的高精度模式: - AWS 访问密钥(`AKIA...`)和 secret keys - OpenAI(`sk-or-...`)、GitHub(`ghp_/gho_/ghu_/ghs_/ghr_/github_pat_...`)、Slack(`xoxb-/xoxp-`)tokens - Bearer tokens,匹配 `key="..."` 赋值的通用 API keys / 密码 / secrets **第 2 层 — gitleaks(安装后生效)。** 如果 [gitleaks](https://github.com/gitleaks/gitleaks) 在 `$PATH` 中,它会自动介入。增加约 700 个内置检测器(Stripe live keys、GCP service account JSON、private keys、database URLs 等),这是 regex 层无法覆盖的。如果未安装 gitleaks,该 hook 会打印一行警告并退回到仅使用 regex 的模式——提交仍然是安全的。 **第 3 层 — OPSEC 内容扫描(当存在 `~/.config/opsec-patterns.local` 或 `./.opsec-patterns.local` 时生效)。** 加载与 `commit-msg` 相同的 `opsec-scan.sh` 库,并扫描暂存文件的**新增行**(以及文件名),以匹配你的机器级 + 仓库级 OPSEC 模式——主机名、agent handles、codenames、tailnet 名称。用于捕获凭证格式的 regex 无法检测到的内容:注释中的 fleet 主机名、docstring 中的 agent handle、URL 中的 tailnet 后缀。 - **仅扫描 diff。** 包含合法提及的未更改文本不会被重新扫描——仅检查新增的行。历史提及仍然是一个单独的清理问题。 - **与第 1 + 2 层相同的路径跳过。** 测试 fixtures、`*.example`/`*.template` 扩展名、`node_modules/` 等将被豁免。 - **与 commit-msg 相同的 opt-out。** `git config opsec.scan disable` 也会关闭此层。 - **优雅的无操作。** 如果不存在 `.local` 文件(默认的 OSS 贡献者设置),则跳过第 3 层——仅运行硬编码的基准(session IDs + Tailscale CGNAT IPs),这对内容扫描很少有用,也绝不会阻止合法的代码。 **安装 gitleaks**(可选但推荐): ``` # macOS brew install gitleaks # Debian/Ubuntu apt install gitleaks # 其他平台 — 下载 release # https://github.com/gitleaks/gitleaks/releases ``` **路径跳过。** 这三层都会跳过已知包含逼真假密钥的暂存路径:`node_modules/`、`vendor/`、`third_party/`、`*.min.js`/`*.min.css`、`test[s]/`/`spec/`/`fixtures/`/`__tests__/`、`example[s]/`/`sample[s]/`/`demo/`/`docs/`,以及 `*.example`/`*.sample`/`*.template`/`*.dist` 模板扩展名。真正的 secrets 存在于源码/配置文件中。 ### `opsec-scan.sh`(可选——适用于拥有内部基础设施的运维人员) 可加载的库,从最多三层构建一个 `$opsec_patterns` regex: 1. **硬编码基准**(被追踪)—— session IDs(`Sxxx` 约定)+ Tailscale CGNAT IPs(`100.x.x.x`)。对所有人都安全。 2. **机器级** —— `$HOME/.config/opsec-patterns.local`(已 gitignore)。你真实的主机名、tailnet 名称、codenames、agent handles。每台机器定义一次,适用于你提交的每个仓库。 3. **仓库本地** —— `./.opsec-patterns.local`(已 gitignore)。用于特定项目模式的可选附加项。 `.local` 文件按照约定被 gitignore——它们包含本身就是 OPSEC 敏感的真实基础设施标识符。有关约定,请参见 [`hooks/opsec-patterns.local.example`](hooks/opsec-patterns.local.example)。 `commit-msg` 加载此库并扫描提交主题(第一行)以查找匹配项。不扫描正文——合法的文本可能会按名称提及协作者。如果不存在 `.local` 文件,则仅运行硬编码的基准(对于 OSS 贡献者来说是安全的默认设置)。 模式的单词边界会自动添加——`ada` 不会在 `readable` 或 `metadata` 中产生误报。 ## 安装 ### 按用户(推荐——适用于你拥有的每个仓库) ``` git clone https://github.com/JordanNewell/git-hygiene.git ~/git-hygiene # Symlink 到你的全局 hooks 路径 mkdir -p ~/.githooks ln -s ~/git-hygiene/hooks/commit-msg ~/.githooks/commit-msg ln -s ~/git-hygiene/hooks/pre-commit ~/.githooks/pre-commit chmod +x ~/.githooks/* # 告诉 git 全局使用该 hooks 路径 git config --global core.hooksPath ~/.githooks ``` ### 按仓库(如果你想要限定作用域) ``` cd /path/to/repo git config core.hooksPath /path/to/git-hygiene/hooks ``` ### 验证 ``` # 测试 commit-msg echo "Co-Authored-By: Claude Opus 4.7 " > /tmp/msg echo "test subject" >> /tmp/msg git commit -F /tmp/msg --allow-empty # trailer should be stripped from the result git log -1 --format='%B' # 测试 pre-commit echo "AWS_SECRET_ACCESS_KEY=abcd1234..." > /tmp/secret git add /tmp/secret # should fail or warn ``` ### 可选:OPSEC 扫描设置 如果你在一台同时托管内部基础设施(homeserver、agent fleet、内部 codenames)的机器上向公共仓库提交代码,请启用 OPSEC 扫描: ``` # 1. 创建你的机器级 patterns 文件 mkdir -p ~/.config cp ~/git-hygiene/hooks/opsec-patterns.local.example ~/.config/opsec-patterns.local # 2. 编辑 ~/.config/opsec-patterns.local — 用你的真实值替换示例 # (主机名、tailnet 名称、agent 别名、代号、内部服务名称) # 3. 测试 — commit-msg 现在将阻止包含你的 patterns 的主题 echo "S100: test session id" > /tmp/msg git commit -F /tmp/msg --allow-empty # should FAIL with OPSEC leak message ``` 想要在机器级集合之上添加特定项目模式的仓库,可以添加一个 `./.opsec-patterns.local` 文件(不要忘记将其加入 gitignore)。 ### 按仓库 opt-out 如果某个仓库的历史记录中合理地引用了与你的 OPSEC 模式匹配的内部 codenames(例如,一个内部基础设施仓库的提交使用 `feat(fleet-cabinet-ops): ...` 作为主题范围),请按仓库 opt-out: ``` cd /path/to/internal-repo git config opsec.scan disable git config opsec.scan # should print: disable ``` 该 opt-out: - 存在于 `.git/config` 中——绝不会意外提交。 - 接受 `disable`、`off`、`false`、`no`、`0`(不区分大小写)——选一个你觉得自然的即可。 - 仅禁用 OPSEC 模式扫描。`commit-msg` 中的 AI 归因剥离和 `pre-commit` 中的 secret 扫描(regex + gitleaks)不受影响。 - 用于其提交永远不会到达公共 remote 的内部仓库。不要在推送到公共 GitHub/GitLab 的仓库上使用它。 使用 `git config opsec.scan` 验证它是否已激活。启用时,`commit-msg` 会向 stderr 输出一行通知:`OPSEC scan skipped (opsec.scan=disable)`。 ## 纵深防御 该 hook 是三层防御之一。腰带、背带,再加一条腰带。 1. **编辑器 / agent 设置** —— Claude Code 的 `~/.claude/settings.json` 包含 `includeCoAuthoredBy: false`。首先阻止尾注被发出。Copilot、Cursor 等都有各自的等效设置。 2. **此 hook** —— `commit-msg` 捕获漏网之鱼。不关心是哪个工具发出了尾注。 3. **CLAUDE.md / AGENTS.md 指令** —— 针对在仓库中运行的 AI agents 的行为规则。 每一层都会独立失效放行。这三者结合在一起非常稳健。 ## 为什么这很重要 **版权 / IP。** 将 AI 共同作者身份混入提交元数据会模糊谁拥有代码的所有权。一些司法管辖区开始对 AI 辅助工作进行诉讼;干净的归因历史是一种防御手段。 **招聘信号。** 未来的雇主、收购方、贡献者会阅读你的提交历史。一个每次提交都写着 `Co-Authored-By: Claude` 的仓库看起来像是表演性质的——“看,我使用 AI!”——这与资深技术人员彰显品味的方式截然相反。 **审计跟踪。** 对于受监管的行业(国防、金融、医疗),AI 辅助代码是一个真实的披露问题。一些组织完全禁止它。不带有 AI 归因的干净提交历史可以避开这个问题;而脏的历史则会引发问题。 ## 这不是什么 - 不是水印 / 隐写工具 - 不是供应链认证框架(请查看 SLSA / Sigstore) - 不能替代 `pre-commit` 框架、Husky、GitGuardian 或 TruffleHog 服务 - 不是用于组织级执行的策略引擎(为此请使用 GitHub push rules) 它是一套小巧、专注的 hooks,适用于希望在不依赖 SaaS 的情况下保持干净本地提交历史的个人运维人员。 ## License [MIT](LICENSE) © Jordan Newell ## Signature 本仓库遵循 [Jordan Newell 代码签名模式](https://jordannewell.com/signature/)。PGP 指纹:`67567DC5E7C5353F85F2AF0DAC05D3F3E0EFA32A`。使用 `git verify-commit HEAD` 验证提交。

Built by Jordan Newell

标签:Bash, Git钩子, Shell, SOC Prime, StruQ, 代码规范, 应用安全, 开发工具, 网络安全研究