如何通过以下命令确定阻止提交被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阻止了藏匿列表。
如果没有存储并且你已经使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并不保证这样做。因此,如果您需要提交,那么最安全的事情是到达本地不存在的点,然后从该干净的本地存储库重建任何遥控器(等)。