确定阻止从 git 修剪提交的原因



如何通过以下命令确定是什么阻止了从 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命令不知道该怎么做,就像没有存储一样,但stashref 仍然存在,使最新存储中的任何内容(或从创建该存储的提交访问的完整提交历史记录(在本地保持活动状态[1]。

IMO 这可能被认为是一个错误。 默认情况下,计划的 reflog 到期stash单独保留(用于...井。。。这个原因(。 也许有人认为你特别说要使所有reflogs 过期,但我认为"除stash之外的所有 reflogs "在这种情况下对--all的定义更有用。

好吧,随便。

如果你确定你不在乎藏匿的任何东西

git update-ref -d refs/stash

,然后继续清理。


[1] ">本地活动"是因为至少在默认情况下,stash不是共享的。 克隆存储库或将其引用推送到空的远程数据库可能不会携带有问题的提交。 但是,这取决于 git 将发送最小包的假设 - 并且 AFAIK 它不能保证这样做。 因此,如果您需要取消提交,那么最安全的做法是达到本地不存在的点,然后从该干净的本地存储库重建任何远程(等(。

最新更新