如何通过以下命令确定是什么阻止了从 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 错误阻止了藏匿处被列出。
如果没有存储并且您已经过期了 reflogs,那么假设可以从某个 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
创建的重写前"备份引用"
更新- 根据评论进行一些跟进。
您注意到上面的命令返回refs/stash
,但存储列表(每git stash list
(为空。
问题是,存储列表使用经过大量操作的 reflog。 以及您用于清除 reflogs 的命令
git reflog expire --expire=now --all
将销毁密钥引用日志。 所以现在stash
命令不知道该怎么做,就像没有存储一样,但stash
ref 仍然存在,使最新存储中的任何内容(或从创建该存储的提交访问的完整提交历史记录(在本地保持活动状态[1]。
IMO 这可能被认为是一个错误。 默认情况下,计划的 reflog 到期stash
单独保留(用于...井。。。这个原因(。 也许有人认为你特别说要使所有reflogs 过期,但我认为"除stash
之外的所有 reflogs "在这种情况下对--all
的定义更有用。
好吧,随便。
如果你确定你不在乎藏匿的任何东西
git update-ref -d refs/stash
,然后继续清理。
[1] ">本地活动"是因为至少在默认情况下,stash
不是共享的。 克隆存储库或将其引用推送到空的远程数据库可能不会携带有问题的提交。 但是,这取决于 git 将发送最小包的假设 - 并且 AFAIK 它不能保证这样做。 因此,如果您需要取消提交,那么最安全的做法是达到本地不存在的点,然后从该干净的本地存储库重建任何远程(等(。