mcpField
K
keeping-git-repos-clean

keeping-git-repos-clean

github.com/wdm0006开发10961 次安装2 天前更新
代码仓库

关于 keeping-git-repos-clean

面向开发者和维护者的 Git 仓库清洁指南,帮助避免提交密钥、构建产物和个人文件,并说明如何审计、清理及检查验证产生的改动。

主要功能

  1. 01审计已跟踪文件中的密钥与杂项
  2. 02取消跟踪文件但保留本地副本
  3. 03清理前先轮换泄露的凭据
  4. 04配置全局忽略规则和提交扫描
  5. 05验证前后检查仓库状态

适用场景

  1. 01查找已跟踪的密钥或临时文件
  2. 02安全地停止跟踪本地文件
  3. 03处理已进入仓库历史的凭据泄露
  4. 04避免构建产物混入待审改动

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wdm0006/python-skills --skill keeping-git-repos-clean

安装后在 Claude Code 中输入/keeping-git-repos-clean确认已加载。

详细介绍

保持 Git 仓库整洁

有两类文件总是会混进仓库:机密信息和开发产物。 预防它们成本很低,事后清理却代价高昂,因为 Git 历史永远存在,而且公开仓库会发布所有内容。

大家总会忘记的那条规则

.gitignore 不会取消对已提交文件的跟踪。 将路径添加到 .gitignore 只会阻止未来尚未跟踪的文件被暂存。Git 已经跟踪的文件仍会继续被提交。这种情况屡见不鲜:.env 已列在 .gitignore 中,但在规则生效之前就已提交,所以它仍会被发布。

若要真正停止跟踪文件,同时保留本地副本:

git rm --cached path/to/file        # untrack, leave working-tree copy in place
git rm -r --cached some/dir/        # for a directory
echo "path/to/file" >> .gitignore   # then ignore it so it doesn't come back
git commit -m "Stop tracking <file>; add to .gitignore"

--cached 是关键标志——直接使用 git rm 也会删除工作副本。

审查仓库实际跟踪的内容

别指望 .gitignore 能告诉你仓库是否干净——直接查看索引:

git ls-files | grep -iE '\.(env|pem|key|p12|profraw|log|bak|db|sqlite3?)$'
git ls-files | grep -iE '(^|/)(\.DS_Store|~\$|todo\.db|node_modules/|__pycache__/)'
git ls-files '*.db' '*.sqlite*'                 # scratch databases
git ls-files | xargs -I{} du -h {} | sort -rh | head   # surprisingly large tracked files

在实际仓库中常见的可疑文件:

  • 机密信息: 含有有效令牌的 .env、设置模块中硬编码的 AWS_*/数据库凭据、发布到生产环境的 SECRET_KEY = "CHANGEME"/"foobar" 占位值。
  • 构建产物: LaTeX .aux/.toc/.log/.synctex.gz/.pdf、LLVM *.profraw、编译后的二进制文件、htmlcov/、dist/、*.egg-info/。
  • 临时文件 / 个人文件: todo.db 等工具本地的 SQLite 临时数据库、编辑器备份文件(*.backup、*.bak、~$*.docx Word 锁定文件)、多余的 *.log。
  • 操作系统杂项: .DS_Store、Thumbs.db。

机密信息不只是用 git rm 就能处理

从 HEAD 中删除机密信息,不会将它从历史中移除——git log -p 和引入它的提交仍会暴露它。必须依次完成三件事,其中只有第一件能真正保护你:

  1. 轮换凭据。 将任何曾接触过远程仓库的机密信息视为已泄露。签发新的令牌/密钥/密码,并撤销旧凭据。首先执行这一步——泄露的值一经推送就会公开。
  2. 从此不再跟踪(使用 git rm --cached + .gitignore + .env.example,其中说明所需变量,且仅使用占位值)。
  3. 按需清理历史(使用 git filter-repo --invert-paths --path .env 或 BFG),然后强制推送。这会重写 SHA 并影响协作者,因此通常是轮换凭据后由维护者有意执行的步骤,而不是自动化 PR。

如果 PR 做了(2)和(3)却跳过(1),只会带来虚假的安全感:该值仍然有效,而且仍存在于历史记录的克隆和分叉中。务必明确指出轮换凭据是必须由人工后续处理的事项。

“已提交”就意味着“已发布”

对于公开仓库,尤其是使用 path: '.' 部署的静态站点(GitHub Pages 会上传整个仓库),所有已跟踪文件都能通过公开 URL 获取。宣传网站仓库根目录中的临时 todo.db 会通过 /todo.db 提供访问。提交到任何公开仓库之前,都要假设任何人都能下载其中的文件。

做好预防:全局忽略 + 机密信息扫描器

每位开发者各自的杂项文件(编辑器文件、操作系统文件、todo.db 等工具临时数据库)应当全局忽略,而不是添加到每个项目的 .gitignore 中——这样它们就不会进入任何仓库:

git config --global core.excludesFile ~/.gitignore_global
printf '%s\n' '.DS_Store' '*.swp' 'todo.db' '*.profraw' >> ~/.gitignore_global

使用 pre-commit 钩子在提交时拦截机密信息,避免它们进入历史:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks: [{id: gitleaks}]
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.5.0
    hooks: [{id: detect-secrets, args: ["--baseline", ".secrets.baseline"]}]

起始项目 .gitignore(将其提交):

# Secrets / local config
.env
.env.*
!.env.example
*.pem
*.key

# Python build/test artifacts
__pycache__/
*.py[cod]
build/
dist/
*.egg-info/
.coverage
htmlcov/
.pytest_cache/

# Scratch / OS / editor
*.db
*.sqlite
*.sqlite3
*.profraw
*.log
*.bak
*.backup
.DS_Store
~$*

验证可能会弄脏工作树

即使命令只是为了验证更改,编译器、测试运行器和资源管线也常会在检出目录中写入文件。它们可能会创建未被忽略的缓存文件,或重新生成受版本控制的可分发文件,例如 PDF 或编译后的 CSS。命令运行成功并不意味着工作树中仍然只有你的更改。

在验证前后检查状态,并且只暂存经过审查的路径:

git status --short
make test                         # or the project's real build command
git status --short
git diff -- path/you/changed
git add path/you/changed          # never sweep in generated files with git add -A
git diff --cached --check
git diff --cached --stat

如果工具必然会产生大量杂项输出,请在一次性副本中运行。这样既能保留真实的构建过程,又能避免生成文件进入补丁:

scratch_dir=$(mktemp -d)
rsync -a --exclude .git ./ "$scratch_dir/"
(cd "$scratch_dir" && make build)

如果验证修改了一个不在预期范围内的受版本控制的生成文件,请先审查其差异,然后只还原该确切路径:

git diff -- docs/manual.pdf
git restore -- docs/manual.pdf

不要使用范围过大的还原或重置命令来清理:检出目录中可能已经有其他人的工作。也不要依赖 git stash 来清理未跟踪的产物;普通 stash 会忽略这些文件,而 --include-untracked 也可能与 stash pop 前重新生成的文件冲突。请明确预防或移除已知的生成路径。

检查清单

Audit:
- [ ] `git ls-files` reviewed for secrets, build output, scratch DBs, OS files
- [ ] No live credentials in tracked source or .env
- [ ] No surprisingly large/binary tracked files

Remediate (if dirty):
- [ ] Secret rotated/revoked FIRST (history is public the moment it was pushed)
- [ ] `git rm --cached` + .gitignore entry for each offending file
- [ ] .env.example documents required vars with placeholder values only
- [ ] History scrub flagged as a maintainer follow-up if the secret is in history

Prevent:
- [ ] Project .gitignore covers secrets, build artifacts, OS/editor noise
- [ ] Global core.excludesFile catches per-developer scratch files
- [ ] gitleaks / detect-secrets pre-commit hook installed
- [ ] Verification bracketed by `git status --short`; only reviewed paths staged

如需扫描源代码中的漏洞和硬编码机密模式,请参阅 auditing-python-security 技能——本技能关注的是 git 跟踪的内容。

评论

支持 Markdown