列出并删除没有分支的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.pruneexpire
, gc.reflogexpire
和gc.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