如何在不影响历史记录的情况下删除旧提交

How to delete old commits without affecting history

我需要删除 1 年前的提交,因为它们包含必须删除的敏感数据。

我已经使用了BFG Repo-Cleaner,我几乎可以删除所有内容,但是有一些非常旧的提交没有被删除

我会尝试写一个例子; GIT 历史看起来像这样

A 是最旧的,C 是最新的提交)

这就是我需要的(B 不再存在,但以后的提交不受影响):

我在一个大团队工作,所以除非别无选择,否则我想避免使用 git push -f

实现此目标的最佳方法是什么?

非常感谢

(编辑)

这是因为我们对我们的存储库进行了定期扫描,将提交 A 检测为漏洞。

我们进行了提交 B,是否删除了所有凭据和机密文件,问题是扫描还将提交 B 检测为 'security issue'。

我们被要求删除提交 B 以通过扫描。

TL;DR

  • 您必须首先重写提交 A 以不包含敏感文件
  • 你必须使用git push -f
  • 你还没有完成:你还必须清除服务器上的历史记录

重写提交 A 和整个历史

这应该是 bfg 为您所做的。我假设你 运行 类似于 bfg --delete-files <sensitive-file>。这应该创建了一个全新的历史记录,其中 <sensitive-file> 从未存在过:添加或修改它的提交以及其他文件应该在没有该文件的情况下重写。只触及它的提交应该消失,因为它们现在是空提交。

所以现在你已经提交了 A',A 的副本没有 <sensitive-file>。其余的历史被改写为它的后继者:C'等

为了确认这是否正确,运行 在旧沙箱和由 bfg 更新的新沙箱中执行此命令:

git log --all <sensitive-file>

您应该会看到涉及原始存储库中敏感文件的提交,但在新存储库中没有输出。这就是您可以确信该文件确实已从历史记录中删除的方式。

你必须使用git push -f

Git 提交的 sha1 是提交及其所有元数据(提交者、日期、评论等)、所有内容及其所有历史记录的加密签名。

如果您更改提交的任何一方面:日期、评论、内容或其任何祖先的任何一方面,根据定义,加密签名会发生变化。

所以唯一的出路是git push -f

您可能还没有完成

但是等一下,在执行 git push -f 之后,服务器仍然会有旧历史的副本。请在此处查看 Git 中心:If you pushed to GitHub, it is too late even if you force push it away one second later。显然,从 GitHub 存储库中删除敏感文件的唯一真正安全的方法是删除它并重新创建一个只包含您想要保留的干净历史记录的新文件。还有其他解决方案,但您的里程可能会有所不同 - 链接中的详细信息 post.

如果您使用的是不同的或私有的 Git 服务器,请确保强制执行垃圾收集并遵循 Remove sensitive files and their commits from Git history

中的进一步建议