确定是什么阻止了从 git 中删除提交
Determine what prevents a commit from being pruned from git
我如何确定是什么阻止了通过以下命令从 git 中删除提交?
git reflog expire --expire=now --all
git gc --prune=now
详情
我想从我的克隆中完全删除一个提交(例如,使用提交哈希 XYZ
)。如果以上不是正确的命令(或者如果我的以下任何命令/推论不正确),请告诉我。
我知道在 运行 上述修剪后 XYZ
仍保留在我的克隆中,因为以下 returns 日志列表:
git log XYZ
我知道 XYZ
不在任何分支中,因为以下没有任何输出:
git branch --contains XYZ
我认为 XYZ
不在任何藏匿处,因为以下内容没有任何输出:
git stash list
XYZ
,然而,实际上是在一个藏匿处,但是一个 git 错误阻止了藏匿处被列出。
如果没有存储并且您已经使引用日志过期,那么假设可以从某些引用访问提交似乎是合理的——但并非所有引用都是 b运行ches。
你可以试试这个:
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
下的引用保持活动状态 - 在本例中是 git filter-branch
创建的预重写 "backup ref"
更新 - 根据评论进行一些跟进。
您注意到上面的命令 returns refs/stash
,但是隐藏列表(根据 git stash list
)是空的。
事实是,隐藏列表使用了重度操纵的 reflog。还有你用来清除 reflogs 的命令
git reflog expire --expire=now --all
将破坏密钥刷新。所以现在 stash
命令不知道该做什么并且表现得好像没有存储,但是 stash
ref 仍然存在,保留了最新存储的任何内容(或可访问的完整提交历史记录)来自创建该存储的提交)在本地 [1].
在我看来,这可能是一个错误。默认情况下,计划的 reflog 过期只留下 stash
(因为......好吧......这个原因)。也许争论的焦点是你明确表示过期 all reflogs,但我认为 "all reflogs except the stash
" 在这种情况下将是 --all
的更有用的定义。
好吧,随便吧。
如果你确定你不关心藏匿的东西
git update-ref -d refs/stash
然后继续清理。
[1] "alive locally" 因为,至少在默认情况下,stash
是不共享的。克隆 repo,或将其 refs 推入一个空的远程,很可能不会携带有问题的提交。然而,这取决于 git 将发送一个最小包的假设——据我所知,这并不是 gua运行 应该做的。因此,如果您需要 提交消失,那么最安全的做法是到达本地不存在的位置,然后从该干净的本地 repo 重建任何遥控器(等)。
我如何确定是什么阻止了通过以下命令从 git 中删除提交?
git reflog expire --expire=now --all
git gc --prune=now
详情
我想从我的克隆中完全删除一个提交(例如,使用提交哈希 XYZ
)。如果以上不是正确的命令(或者如果我的以下任何命令/推论不正确),请告诉我。
我知道在 运行 上述修剪后 XYZ
仍保留在我的克隆中,因为以下 returns 日志列表:
git log XYZ
我知道 XYZ
不在任何分支中,因为以下没有任何输出:
git branch --contains XYZ
我认为 XYZ
不在任何藏匿处,因为以下内容没有任何输出:
git stash list
XYZ
,然而,实际上是在一个藏匿处,但是一个 git 错误阻止了藏匿处被列出。
如果没有存储并且您已经使引用日志过期,那么假设可以从某些引用访问提交似乎是合理的——但并非所有引用都是 b运行ches。
你可以试试这个:
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
下的引用保持活动状态 - 在本例中是 git filter-branch
更新 - 根据评论进行一些跟进。
您注意到上面的命令 returns refs/stash
,但是隐藏列表(根据 git stash list
)是空的。
事实是,隐藏列表使用了重度操纵的 reflog。还有你用来清除 reflogs 的命令
git reflog expire --expire=now --all
将破坏密钥刷新。所以现在 stash
命令不知道该做什么并且表现得好像没有存储,但是 stash
ref 仍然存在,保留了最新存储的任何内容(或可访问的完整提交历史记录)来自创建该存储的提交)在本地 [1].
在我看来,这可能是一个错误。默认情况下,计划的 reflog 过期只留下 stash
(因为......好吧......这个原因)。也许争论的焦点是你明确表示过期 all reflogs,但我认为 "all reflogs except the stash
" 在这种情况下将是 --all
的更有用的定义。
好吧,随便吧。
如果你确定你不关心藏匿的东西
git update-ref -d refs/stash
然后继续清理。
[1] "alive locally" 因为,至少在默认情况下,stash
是不共享的。克隆 repo,或将其 refs 推入一个空的远程,很可能不会携带有问题的提交。然而,这取决于 git 将发送一个最小包的假设——据我所知,这并不是 gua运行 应该做的。因此,如果您需要 提交消失,那么最安全的做法是到达本地不存在的位置,然后从该干净的本地 repo 重建任何遥控器(等)。