确定阻止从git删除提交的原因

时间:2018-09-05 16:29:23

标签: git git-commit git-reflog git-gc

如何确定是什么原因阻止了以下命令从git中删除提交?

git reflog expire --expire=now --all

git gc --prune=now

详细信息

我想从克隆中完全删除一个提交(例如,提交哈希XYZ)。如果上面的命令不正确(或者我的以下任何命令/推论不正确),请告诉我。

我知道运行以上修剪后XYZ仍保留在我的克隆中,因为以下内容返回了日志列表:

git log XYZ

我知道XYZ不在任何分支中,因为以下内容什么都不输出:

git branch --contains XYZ

我认为XYZ没有任何隐匿之处,因为以下内容什么都不输出:

git stash list

XYZ实际上是在一个藏身处,但是一个git bug阻止了藏身之列。

1 个答案:

答案 0 :(得分:8)

如果没有存储,并且您已经使reflog过期,则可以合理地假设可以从某些ref到达提交-但并非所有ref都是分支。

您可以尝试以下方法:

git for-each-ref --format='%(refname)' |xargs -I {} git rev-list {} --format="%H {}" |grep ^<hash>

其中<hash>是您要摆脱的提交的ID。在一个简单的测试中,我跑了

git for-each-ref --format='%(refname)' |xargs -I {} git rev-list {} --format="%H {}" |grep ^80c0ab

并得到类似

的输出
80c0ab39850d7b3ef4969ab934d834f22959a317 refs/original/refs/heads/master

告诉我我的目标提交被refs/original下的ref保留-在这种情况下,由git filter-branch创建的pre-rewrite“ backup ref”


更新-根据评论进行的后续操作。

您注意到上面的命令返回refs/stash,但存储列表(按git stash list)为空。

问题是,存储列表使用了操纵严重的引用日志。还有您用来清除reflog的命令

git reflog expire --expire=now --all

将销毁密钥引用日志。因此,现在stash命令不知道该怎么做,就像没有隐藏物一样工作,但是stash引用仍然存在,保留了最近隐藏物中的任何内容(或完整的提交历史可访问)从创建该存储的提交开始)在本地[1]。

可以认为是错误的IMO。默认情况下,预定的reflog有效期将stash保留为空(原因是……这个原因)。也许有人争论说,您专门说过要终止所有 all reflog,但是我认为“ stash之外的所有reflogs”在此是对--all的更有用的定义。实例。

好吧,

如果您确定自己不在乎隐藏的东西

git update-ref -d refs/stash

,然后继续清理。


[1]“在本地激活 ”,因为至少默认情况下未共享stash。克隆存储库或将其引用推入一个空的遥控器中,很可能不会带来有问题的提交。但是,这取决于git将发送最小包的假设-而AFAIK不能保证做到这一点。因此,如果您需要提交已丢失,那么最安全的方法是到达本地不存在的位置,然后从该干净的本地存储库中重建任何远程服务器(等)。

相关问题