从远程 Git 存储库中删除所有历史记录、提交和分支?

21

我已经阅读并尝试了许多Git命令推荐和讨论,这已经持续了几天了。看起来真的没有一种简单而全面的方式可以使远程Git存储库完全为空——没有分支、没有引用、没有对象、没有文件、没有任何内容

是的,我知道一个人可以删除并重新创建存储库——如果有这种权限在源头上(我没有这个),但这不是重点。怎样才能做到呢?哪些Git命令的组合将实际完成这个操作,使存储库处于原始状态,准备接收我们想要推入其中的任何内容,并且尽可能地小(或者是一个未修改过的存储库的最小大小)

不要告诉我这不应该这样做,或者我们必须通知所有用户等等。我知道这些。 我只是想从头开始


你能否只是删除并重新创建它? - Thomas
1
https://dev59.com/tG435IYBdhLWcg3wiggk - Alex
1
@Stabledog,你能从远程仓库删除分支吗?你用什么命令来克隆它?你使用的是哪些确切的命令来强制推送。再次请提供详细信息! - user456814
是的,我可以删除分支,我可以将主分支重置为第一个提交并推送它。但显然仍然存在悬空引用,这些引用保留了对象,因此仓库的大小不会缩小,历史记录也不会消失等等。@Alex:我尝试了这种方法,但它没有起作用。我仍然能够在历史记录中找到标签,并跟踪它们所代表的树等。我有一种感觉,真的没有人知道如何做到这一点——谁实际上已经做到了,因此情绪沮丧。抱歉。 - Stabledog
1
@Stabledog 悬空提交可以被垃圾回收,但如果您无法控制远程仓库,则垃圾回收可能由远程主机处理。此外,您可以删除标签。您如何在历史记录中“查找标签”?您使用了哪些命令?此外,当您从远程克隆时,我怀疑悬空提交不会被获取,应该获取的只有那些从引用/分支可达的提交。另外,您是否收到任何错误消息 - user456814
显示剩余5条评论
2个回答

34
你可以尝试使用--mirror 参数(重点标注是我的建议)来推送一个空的本地仓库。
--mirror

Instead of naming each ref to push, specifies that all refs under refs/ (which includes but is not limited to refs/heads/, refs/remotes/, and refs/tags/) be mirrored to the remote repository. Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end. This is the default if the configuration option remote.<remote>.mirror is set.

如果您的存储库在GitHub上,当尝试推送时,如果将master设置为默认分支,则会出现此错误:
$ mkdir practice; cd practice;
$ git init; git remote add origin git@github.com:user/practice.git;

$ git push origin --mirror
remote: error: refusing to delete the current branch: refs/heads/master
To git@github.com:user/practice.git
 ! [remote rejected] master (deletion of the current branch prohibited)
error: failed to push some refs to 'git@github.com:user/practice.git'

我解决了这个问题,通过先进行初始提交然后推送。

强制警告:当然,这将完全清除您的远程存储库中所有历史记录和提交——所有引用、所有分支、所有标签等。请确保这确实是您想要做的事情。当然,在执行此操作之前,您可以始终对远程存储库进行备份克隆,以防您想出于任何原因保留它。

还要注意,没有一个提交将立即被删除。它们只会成为悬空提交,这意味着它们无法从分支中访问。最终,它们将被Git repos垃圾回收,但如果您可以访问您的远程存储库,则可以使用git gc手动开始垃圾回收。


1
太棒了...这就解决了问题,而且具有正确解决方案的优雅简洁!(我还不得不添加一个简单的提交)。谢谢! - Stabledog
这是对(https://dev59.com/jWMl5IYBdhLWcg3wzpnV#18116141)的跟进。我在本地进行了实验,发现使用--mirror推送实际上并不会缩小原始存储库:磁盘使用量相同,但历史记录不再可访问,当重新克隆该存储库时,克隆体积很小。因此,该效果产生了我需要的实际效果...我并不真正关心一个否则无法访问的源正在消耗比它应该更多的磁盘空间。但这仍然是一个令人惊讶的结果。 - Stabledog
1
@Stabledog 无论是谁管理远程仓库(例如您的仓库托管提供商),最终都会运行git gc(垃圾回收),这将删除所有悬空提交(即不可从分支/引用访问的提交),因此远程磁盘使用量最终会缩小到与本地克隆相似的大小。这是我在此评论中提到的。 - user456814
1
是的,抱歉...这个问题让我失去了阅读能力,太沮丧了。现在我正在康复中。 - Stabledog
这似乎是一个错误的答案,因为这样做后将在历史记录中产生一个实际的提交。有没有一种方法可以真正地没有提交呢?(所谓没有提交就是服务器端没有剩余提交,因此由于单个不匹配的初始提交而被拒绝推送历史记录) - E. T.
哇 - 这个方法起了作用,其他的方法都没有帮助。重置等操作都是无意义的。这个解决方案可以快速将所有标签从远程移除。 - dorsz

-1

你不能这样做。最好的方法是删除所有引用,并希望服务器运行git gc并具有设置以清除没有任何引用的对象。这取决于服务器配置。

通常需要14天才能通过git gc删除对象。但是,如果您尝试克隆存储库,则不会克隆这些对象。

您已经得到了如何执行“黑客”以删除所有引用的好答案。它可以工作,您的存储库将对您显示为“新鲜”。但是它并不是。


实际上这是可以做到的,而且结果比我尝试根据提示进行的所有复杂过程都要简单得多:我们只需要创建一个空仓库,指定源,然后执行“git push --mirror”命令。嘭……远程就成为了一个新的、空的、微小的仓库。 - Stabledog
1
就像我之前所说的,它不是空的,里面仍然有对象。但是当你克隆那个仓库时,你只会得到那些具有引用的对象。因此,你对仓库的克隆不包含任何旧对象,但在服务器端它们仍然存在。 - iveqy
@Stabledog git gc --aggressive 可能是不必要的。此外,默认情况下,git gc 仅会清除两周以上的悬空提交。如果您想进行更多的垃圾回收,可以传递 --prune=now 来清除所有内容,请参见 git gcgc.pruneexpire - user456814
1
好的。作为Subversion专家,某些git概念似乎很奇怪...比如说一个人会有参考超时与垃圾回收相互关联的概念。这动摇了整个“源代码控制是混凝土和钢铁”的美学! - Stabledog
是的,好的。这些陌生的概念开始渐渐明了起来。感谢你的帮助和耐心!:) - Stabledog
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接