简短的回答 - 创建一个新的 repo
要进行如此彻底的清理,您需要创建一个全新的 repo 并删除旧的。
我可以为您提供有关运行垃圾收集、清除 reflog 以及查找 Git 存储已删除提交一段时间的其他地方的答案,但是对于您提出的问题,我强烈推荐一个新的存储库。
特别是,如果您使用 GitHub 或其他在线 Git 服务器,完全清理旧提交可能是一项无望的任务。
真正尝试一下 - 沙盒方面
好的,所以我的回答“放弃,做不到”不是很令人满意。以下是一些可能会从沙箱中清除旧提交的命令:
第 1 步:清除 reflog
reflog 保存指向 HEAD 指向的位置的指针一段时间。 git gc 不会删除 reflog 仍然指向的任何提交,因为如果它们仍然被 reflog 指向,它们实际上并不是松散的对象。
这对我有用:
git reflog expire --expire=all --all
验证:运行 git reflog 并确保它为空。
第 2 步:删除或更新任何指向旧历史记录的标签或分支
任何仍然指向旧历史的标签或分支都将确保历史不能被删除。
git tag -d <tagname>
git branch -D <oldbranchname>
第 3 步:断开或清理所有远程引用
如果你仍然有origin/master 指向一个提交,它不能被垃圾回收。所以要么删除旧遥控器,要么也删除旧遥控器上的所有标签和引用,并在你的沙箱中修剪它们的引用:
git fetch --prune
甚至
git remote remove origin
验证:运行 git log --all 并确保未列出旧提交。
第四步:垃圾回收
现在,您可以运行垃圾收集,并选择使其尽可能彻底。
git gc --prune=now --aggressive
在这个阶段,最后,旧的master 提交不再由git show <old-sha1-of-master> 在我的测试存储库中显示。
考虑试一试 - 服务器端
这就是事情变得更加困难的地方,因为您必须知道您的服务器使用哪些类型的类似 reflog 的东西和备份。但是……
- 推送您想要的新历史记录。
- 确保删除所有旧历史记录:删除或更新任何指向旧提交的标签或分支。
- 拉取请求:据我所知,GitHub 会永久保存任何拉取请求的 HEAD,即使是那些在未合并的情况下关闭的请求,即使分支被删除也是如此。我不知道如何清除旧 PR 保持活跃的提交。
- 问题:我认为问题可以通过它们的 sha1 引用提交,我敢打赌那些也会阻止垃圾收集。所以,彻底扫描你的旧问题,如果你发现有问题的问题,我不确定你应该怎么做。
- 备份:这里我不知道,但我确定有备份,而且他们不会成为您执行此任务的朋友。但也许它们的保留有限,并且会在一段时间后被刷新?
- reflog 和垃圾收集:我们回到第 1 步,因为我不知道如何强制 GitHub 触发 reflog 清理和垃圾收集。如果您有权访问自己的 GitLab 实例,您的 Git 系统管理员也许可以做到。
检查完以上所有内容后,请尝试新的git clone 和git clone --mirror。也可以尝试在浏览器中加载:https://<server>/<user>/<repo>/commit/<sha1>。如果这些都没有显示您想要删除的提交,那么我猜您已经完成了?
实际上,我认为上述测试不会说明您已完成。
服务器端,如果你真的想删除它可能包含的任何秘密的旧历史,我回到我不满意的最初答案:从你的 Git 服务器完全删除 repo(接受所有警告说“这是不可逆的” - 毕竟,这就是你想要的!),然后创建一个新的仓库,其中包含一个空的历史记录、一个空的 PR 列表、空的备份,然后只推送你想要的历史记录。
更新:这个对相关问题的回答 Remove sensitive files and their commits from Git history 表示您可以联系 GitHub 客户支持以获取一个悬空提交,其中包含实际从您的存储库中删除的敏感信息。
思考其他痕迹
一旦您的沙盒和服务器修复完毕,请不要忘记:
- 您的 repo 的任何分支仍将引用旧提交
- 在他们的机器上克隆 repo(或 fork)的任何其他人仍将引用旧提交