列出并删除没有分支的Git提交(dangling?)

我有一个Git仓库,有很多提交没有特定的分支,我可以git show他们,但是当我尝试列出包含他们的分支,它没有报告什么。

我认为这是悬而未决的提交/树问题(由于-D分支),所以我修剪了回购,但是在那之后我仍然看到相同的行为:

 $ git fetch origin $ git fsck --unreachable $ git fsck 

没有输出,没有什么悬挂(对吧?)。 但提交存在

 $ git show 793db7f272ba4bbdd1e32f14410a52a412667042 commit 793db7f272ba4bbdd1e32f14410a52a412667042 Author: ... 

并且它不能通过任何分支到达

 $ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042 

没有输出。

那个提交的状态到底是什么? 如何列出所有类似状态的提交? 我怎样才能删除这样的提交?

没有输出,没有什么悬挂(对吧?)

请注意,从reflog引用的提交被视为可访问。

那个提交的状态到底是什么? 如何列出所有类似状态的提交

通过--no-reflogs说服git fsck向他们展示给你。

我怎样才能删除这样的提交?

一旦你的reflog条目到期,这些对象也将被git gc清理。

有效期限由gc.pruneexpiregc.reflogexpiregc.reflogexpireunreachable设置规定。 参看 git help config

默认值都很合理。

要删除所有悬而未决的提交和可从reflogs中获得的提交,请执行以下操作:

 git reflog expire --expire-unreachable=now --all git gc --prune=now 

但要确定这是你想要的。 我build议你阅读手册页,但这里是要点:

git gc删除无法访问的对象(提交,树,斑点(文件))。 如果某个对象不是某个分支的历史logging的一部分,则该对象无法访问。 其实它有点复杂:

git gc做了一些其他的事情,但他们在这里不相关,并不危险。

小于两周的无法访问的对象不会被删除,所以我们使用--prune=now ,这意味着“删除现在创build的不可访问的对象”。

对象也可以通过reflog访问。 在分支logging某个项目的历史logging时,logginglogging这些分支的历史logging。 如果你修改,重置等提交从分支历史中删除,但git让他们在附近,如果你意识到你犯了一个错误。 Reflogs是查找分支(或HEAD)上执行的破坏性(和其他)操作的便捷方式,使撤销破坏性操作变得更容易。

所以我们也必须删除reflog,以便实际删除从分支中不可访问的所有内容。 我们这样做是因为过期 – 所有reflogs。 再次git保留一些reflogs来保护用户,所以我们再次要告诉它不要这样做:– --expire-unreachable=now

由于我主要使用reflog来从破坏性操作中恢复,所以我通常使用--expire=now来完成对reflog的调用。

 git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042 

可能只是需要

 git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042 

也从远程报告分支

我有同样的问题,仍然遵循这个线程中的所有build议:

 git reflog expire --expire-unreachable=now --all git gc --prune=now git fsck --unreachable --no-reflogs # no output git branch -a --contains <commit> # no output git show <commit> # still shows up 

如果它不是一个reflog而不是一个分支,它必须是一个标签

 git tag # showed several old tags created before the cleanup 

我用git tag -d <tagname>去掉标签,重新清理,旧的提交不见了。

我有一个类似的问题。 我跑了git branch --contains <commit> ,它没有返回任何输出,就像在问题中一样。

但即使跑完了

 git reflog expire --expire-unreachable=now --all git gc --prune=now 

我的提交仍然可以使用git show <commit> 。 这是因为其分离/悬挂的“分支”中的一个提交被标记。 我删除了标签,再次运行上述命令,而我是金黄色的。 git show <commit>返回fatal: bad object <commit> – 正是我所需要的。 希望这有助于像我一样卡住的其他人。

git gc --prune=<date>默认修剪两周前的对象。 你可以设置一个更近的date。 但是,创build松散对象的git命令通常会运行git gc –auto(如果它们的数量超过configurationvariablesgc.auto的值,则会修剪松散的对象)。

你确定要删除这些提交吗? gc.auto的默认设置将确保松散的对象不占用不合理的内存量,并且将松散的对象存储一段时间通常是一个好主意。 这样,如果你明天意识到你的被删除的分支包含你需要的提交,你可以恢复它。

我不小心碰到了相同的情况,发现我的stash中包含对不可达提交的引用,因此推定的不可达提交可以从stash到达。

这些就是我所做的,使它真正无法到达。

 git stash clear git reflog expire --expire-unreachable=now --all git fsck --unreachable git gc --prune=now