【问题标题】:Permanently remove git commit history永久删除 git 提交历史
【发布时间】:2019-11-14 12:23:26
【问题描述】:

我需要永久彻底删除 git 存储库的提交历史记录,并继续使用当前版本的文件。不能以任何方式访问旧版本/提交。我尝试创建一个新的主分支,删除所有其他分支,但是当我在 git bash 中尝试 'git show xxxx' 时,旧提交仍然显示。

我尝试创建一个新的 master 分支,删除所有其他分支,并使用 git gc。

【问题讨论】:

标签: git repository


【解决方案1】:

简短的回答 - 创建一个新的 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 &lt;old-sha1-of-master&gt; 在我的测试存储库中显示。

考虑试一试 - 服务器端

这就是事情变得更加困难的地方,因为您必须知道您的服务器使用哪些类型的类似 reflog 的东西和备份。但是……

  • 推送您想要的新历史记录。
  • 确保删除所有旧历史记录:删除或更新任何指向旧提交的标签或分支。
  • 拉取请求:据我所知,GitHub 会永久保存任何拉取请求的 HEAD,即使是那些在未合并的情况下关闭的请求,即使分支被删除也是如此。我不知道如何清除旧 PR 保持活跃的提交。
  • 问题:我认为问题可以通过它们的 sha1 引用提交,我敢打赌那些也会阻止垃圾收集。所以,彻底扫描你的旧问题,如果你发现有问题的问题,我不确定你应该怎么做。
  • 备份:这里我不知道,但我确定有备份,而且他们不会成为您执行此任务的朋友。但也许它们的保留有限,并且会在一段时间后被刷新?
  • reflog 和垃圾收集:我们回到第 1 步,因为我不知道如何强制 GitHub 触发 reflog 清理和垃圾收集。如果您有权访问自己的 GitLab 实例,您的 Git 系统管理员也许可以做到。

检查完以上所有内容后,请尝试新的git clonegit clone --mirror。也可以尝试在浏览器中加载:https://&lt;server&gt;/&lt;user&gt;/&lt;repo&gt;/commit/&lt;sha1&gt;。如果这些都没有显示您想要删除的提交,那么我猜您已经完成了?

实际上,我认为上述测试不会说明您已完成。 服务器端,如果你真的想删除它可能包含的任何秘密的旧历史,我回到我不满意的最初答案:从你的 Git 服务器完全删除 repo(接受所有警告说“这是不可逆的” - 毕竟,这就是你想要的!),然后创建一个新的仓库,其中包含一个空的历史记录、一个空的 PR 列表、空的备份,然后只推送你想要的历史记录。

更新:这个对相关问题的回答 Remove sensitive files and their commits from Git history 表示您可以联系 GitHub 客户支持以获取一个悬空提交,其中包含实际从您的存储库中删除的敏感信息。

思考其他痕迹

一旦您的沙盒和服务器修复完毕,请不要忘记:

  • 您的 repo 的任何分支仍将引用旧提交
  • 在他们的机器上克隆 repo(或 fork)的任何其他人仍将引用旧提交

【讨论】:

  • 我想我仍然对如何永久删除当前存储库中不需要的提交感兴趣。我知道这很“难”,但我仍然想知道如何,特别是对于仅删除提交子集而不是 all 提交的 OP 用例的更一般情况。在更一般的情况下,重建提交历史减去不需要的提交,使其与旧回购完全相同,包括提交元数据(尽可能多 - 当然,SHA 在某些情况下会改变),也很难。
  • @Juan,你的问题是一个有趣的问题,但我会单独提出一个完全不同的用例。 rebase 和 filter-repo 之类的东西将有助于创建新的 repo,实际上,这个问题已经被问过很多次并且得到了彻底的回答:搜索“从 git 存储库中删除敏感文件”以找到许多结果。鉴于所有关于该主题的文章,我现在将其定性为已解决且相当容易的难题。
  • @Juan 你刚刚说服我我应该尝试给出一个真实的答案。看看,让我知道它是否有帮助。
【解决方案2】:

您可以尝试这种方法。这将永久删除您的提交历史记录。

创建一个新的孤立分支

git checkout --orphan temp_branch

将文件添加到新分支

git add -A
git commit -m "Initial commit"

删除原来的master分支

git branch -D master

重命名孤立分支

git branch -m master

推送更改(如有必要)

git push -f origin master

【讨论】:

  • 这是我尝试过的,但 'git show xxxx'(其中 xxxx 是较旧的提交)仍然会出现旧版本。
  • 这并不像你想象的那么永久:git 将删除的分支保留一段时间,你需要清理 reflog 并运行垃圾收集和刷新备份等。
  • 如果您尝试检查旧的提交(例如,通过 SHA),它仍然可用。即使在git gc --purge=now 之后也是如此。我还没有找到真正删除当前仓库中的提交的方法。甚至克隆也保留了旧的“主人”。
  • @Juan,我完全同意你的看法,因此我残酷地废弃了 repo,废弃了沙盒,并从一个只包含你想要保留的重写历史的新 repo/沙盒重新开始。
  • 啊,是的,按照Randall Munroe 概述的方法。不幸的是,对于 git,它被广泛视为一种可接受的用户体验,而不是工具设计的缺点(“你的意思是应该有更好的方法吗?”)。
【解决方案3】:

正如@torek 指出的那样:

历史不过是提交;提交是历史;所以一个新的空仓库,还没有提交,你提交一个包含所有文件的提交,就是答案。

作为一般警告,这是一种破坏性行为。删除您的历史记录:

rm -rf .git/

一个新的 Git 存储库,添加所有文件,然后提交:

git init
git add .
git commit -m 'Initial commit'

然后推送或强制推送到您保存 repo 的任何位置。

对“不能以任何方式访问旧提交”的既定目标的警告:Git 是一个distributed 版本控制系统。任何拥有代码库副本及其当前历史记录的用户在进行这些更改后仍将拥有它。

【讨论】:

  • 警告:如果原始存储库的文件是存储库的一部分并匹配 .gitignore 规则,则生成的存储库可能没有相同的索引内容。
猜你喜欢
  • 2013-08-03
  • 1970-01-01
  • 2014-11-20
  • 2015-09-02
  • 2013-01-23
  • 2013-05-09
  • 2021-06-19
  • 2014-09-29
  • 2011-10-26
相关资源
最近更新 更多