从 Git 历史中删除敏感数据

当敏感信息(如密码、密钥、私人域名等)被提交到 Git 仓库后,即使后续提交中删除了这些内容,它们仍然存在于 Git 历史记录中。本文介绍如何彻底清除这些敏感数据。

问题场景

  • 不小心提交了 API 密钥、密码
  • 配置文件中包含真实域名或个人信息
  • 已推送到 GitHub 等公开仓库

解决方案’"

方法一:使用 git filter-branch(内置工具)

适用于替换历史中所有提交的某个文件内容。

# 1. 暂存当前未提交的更改
git stash'"

# 2. 替换历史中所有 README.md 文件里的敏感内容
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --force --tree-filter \
  "find . -name 'README.md' -exec sed -i '' 's/敏感内容/替换内容/g' {} \;" \
  -- --all

# 3. 恢复暂存的更改
git stash pop

# 4. 强制推送到远程仓库(覆盖历史)
git push origin main --force

参数说明

参数 说明
<code>–force</code> 强制执行,即使已有备份
<code>–tree-filter</code> 对每个提交的文件树执行命令
<code>– –all</code> 处理所有分支
<code>sed -i ''</code> macOS 下的原地替换(Linux 用 <code>sed -i</code>)

方法二:使用 BFG Repo-Cleaner(推荐,更快)

适用于删除大文件或敏感文件。

# 安装 BFG
brew install bfg

# 删除某个文件的所有历史
bfg --delete-files 敏感文件.txt

# 或替换敏感文本
bfg --replace-text passwords.txt

# 清理并强制推送
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push origin main --force

方法三:使用 git filter-repo(官方推荐)

# 安装
brew install git-filter-repo

# 替换敏感内容
git filter-repo --replace-text <(echo '敏感内容==>替换内容')

# 重新添加远程并推送
git remote add origin https://github.com/user/repo.git
git push origin main --force

注意事项

  1. 强制推送有风险:会覆盖远程历史,协作者需要重新克隆仓库
  2. 轮换密钥:敏感信息一旦泄露,应立即轮换(如重新生成 API Key)
  3. GitHub 缓存:GitHub 可能会缓存提交,联系 GitHub 支持可请求清除
  4. 本地备份:操作前建议备份仓库 <code>cp -r .git .git.backup</code>

预防措施

  • 使用 <code>.gitignore</code> 忽略敏感文件
  • 使用环境变量存储敏感配置
  • 提交前检查 <code>git diff –staged</code>
  • 启用 GitHub 的 Secret Scanning 功能

总结

  1. git stash – 暂存当前未提交的更改
  2. git filter-branch –tree-filter – 遍历所有历史提交,用 sed 替换敏感内容
  3. git stash pop – 恢复暂存的更改
  4. git push –force – 强制推送覆盖远程历史