git fsck:如何--dangling与--unreachable vs. --lost-found有何不同?

时间:2016-04-14 11:29:19

标签: git

我最近found about git fsck,但链接的答案和git help fsck列出了各种替代选项,其中一些似乎与未经训练的眼睛相同。为了能够很好地使用该工具,我很想学习以下命令之间的区别是什么?

  • git fsck --dangling
  • git fsck --unreachable
  • git fsck --lost-found

此外,可以/应该在某些组合中一起使用,还是更好?

(作为旁注,我特别感兴趣的是在git log -G$REGEX $(git fsck --something)中使用它,尽可能地扩大网络,希望能找到我记得在某些时候写过的东西,但我找不到git log -G$REGEX -a。)

1 个答案:

答案 0 :(得分:8)

部分答案位于git glossary,我们find this

  

悬空物品

     

unreachable object即使来自其他无法访问的对象,也不是reachable;悬挂物体没有从object中的任何参考或repository引用它。

(所有链接他们的)。可达性(如果你愿意,可以按照它们的链接)是git提交图中的一个基本概念,我们从一些外部引用开始,如分支或标记名称,以获取图中的起点,然后按照每个节点的出站边找到所有其他节点。

ref有一个词汇表条目,但不供参考,但引用只有regular dictionary meaning。)

我认为这是最好的解释说明。假设我们有一个如下所示的提交DAG:

     C--D--E      <-- branch-a
    /
A--B--F---G--H    <-- branch-b
    \    /
     I--J--K--L   <-- branch-c

节点始终指向左侧,同时也可能指向上方或下方,因此节点E例如指向D,其指向C,指向{ {1}}指向B。 (A无处指出:它是 root 节点。)节点A是合并,并指向GF。此图中的每个节点都是可到达的:我们从所有外部引用(分支)开始并向左走,并发现节点JAE上;节点branch-aABF位于G;等等。 (请注意,节点branch-bA位于每个分支上。节点可以在多个分支上的事实是git有点不寻常的事情之一。例如,在mercurial中,每个节点只在一个分支上。以这种特殊的方式,git的分支是流动的,而mercurial是固定的。)

现在让我们看看如果我们删除其中一个分支标签会发生什么。让我们先剥离B标签。

提交branch-a不再有任何指向它的内容。它是无法访问,并且在git的术语中 - 悬空。提交E仅提交D指向它。由于E无法访问,E也无法访问,但D 悬空,因为D指向EDC处于同一状态。另一方面,节点D可以从Bbranch-bHGFBHGJI来自B关注branch-cLKJI

让我们放回B标签(以便再次branch-aC),然后剥离E。此时branch-cL无法访问。但是,节点K仍然可以访问,从J开始,从branch-bH工作到G。在JK次提交中,只有L悬空,因为L指向L

当使用K时,正如我在其他答案中所述,git fsck通过将其ID或内容写入--lost-found来“复活”(某些)悬挂对象。

(请记住,提交指向以前的提交,而blob只是文本而且从不指向任何内容。当您删除分支时,或者当重新设置并因此放弃的提交链丢失其reflog引用时,您将获得悬空提交,例如,它们非常正常。当你.git/lost-found/文件的内容时,你会得到悬空blob,然后git addgit reset新内容而不先提交,所以摇晃的blob非常正常。git add不保存悬空树或标记对象。通常不应该有悬空树:树对象只能指向更多的树和blob,并且任何悬空树通常应该被提交指向;并且您必须手动使用git fsck,然后永远不要引用树,以获得悬挂的树。我不确定为什么标记对象不会复活,因为不小心删除了带注释标记的外部引用导致悬空的标签对象,能够让它们回来可能会很好。)

摘要:git write-tree检测并恢复悬空或未引用的对象

无法访问的对象是那些无法从外部引用访问的对象(主要是分支和标记名称,但git fsck使用的其他对象如refs/stash)。悬空对象是无法到达的对象的子集,特别是那些没有入站弧的对象(在图论的理论术语中)。

添加git stash标志将保存悬空提交的ID - 这使得这些提交,因此任何其他未引用的提交,所有再次引用 - 并解压缩并使所有悬空blob对象可用。