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

Sam*_*una 132 git branch git-dangling

我有一个Git存储库,其中有很多提交,没有特定的分支,我可以git show,但是当我尝试列出包含它们的分支时,它没有报告任何内容.

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

$ git fetch origin

$ git fsck --unreachable
$ git fsck
Run Code Online (Sandbox Code Playgroud)

没有输出,没有悬空(对吧?).但提交存在

$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
Run Code Online (Sandbox Code Playgroud)

它不能通过任何分支到达

$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
Run Code Online (Sandbox Code Playgroud)

没有输出.

这个提交的状态究竟是什么?如何列出处于类似状态的所有提交?如何删除那些提交?

tar*_*ius 246

要删除所有悬空提交以及可从reflog中访问的提交,请执行以下操作:

git reflog expire --expire-unreachable=now --all
git gc --prune=now
Run Code Online (Sandbox Code Playgroud)

但请确保这是你想要的.我建议你阅读手册页,但这里是要点:

git gc删除无法访问的对象(提交,树,blob(文件)).如果某个对象不属于某个分支的历史记录,则该对象无法访问.实际上它有点复杂:

git gc 做其他一些事情,但它们在这里并不重要,也没有危险.

不会删除小于两周的无法访问的对象,因此我们使用的--prune=now方法是"删除之前创建的无法访问的对象".

也可以通过reflog访问对象.虽然分支记录了某个项目的历史记录,但是reflog记录了这些分支的历史记录.如果你修改,重置等提交将从分支历史记录中删除,但是如果你意识到你犯了错误,git会保留它们.Reflogs是一种方便的方法,可以找出在分支(或HEAD)上执行的破坏性(和其他)操作,从而更容易撤消破坏性操作.

因此,我们还必须删除reflog以实际删除从分支无法访问的所有内容.我们通过使--allreflogs 到期来实现这一目标.git再次保留了一些reflog以保护用户,所以我们再次告诉它不要这样做:--expire-unreachable=now.

由于我主要使用reflog来从破坏性操作中恢复,我通常会使用--expire=now它来完全消除reflog.

  • 虽然给出的答案可能是正确的,但@ erikb85指出没有关于你被告知要做什么的教育是正确的.跟进RTFM甚至没那么有用.是的,我们都应该阅读所有文档.在某些情况下,进行搜索的人可能没有足够的文档知道发生了什么.所以,关于命令正在做什么的一点教育对于稍后找到这个答案的每个人都会有所帮助. (7认同)
  • `git reflog expire --expire-unreachable = now --all`丢弃你的所有藏匿处! (7认同)
  • 我认为这个答案需要一个明确的警告,最好是在顶部。我的编辑建议被拒绝了,因为我想我应该在评论中向作者建议?请接受此编辑 https://stackoverflow.com/review/suggested-edits/26023983 或以您自己的方式添加警告。它会掉落你所有的藏品也是一件大事! (6认同)

Ari*_*zis 72

没有输出,没有悬空(对吧?)

请注意,从您的reflog引用的提交被认为是可访问的.

这个提交的状态究竟是什么?如何列出具有类似状态的所有提交

通过--no-reflogs说服git fsck向他们展示.

如何删除那些提交?

一旦您的reflog条目过期,那么这些对象也将被清除git gc.

到期由调控gc.pruneexpire,gc.reflogexpiregc.reflogexpireunreachable设置.参看 git help config.

默认值都非常合理.

  • 所以您基本上是说悬空提交的重排会在一段时间后自动删除吗? (2认同)
  • 基本上:是的 - 除了这个问题有点困惑。我是说 *all* reflog 条目会在一段时间后自动删除,但您可以通过配置设置进行更改。并且因为提交仅在没有任何内容指向它时才被称为 [dangling](https://git-scm.com/docs/gitglossary#gitglossary-aiddefdanglingobjectadanglingobject) - 包括引用日志条目 - ,“用于悬空提交的引用日志”不是一回事。它们将是“[unreachable](https://git-scm.com/docs/gitglossary#gitglossary-aiddefunreachableobjectaunreachableobject) 提交的引用”。 (2认同)

jak*_*b.g 18

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

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
Run Code Online (Sandbox Code Playgroud)

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

git tag                             # showed several old tags created before the cleanup
Run Code Online (Sandbox Code Playgroud)

我删除了标签git tag -d <tagname>并重新进行了清理,旧的提交已经消失.


seh*_*ehe 13

git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
Run Code Online (Sandbox Code Playgroud)

可能只是需要

git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042
Run Code Online (Sandbox Code Playgroud)

还报告遥控器的分支机构


Lei*_*hao 8

我不小心遇到了同样的情况,发现我的 stash 包含对无法访问的提交的引用,因此可以从 stash 访问假定的无法访问的提交。

这些是我为了让它真正无法到达而做的事情。

git stash clear
git reflog expire --expire-unreachable=now --all
git fsck --unreachable
git gc --prune=now
Run Code Online (Sandbox Code Playgroud)


And*_*son 6

我有类似的问题.我跑了git branch --contains <commit>,它没有像问题那样返回任何输出.

但即使跑完了之后

git reflog expire --expire-unreachable=now --all
git gc --prune=now
Run Code Online (Sandbox Code Playgroud)

我的提交仍可使用git show <commit>.这是因为其分离/悬挂"分支"中的一个提交被标记.我删除了标签,再次运行上面的命令,我是金色的.git show <commit>返回fatal: bad object <commit>- 正是我需要的.希望这可以帮助那些和我一样困难的人.


Ale*_*lex 5

TL:博士;

可以通过以下方式引用提交:

  • 分店
  • 一个标签(!)
  • 一个藏品(!!)
  • “替换”(!!?)

使用此命令来查找它到底是什么:

git for-each-ref --contains <SHA>
Run Code Online (Sandbox Code Playgroud)

长版

我做了一个filter-repo存储库来清理一些大文件。

显然最终导致了一些悬而未决的提交。我尝试了所有答案,但没有任何效果。

git branch --contains <SHA>           # nothing!
git fsck --unreachable --no-reflogs   # nothing!
Run Code Online (Sandbox Code Playgroud)

然后我发现并删除了一个标签,感谢这个答案

提交仍然不断出现!

所以我最终运行了这个命令:

git for-each-ref --contains <SHA>
Run Code Online (Sandbox Code Playgroud)

它回来了

1b9bf9c63209a4728b2d3dc7946da836dc331bbd commit refs/stash
Run Code Online (Sandbox Code Playgroud)

答对了!

我跑了git stash——但奇怪的是,里面是空的。如果我的存储中没有任何内容,存储如何引用提交?

然而,运行git stash drop几次已经删除了一些基于过时分支的被上帝遗弃的“悬挂”存储,最后我能够进行gc该提交,并且我的存储库立即变小了 15MB。

加长版

(来自另一位用户)我使用了上面的提示,但它返回了

4c79e05b102c673e1f60242c022ff06e017b9a1d commit refs/replace/2acd8f182e14d7d367b3469fd8751f2d9738a884
Run Code Online (Sandbox Code Playgroud)

替换到底是什么?

git replace -h
Run Code Online (Sandbox Code Playgroud)

显示您可以列出删除和编辑这些“替换对象”。诡异的。运行git replace -d 2acd8f会删除提交!