我最近发现了git fsck,但链接的答案并git help fsck列出了各种替代选项,其中一些似乎与未经训练的眼睛相同.为了能够很好地使用该工具,我想了解以下命令之间的区别是什么?
git fsck --danglinggit fsck --unreachablegit fsck --lost-found此外,可以/应该在某些组合中一起使用,还是更好?
(作为旁注,我特别感兴趣的是使用它git log -G$REGEX $(git fsck --something),尽可能地扩大网络,我希望找到一些我记得在某些时候写过的东西,但是我找不到它git log -G$REGEX -a.)
悬空物体
(所有链接他们的).可达性(如果你愿意,可以按照它们的链接)是git提交图中的一个基本概念,我们从一些外部引用开始,如分支或标记名称,以获取图中的起点,然后按照每个节点的出站边找到所有其他节点.
(有一个ref的词汇表条目,但不供参考,但参考只是在这里有它的常规字典.)
不过,我认为这是最好的说明.假设我们有一个如下所示的提交DAG:
C--D--E <-- branch-a
/
A--B--F---G--H <-- branch-b
\ /
I--J--K--L <-- branch-c
Run Code Online (Sandbox Code Playgroud)
节点始终指向left-ish,同时可能也指向上或下,因此节点E例如指向返回D,指向C哪个点处的B点A.(A点无处:它是一个根节点.)节点G是合并并在两个点背F和J.在该图中的每个节点可到达:从我们所有的外部引用(分公司)开始,然后步行离开十岁上下,并发现节点A通过E上branch-a; 节点A,B和F通过G上branch-b; 等等.(注意节点A并且B在每个分支上.节点可以在许多分支上的事实是关于git有点不寻常的事情.例如,在mercurial中,每个节点只在一个分支上.特别的方式,git的分支是流动的,而mercurial是固定的.)
现在让我们看看如果我们删除其中一个分支标签会发生什么.让我们branch-a先剥掉标签.
提交E不再有任何指向它的东西.这是不可达,而且,在Git的任期这里- 晃来晃去.Commit D只提交E指向它.由于E无法访问,D也无法访问,但D在不晃来晃去,因为E点D. C与...处于同一状态D.节点B,而另一方面,是从可到达的branch-b通过以下H来G给F到B,并且由以下H给G到J对I向B,并从branch-c由以下L给K到J给I到B.
让我们把branch-a标签放回去(以便C通过E再次到达)然后剥离branch-c.这一次L和K不可达.J但是,节点仍然可以通过开始branch-b和工作H来G访问J.的K和L提交,仅L是晃来晃去,因为L点K.
git fsck正如我在其他答案中所提到的,当使用时,--lost-found通过将其ID或内容写入来"复活"(某些)悬空物体.git/lost-found/.
(请记住,提交指向以前的提交,而blob只是文本,并且从不指向任何内容.当您删除分支时,或者当重新设置并因此放弃的提交链丢失其reflog引用时,您将获得悬空提交,例如,所以它们很正常.当你git add文件的内容时,你会得到悬空的blob ,然后是git reset它或者git add没有先提交的新内容,所以摇晃的blob非常正常. git fsck不保存悬空树或标记对象.通常应该没有悬空的树:树对象只能指向更多的树和blob,并且任何悬空树通常都应该由提交指向;并且你必须git write-tree手动使用,然后不要引用树,以获得悬空树.我是不确定为什么标签对象没有复活,因为不小心删除了带注释标签的外部引用会导致悬挂标签对象,并且能够让它们恢复原状可能会很好.)
git fsck检测和恢复悬空或未引用的对象无法访问的对象是那些无法从外部引用访问的对象(主要是分支和标记名称,尽管还有其他类似的refs/stash,使用过的git stash).悬空对象是无法到达的对象的子集,特别是那些没有入站弧的对象(以图形理论术语表示).
添加--lost-found标志将保存悬空提交的ID - 这使得这些提交,因此任何其他未引用的提交,所有再次引用 - 并解压缩并使所有悬空blob对象可用.