确定阻止提交从git中删除的内容

问题描述 投票:3回答:1

如何通过以下命令确定阻止提交被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阻止了藏匿列表。

git git-commit git-reflog git-gc
1个回答
8
投票

如果没有存储并且你已经使reflogs过期,那么假设可以从某些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。以及用于清除reflog的命令

git reflog expire --expire=now --all

将摧毁关键的reflog。所以现在stash命令不知道该怎么做,并且表现得像没有stashes,但是stash ref仍然存在,保留了最近的存储中的任何东西(或者从存储的提交可以获得的完整提交历史)在当地活着[1]。

IMO可能被认为是一个错误。默认情况下,预定的reflog到期会单独留下stash(因为......嗯......这个原因)。也许这个论点认为你明确表示要使所有的reflogs到期,但我认为“除了stash之外的所有reflogs”在这个例子中对--all来说是一个更有用的定义。

好吧,无论如何。

如果你确定你不关心被藏起来的东西

git update-ref -d refs/stash

然后恢复你的清理工作。


[1]“本地活着”因为,至少在默认情况下,stash不会被共享。克隆存储库或将其refs推入空的遥控器可能不会带来违规提交。然而,这取决于git将发送最小包的假设 - 而AFAIK并不保证这样做。因此,如果您需要提交,那么最安全的事情是到达本地不存在的点,然后从该干净的本地存储库重建任何遥控器(等)。

© www.soinside.com 2019 - 2024. All rights reserved.