git - git fsck 结合 --lost-found 和 --unreachable
问题描述
我发现了很多关于 的有趣帖子git fsck
,所以我想对它们进行一些实验。首先,我在这个问题之前阅读的所有资料:
我从这个 repo 开始:
* 9c7d1ea (HEAD -> test) f
* cd28884 e
| * 7b7bac0 (master) d
| * cab074f c
|/
* d35af2c b
| * f907f39 r # unreferenced commit
|/
* 81d6675 a
从r
分离HEAD
的a
. 然后我想重新定位master
,test
但我有一些未分级的更改,所以我做了:
git rebase --autostash test
获得(我没有显示r
,但它仍然存在):
* caee68c (HEAD -> master) d
* 2e1cb7d c
* 9c7d1ea (test) f
* cd28884 e
* d35af2c b
* 81d6675 a
接下来我运行:
$ git fsck
#...
dangling commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
#...
$ git fsck --unreachable
#...
unreachable commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
unreachable commit d8bb677ce0f6602f4ccad46123ee50f2bf6b5819 # stash index
#...
$ git fsck --lost-found
#...
dangling commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
dangling commit f907f39d41763accf6d64f4c736642c0120d5ae2 # r
#...
第一个问题
为什么只有--lost-found
版本返回r
提交?为什么不可达之间显示c
和d
之前?rebase
我以为我理解阅读链接问题的区别,但我显然遗漏了一些东西。我仍然有完整的 reflog,但我猜你不需要它,因为所有提交(除了与 相关的stash
)都被引用了。
我知道我应该创建另一个帖子,但第二个问题是部分相关的。我出于好奇尝试了:
$ git fsck --lost-found --unreachable
#...
unreachable commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
unreachable commit d8bb677ce0f6602f4ccad46123ee50f2bf6b5819 # stash index
unreachable commit f907f39d41763accf6d64f4c736642c0120d5ae2 # r
unreachable commit 7b7bac0608936a0bcc29267f68091de3466de1cf # c before rebase
unreachable commit cab074f2c9d63919c3fa59a2dd63ec874b0f0891 # d before rebase
#...
第二个问题
结合这两个选项,我得到了所有无法访问的提交(而不仅仅是 and 的--lost-found
并集--unreachable
),这是非常出乎意料的。为什么它会这样?
解决方案
其中一些确实令人费解,并且似乎没有正确记录,但快速浏览一下builtin/fsck.c表明使用--lost-found
:
- 打开
--full
; - 打开
--no-reflogs
。
第 1 项并不是特别有趣,因为--full
无论如何现在默认情况下都是打开的,但文档确实应该指出--lost-found
禁用--no-full
。第 2 项解释了其余的大部分内容;我对最后一部分有一个猜测[编辑:其余部分]。
请注意,当您运行时:
git checkout master && git rebase --autostash test
这使得 Git run git stash push
,它创建了一个包含两个新提交的新存储。然后 Git 像往常一样进行变基,将原始输出中可见的cab074f
和提交复制到第二个输出中可见的新和提交。7b7bac0
git log --all --decorate --oneline --graph
2e1cb7d
caee68c
为什么只有
--lost-found
版本返回r
提交?为什么不可达之间显示变基之前的c
和?d
据推测,该提交仍在HEAD
reflog 中。这使得它可以从引用中访问——但由于--lost-found
蕴含--no-reflogs
,这一次它变得不可访问。和 的原件也是如此c
:d
它们可以通过多个 reflog 条目访问,来自HEAD
's 的 reflog 和master
's。
结合这两个选项,我得到了所有无法访问的提交(而不仅仅是 and 的
--lost-found
并集--unreachable
),这是非常出乎意料的。为什么它会这样?
这更令人费解。[编辑:解决;见下文。]让我们按照您的git fsck
命令顺序运行它们:
fsck 1 和 fsck 2:两者都发现了 autostash 提交。那是因为
git stash push
将原始文件复制refs/stash
到了 stash reflog,所以这refs/stash
可能指向 autostashw
(工作树)提交。然后隐含的git stash apply && git stash drop
(git stash pop
) 应用存储并将其删除,将stash@{1}
条目移回refs/stash
并删除存储引用日志。所以w
来自 autostash 的提交确实是“悬空的”。它不在,refs/stash
甚至不在stash
reflog 中,因为git stash
(ab) 将此 reflog 用作“存储堆栈”。但是,它确实指向i
来自 autostash 的提交。然后,第一个 fsck 打印
6387b70fe14f1ecb90e650faba5270128694613d
并将其称为“悬空”。那w
就是被丢弃的提交。第二个fsck
,with--unreachable
,添加d8bb677ce0f6602f4ccad46123ee50f2bf6b5819
:被删除的相应i
提交。fsck 3:
r
和 rebased 提交仍然不可见,git fsck --unreachable
因为它们是从 reflogs 中引用的。但是现在,有了--lost-found
, fsck 不会查看 reflog。我们应该期望看到 autostashw
提交、r
提交和 pre-rebased
都悬空。[编辑:根据评论,这是错误的:w
链接回i
和d
,所以这将隐藏d
。]我们实际上看到了
w
andr
提交,但没有看到。d
commit为什么不? 这是我的猜测,但很容易测试您是否仍有设置:当您git rebase
成功使用时,Git 会创建或更新伪引用,以在 rebase 完成之前ORIG_HEAD
记住提示提交的哈希 ID 。请注意,在成功移动一个之后,以及在任何其他可能将分支名称移动一段距离的操作(例如,快进合并)之后,这个相同的名称用于记住 ref 的先前值。git reset
很明显,git fsck
必须将所有各种*_HEAD
伪引用作为可达性的起点。这也没有记录在案(甚至不完全清楚这是故意的——参考代码最近进行了一些相当繁重的修改,以支持替代参考后端)。fsck 4,就在你的第二个问题部分之前:
要么[编辑] 由于--unreachable
关闭伪引用包含,或者——我认为这更有可能——你在这两者之间做了一些事情,ORIG_HEAD
这样它就不再选择原始的预变基d
提交。--unreachable
列出了所有无法访问的提交,因此d
可以从自动存储提交间接访问的事实w
是无关紧要的,我们可以看到所有内容。
如果您想报告一个 Git 文档错误,而 fsck 文档没有指出这--lost-found
意味着--no-reflogs
,您应该这样做。
推荐阅读
- python - 如何使用python确定两个图中的峰值并仅绘制两个图中的峰值图
- node.js - 如何在 docker 容器中配置节点应用程序和 haProxy?
- postgresql - 根据条件拆分为多列
- java - Spring Boot JAR 应用程序未从资源文件夹中读取 chromedriver.exe
- hyper-v - Enable-PSRemoting (Set-WSManQuickConfig) 和 HyperV 适配器
- java - Spring Kafka:记录侦听器与批处理侦听器
- image-processing - C++ 从位图中获取图像缓冲区
- c - C 库应该如何管理错误?
- regex - 正则表达式:如果在路径中找到特定的字符串模式,则重新调整 url 路径
- flutter - 如何从 Sub Collection Flutter 中获取数据?