如何确定是什么原因阻止了以下命令从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阻止了藏身之列。
答案 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不能保证做到这一点。因此,如果您需要提交已丢失,那么最安全的方法是到达本地不存在的位置,然后从该干净的本地存储库中重建任何远程服务器(等)。