我有一个Git存储库,其中包含大量没有特定分支的提交,我可以git show
,但是当我尝试列出包含它们的分支时,它不会报告任何内容。
我认为这是悬挂的提交/树问题(由于-D分支),所以我修剪了回购,但之后我仍然看到相同的行为:
$ git fetch origin
$ git fsck --unreachable
$ git fsck
没有输出,没有悬空(对吧?)。但提交存在
$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
并且无法通过任何分支到达
$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
没有输出。
该提交的状态究竟是什么?如何列出处于类似状态的所有提交?如何删除那些提交?
答案 0 :(得分:232)
要删除所有悬空提交以及可从reflog中访问的提交,请执行以下操作:
git reflog expire --expire-unreachable=now --all
git gc --prune=now
但请确保这是你想要的。我建议你阅读手册页,但这里是要点:
git gc
删除无法访问的对象(提交,树,blob(文件))。如果某个对象不属于某个分支的历史记录,则该对象无法访问。实际上它有点复杂:
git gc
做了其他一些事情,但它们在这里没有关系,也没有危险。
未删除不到两周的无法访问的对象,因此我们使用--prune=now
,这意味着“删除之前创建的无法访问的对象”。
也可以通过reflog访问对象。虽然分支记录了某个项目的历史记录,但是reflog记录了这些分支的历史记录。如果你修改,重置等提交将从分支历史记录中删除,但是如果你意识到你犯了错误,git会保留它们。 Reflogs是一种方便的方法,可以找出在分支(或HEAD)上执行的破坏性(和其他)操作,从而更容易撤消破坏性操作。
因此,我们还必须删除reflog以实际删除从分支无法访问的所有内容。我们通过--all
reflogs到期来实现这一目标。 git再次保留了一些reflog以保护用户,所以我们再次告诉它不要这样做:--expire-unreachable=now
。
由于我主要使用reflog来从破坏性操作中恢复,所以我通常使用--expire=now
来完全消除reflog。
答案 1 :(得分:70)
没有输出,没有悬空(对吧?)
请注意,您的reflog引用的提交被视为可访问。
该提交的状态究竟是什么?如何列出具有类似状态的所有提交
通过--no-reflogs
说服git fsck
向您展示。
如何删除那些提交?
一旦您的reflog条目过期,这些对象也将被git gc
清除。
到期时间由gc.pruneexpire
,gc.reflogexpire
和gc.reflogexpireunreachable
设置规定。参看git help config
默认值都很合理。
答案 2 :(得分:14)
我有同样的问题,仍然遵循这个帖子中的所有建议:
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>
删除了标记并重新进行了清理,旧的提交已经消失。
答案 3 :(得分:13)
git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
可能只需要
git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042
还报告来自遥控器的分支
答案 4 :(得分:5)
我有类似的问题。我跑了git branch --contains <commit>
,它没有像问题那样返回任何输出。
但即使在跑完
之后git reflog expire --expire-unreachable=now --all
git gc --prune=now
我仍然可以使用git show <commit>
访问我的提交。这是因为其分离/悬挂&#34;分支中的一个提交&#34;被标记的。我删除了标签,再次运行上面的命令,我是金色的。 git show <commit>
返回fatal: bad object <commit>
- 正是我所需要的。希望这可以帮助那些和我一样困难的人。
答案 5 :(得分:2)
git gc --prune=<date>
默认修剪两周前的对象。您可以设置更近的日期。但是,创建松散对象的git命令通常会运行git gc --auto(如果它们的数量超过配置变量gc.auto的值,则修剪松散的对象)。
您确定要删除这些提交吗? gc.auto的默认设置将确保松散的对象不占用不合理的内存量,并且将松散的对象存储一段时间通常是个好主意。这样,如果您明天意识到已删除的分支包含您需要的提交,则可以恢复它。
答案 6 :(得分:2)
我意外地遇到了同样的情况,发现我的藏匿条件包含对无法访问的提交的引用,因此可以从存储中找到假定的无法访问的提交。
这些是我为使它真正无法到达所做的。
git stash clear
git reflog expire --expire-unreachable=now --all
git fsck --unreachable
git gc --prune=now