简短的答案 - 创建一个新的存储库
对于这样的彻底清理,您需要创建一个全新的存储库并删除旧的存储库。
我可以给你关于运行垃圾收集、清除引用日志以及找到 Git 暂时存储已删除提交的其他位置的答案,但对于你提出的问题,我强烈推荐一个新的存储库。
特别是,如果您使用 GitHub 或其他一些在线 Git 服务器,完全清理旧提交可能是一项无望的任务。
真正尝试一下 - 沙箱端
好吧,所以我的回答“放弃,做不到”不是很令人满意。以下是一些可能从沙箱中清除旧提交的命令:
第 1 步:清除引用日志
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
or even
git remote remove origin
验证:运行git log --all
并确保旧的提交未列出。
第四步:垃圾收集
现在,您可以运行垃圾收集,并提供使其尽可能彻底的选项。
git gc --prune=now --aggressive
到了这个阶段,终于老了master
提交不再显示为git show <old-sha1-of-master>
在我的测试仓库中。
考虑尝试一下 - 服务器端
这就是事情变得更困难的地方,因为你必须知道你的服务器使用什么类型的类似引用日志的东西和备份。但...
- 推送您想要的新历史。
- 确保删除所有旧历史记录:删除或更新指向旧提交的任何标签或分支。
- 拉取请求:据我所知,GitHub 会永久保存任何拉取请求的 HEAD,即使是在未合并的情况下关闭的拉取请求,即使分支已被删除。我不知道如何清除旧 PR 保留的提交。
- 问题:我认为问题可以通过 sha1 引用提交,我敢打赌这些也会阻止垃圾收集。所以,彻底扫描你的旧问题,如果你发现有问题的问题,我不知道你应该做什么。
- 备份:我不知道,但我确信有备份,而且它们不会成为您完成此任务的朋友。但也许它们的保留时间有限,一段时间后就会被冲掉?
- reflog 和垃圾收集:我们回到步骤 1,因为我不知道如何强制 GitHub 触发 reflog 清理和垃圾收集。如果您有权访问自己的 GitLab 实例,您的 Git 系统管理员也许能够做到这一点。
检查完以上所有内容后,尝试新的git clone
and git clone --mirror
。另请尝试在浏览器中加载此内容:https://<server>/<user>/<repo>/commit/<sha1>
。如果这些都没有显示您想要删除的提交,那么我想您已经完成了?
实际上,我不认为上述测试会告诉你已经完成了。
服务器端,如果你真的想删除旧历史记录及其可能包含的任何秘密,我会回到我不满意的最初答案:从 Git 服务器中完全删除存储库(接受所有“这是不可逆的”警告) - 毕竟,这就是您想要的!),并创建一个具有空历史记录、空 PR 列表、空备份的新存储库,然后仅推送您想要的历史记录。
Update:这个相关问题的答案,从 Git 历史记录中删除敏感文件及其提交 https://stackoverflow.com/a/32840254/3216427表示您可以联系 GitHub 客户支持来获取悬空提交,其中敏感信息实际上已从您的存储库中删除。
思考其他痕迹
一旦你的沙箱和服务器被修复,不要忘记:
- 您的存储库的任何分支仍将引用旧的提交
- 在其计算机上克隆存储库(或分支)的其他任何人仍将引用旧提交