Skip to main content

如何彻底清除 Git 仓库中提交的敏感信息

· 12 min read
Kyle

下面奉上一篇完整的技术博客,详细讨论了如何清除 Git 仓库历史中包含敏感信息的问题。博客内容包含了问题背景、各种解决方案的对比、推荐排序以及每种方法的详细操作步骤和示例,适用于所有基于 Git 的代码托管平台,不依赖于任何特定平台。


如何彻底清除 Git 仓库中提交的敏感信息

摘要

在开发过程中,常常会遇到这样的问题:仓库在初始化或开发时曾包含敏感内容(例如配置、密钥等),即便在后续提交中删除了这些文件,但敏感信息仍留存在历史记录中。本文将详细介绍清除历史中敏感信息的 5 种常见方法,逐一对比各自的适用范围、优缺点,并给出详细的操作步骤和示例,帮助开发者选择最适合自己场景的方案。


目录

  1. 问题背景
  2. 解决方案总览与对比
  3. 推荐方案排序
  4. 各方案详细操作步骤
  5. 总结与注意事项

问题背景

在代码开发初期,仓库可能包含一些敏感数据(例如配置文件、凭证信息等)。即使这些内容在后续的提交中被删除,历史记录中依然存在相关记录,公开仓库时就存在安全隐患。因此,如何彻底清除历史记录中的敏感内容就成了一个亟待解决的问题。


解决方案总览与对比

下面介绍 5 种常见的方法,并对它们的适用范围、优缺点进行简单对比说明:

方法适用范围优点缺点
A. 重写历史:git filter-branch / git filter-repo整个历史(所有提交)彻底清除所有敏感内容;适用于敏感数据大范围污染操作较复杂,修改历史后需强制推送,协作者需重新同步
B. 使用 BFG Repo-Cleaner清理大文件或敏感内容操作快速、简单;特别适用于清理大文件和敏感数据同样需要重写历史,推送后所有协作者必须重新拉取更新
C. 使用 git rebase -i 交互式变基仅影响少数近期提交针对性强,可逐个提交进行修改或删除,操作直观适用于提交数量较少的情况;若历史过长,操作工作量较大;需强制推送
D. 新建仓库并迁移内容对历史要求不高、可舍弃旧历史彻底摆脱历史问题,操作简单,风险较低(保留原仓库作为备份)丢失所有历史记录,需通知所有协作者切换到新仓库
E. 修改 .gitignore 预防未来问题防止敏感文件未来被提交操作简单,能有效避免未来敏感文件误提交无法清除已存在历史中的敏感信息,仅适用于预防后续问题

推荐方案排序

  1. A / B(重写历史)

    • 适用场景:敏感内容在整个仓库历史中广泛存在时,采用这两种方法能够彻底清除所有痕迹。
    • 说明:其中使用 git filter-repo 提供了较高的灵活性,而 BFG Repo-Cleaner 在操作速度上更快。
  2. C(git rebase -i 交互式变基)

    • 适用场景:敏感信息仅出现在近期的少量提交中时,交互式变基可针对性地修改或删除相关提交。
  3. D(新建仓库并迁移内容)

    • 适用场景:当历史记录不再需要保留,只需从最后一次无敏感记录的提交开始新建仓库。
  4. E(修改 .gitignore)

    • 适用场景:仅用于预防敏感文件在未来误提交,无法解决已有历史问题。

各方案详细操作步骤

A. 使用 git filter-branch / git filter-repo 重写历史

1. 使用 git filter-branch 示例

  1. 备份仓库
    在操作之前,务必备份现有仓库:
    git clone <仓库地址> <备份文件夹>
    
  2. 删除敏感文件
    假设敏感文件的路径为 <file-path>
    git filter-branch --force --index-filter \
      'git rm --cached --ignore-unmatch <file-path>' \
      --prune-empty --tag-name-filter cat -- --all
    
  3. 强制推送到远程仓库
    git push origin --force --all
    git push origin --force --tags
    
  4. 协作者重新同步
    通知其他协作者执行以下命令:
    git fetch origin
    git reset --hard origin/main
    

2. 使用 git filter-repo 示例

  1. 安装 git filter-repo
    例如在 macOS 上使用 Homebrew:
    brew install git-filter-repo
    
  2. 删除敏感文件
    git filter-repo --path <file-path> --invert-paths
    
  3. 强制推送更新
    git push origin --force --all
    

B. 使用 BFG Repo-Cleaner 清理敏感内容

  1. 安装 BFG Repo-Cleaner
    例如在 macOS 上使用 Homebrew:
    brew install bfg
    
  2. 克隆仓库的镜像
    git clone --mirror <仓库地址>
    
  3. 清理敏感文件
    假设需要删除的文件名为 <file-name>
    bfg --delete-files '<file-name>' <仓库名>.git
    
  4. 清理多余的引用并推送更新
    cd <仓库名>.git
    git reflog expire --expire=now --all
    git gc --prune=now --aggressive
    git push --force
    

C. 使用 git rebase -i 交互式变基

  1. 查找包含敏感信息的提交
    使用以下命令查看提交记录:
    git log --oneline
    
  2. 启动交互式变基
    假设需要修改最近 10 次提交:
    git rebase -i HEAD~10
    
  3. 在编辑器中修改提交列表
    将包含敏感信息的提交前的 pick 改为 edit(或直接删除该行以 drop 提交),例如:
    pick 123abc First commit
    edit 456def Add sensitive data
    pick 789ghi Some changes
    
  4. 修改暂停的提交
    当变基暂停后:
    • 重置该提交内容:
      git reset HEAD~
      
    • 手动删除敏感文件:
      rm <sensitive-file>
      
    • 重新提交修改:
      git add .
      git commit --amend -C HEAD
      
  5. 继续变基
    git rebase --continue
    
  6. 变基结束后强制推送
    git push origin main --force
    

D. 新建仓库并迁移内容

  1. 确定最后一次无敏感信息的提交
    通过 git log 查找记录,记下对应的提交编号 <commit-id>
  2. 克隆仓库到新文件夹
    git clone <旧仓库地址> new-repo-folder
    cd new-repo-folder
    
  3. 重置到最后一次良好提交
    git reset --hard <commit-id>
    
  4. 更改远程地址并推送到新仓库
    git remote set-url origin <新仓库地址>
    git push -u origin main
    
  5. 通知所有协作者切换到新仓库

E. 修改 .gitignore 预防未来问题

  1. 编辑 .gitignore 文件
    将敏感文件的路径添加到文件中,例如:
    <file-path>
    
  2. 提交 .gitignore 修改
    git add .gitignore
    git commit -m "Add sensitive files to .gitignore to prevent future commits"
    git push origin main
    
  3. 注意事项
    此方法仅用于预防未来敏感文件误提交,无法删除历史记录中的敏感信息。

总结与注意事项

  • 选择方法依据

    • 若敏感内容分布于整个历史记录,建议采用重写历史的方法(A 或 B),可确保彻底清除所有痕迹。
    • 若敏感内容仅出现在少数近期提交中,则交互式变基(C)操作简单且直观。
    • 若不需要保留历史记录,新建仓库(D)是最稳妥的做法。
    • 为防止未来误提交,则需及时更新 .gitignore(E),但这并不影响已有的历史。
  • 强制推送的影响
    上述大部分方法都会重写 Git 历史,推送后远程仓库历史将被覆盖。务必提前备份,并通知所有协作者重新同步仓库,否则可能导致团队协作出现混乱。

  • 平台适用性
    本文所有方法均适用于基于 Git 的任意代码托管平台,不局限于某一特定平台。

通过本文的详细说明和示例,开发者可以根据实际情况选择合适的方案,确保仓库在公开之前不包含任何敏感信息。希望这份技术博客对您的项目安全管理提供实用的指导与帮助!