使用 `git-filter-repo` 删除 Git 敏感信息

avatar
作者
猴君
阅读量:0

背景

在软件开发过程中,敏感信息(如密码、API 密钥等)有时会意外地被提交到 Git 仓库中。随着项目的发展和历史提交记录的积累,清理这些敏感信息变得愈发困难,尤其是在无法修改生产密码的情况下。本文将介绍如何使用 git-filter-repo 工具安全地从 Git 历史记录中删除敏感信息,从而保护你的代码库安全并减少潜在的安全风险。

安装 git-filter-repo

git-filter-repo 是一个非常灵活的开源工具,可以从整个 Git 仓库历史中移除敏感信息和大文件(blobs),而不仅仅是最后的提交。它是 git-filter-branch 的推荐替代品。

首先,需要确保你的系统上安装过 Python。使用包管理器(如 pip)进行安装它是一种方便的方式。

下面可以安装 git-filter-repo。你可以通过以下命令安装:

pip install git-filter-repo 

前置准备与风险警告

  1. 评估影响:清理历史记录会影响整个代码库的历史,因此需要充分评估对项目和团队的影响。确保所有团队成员了解这次操作的重要性和必要性。

  2. 备份仓库:在进行任何历史修改之前,务必创建仓库的完整备份。(这样即使出问题了也还有救)可以通过以下命令克隆一个镜像仓库:

    git clone 仓库地址 
  3. 通知团队:清理敏感信息需要强制推送,这会覆盖远程仓库的历史记录。通知团队成员,确保他们了解即将进行的操作,并在清理操作完成前避免提交新的代码。

  4. 冻结代码库:在清理敏感信息期间,建议暂时冻结代码库,停止所有开发活动,避免冲突和数据丢失。

  5. 检查依赖和 CI/CD:确认所有依赖项和 CI/CD 管道不会因历史记录更改而受到影响。确保在清理后测试和部署流程仍能正常运行。

使用 git-filter-repo 删除敏感信息

以下是使用 git-filter-repo 删除敏感信息的关键步骤:

1.编写replacements.txt

可以放到电脑的任意位置,比如我是mac电脑,放在了/Users/admin/data/20240802目录下面

这个文件将列出你需要替换的敏感信息。格式如下:

password001 cigfkkdmgnl6jrfmbkqd0luaho54l9bbs==>process.env.SDK_KEY bob@split.io==>support@split.io password002==>[PASSWORD] 

replacements.txt 文件中,每行包含一个敏感文本。你可以添加多条替换规则。

解释

原始内容替换后内容解释
password001完全移除这一行表示 password001 将被从仓库历史中完全移除。
cigfkkdmgnl6jrfmbkqd0luaho54l9bbsprocess.env.SDK_KEY这一行表示将 cigfkkdmgnl6jrfmbkqd0luaho54l9bbs 替换为 process.env.SDK_KEY。
bob@split.iosupport@split.io这一行表示将 bob@split.io 替换为 support@split.io。
password002[PASSWORD]这一行表示将 password002 替换为 [PASSWORD]。

2.执行移除敏感数据命令

使用以下命令从整个 Git 仓库历史中移除敏感数据:

(PS:在执行接下来的命令时,一定要和团队取得联系,千万要小心!)

git filter-repo --replace-text /Users/admin/data/20240802/replacements.txt --replace-refs delete-no-add 

解释

参数或选项描述
git filter-repo这是主要命令,用于启动 filter-repo 工具。
--replace-text /Users/admin/data/20240802/replacements.txt使用 /Users/admin/data/20240802/replacements.txt 文件中的替换规则来替换仓库中所有的文本(包括当前分支以及所有的历史提交)。这个文件包含一系列替换规则,可以参考上面的那个例子
--replace-refs delete-no-add这个选项用于替换引用,delete-no-add 表示删除旧引用但不添加新引用。

这条命令会根据 replacements.txt 文件中的规则替换历史记录中的敏感信息,并更新所有引用。

如果这条命令执行失败,它会提示你加上–force,那么可以改成这条命令

git filter-repo --replace-text /Users/admin/data/20240802/replacements.txt --replace-refs delete-no-add --force 

切记,这个过程中,你当前项目里所有的replacements.txt里出现的文本都会被替换,不仅仅是你的历史提交记录,也包括你的当前的分支。所以如果你的这个密码如果与你的代码某部分重合,那么就会导致尴尬的情况:

比如你的有个密码叫Password。

而你有个类叫做PasswordService,正好命中这个密码

@Slf4j @Service @AllArgsConstructor public class PasswordService  { } 

那么它也会被替换成

@Slf4j @Service @AllArgsConstructor public class ***REMOVED***Service  { } 

这可能会导致你当前的项目无法运行。(所以要全局搜索一下REMOVED,看看是否要改回来)

另外一个比较好的做法是,在replacements.txt里增大匹配的难度,缩小替换的范围,比如,假设我们只是想修改application.yml里的配置,那其实可以在Password左侧加上其对应的key,那这样可以减少替换范围。

3.执行移除敏感文件命令

有些时候,如果你的某个文件整个都是敏感的。或者完全不想要某个文件的提交历史。(有可能是大文件)

你可以从提交历史中移除包含敏感数据的文件,可以使用以下命令:

(PS:在执行接下来的命令时,一定要和团队取得联系,千万要小心!)

git filter-repo --invert-paths --path <path-to-sensitive-file> --replace-refs delete-no-add 

例如,如果你想移除文件 config.json,命令如下:

git filter-repo --invert-paths --path config.json --replace-refs delete-no-add 
命令部分解释
git filter-repo一个工具,用于重写Git存储库历史
–invert-paths反转路径选择,即选择所有匹配指定路径的文件进行操作。
–path config.json指定路径 config.json,在此命令中将与 --invert-paths 配合使用,即选择所有包括 config.json 的文件。
–replace-refs delete-no-add删除所有对引用(如分支、标签等)的添加操作,而不添加新的引用。这意味着会删除历史记录中对引用的所有修改。

效果就是保留除了config.json以外的所有文件(等价于将config.json从所有提交中删除)

4.强制推送

当你执行完刚刚的惊心动魄的操作以后,你会发现的Git本地仓库不再关联远程仓库,比如你用下面这条命令检查一下

git remote -v 

会发现没有输出,即为没有任何一个远端仓库与本地仓库相关,因此,此时需要重新执行下面这条命令,关联之前的远端仓库。

git remote add origin 仓库地址 

强制推送到远程仓库:在本地清理完成后,你需要强制推送更改到远程仓库,以覆盖远程历史记录。

git push origin --force --all git push origin --force --tags 

(PS:在执行这条命令时,一定要和团队取得联系,千万要小心!!!)

结论

通过上述步骤,你可以安全地从 Git 仓库中删除敏感信息,确保代码库的安全性。git-filter-repo 提供了一个强大而灵活的解决方案,使得清理 Git 历史变得更加容易和高效。

希望这篇指南能帮你更好地理解和使用 git-filter-repo 工具。如果有任何问题,欢迎在评论区讨论。

致谢

How to Remove Sensitive Data From a Git History

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!