git fsck:怎么--dangling与--unreachable与--lost-found不同? [英] git fsck: how --dangling vs. --unreachable vs. --lost-found differ?

查看:519
本文介绍了git fsck:怎么--dangling与--unreachable与--lost-found不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近找到了 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 。)

解决方案

部分答案是在 GIT中词汇表,我们找到


悬挂对象



不可达对象可达<甚至来自其他不可达的对象;一个悬挂对象没有从对象引用它=https://git-scm.com/docs/gitglossary/#def_repository =nofollow> repository 。

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



(有一个术语表 ref ,但不能作为参考,但参考只是在这里有常规字典 。)



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

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

节点始终指向左边,同时可能指向上或下,所以节点 E 例如指向 D ,它指向 C ,它指向 B ,它指向 A 。 ( A 指向无处:它是一个 root 节点。)节点 G 并指向 F J 。这个图中的每个节点都是可访问的:我们从所有的外部引用(分支)开始,走到左边,发现节点 A E 位于分支-a ;节点 A B F G 位于分支-b ;等等。 (请注意,节点 A B 位于每个分支上 可以在许多分支上是git有点不同寻常的事情之一,例如,在mercurial中,每个节点都只存在于一个分支上,以这种特殊方式,git的分支是流畅的mercurial's是固定的。)



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



提交 E 不再有任何指向它的东西。这是无法访问,并且也是在git的术语中 。提交 D 只提交 E 指向它。由于 E 无法访问,因此 D 也无法访问,但 D 不是 dangling,因为 E 指向 D C 处于与 D 相同的状态。另一方面,节点 B 通过 H 可以从 branch-b / code>至 G F B H G J <> / code>至 I B 通过遵循 L K 来分支 branch-c J I B


$ b $让我们把分支 - 一个标签放回去(这样 C E 可以再次到达),然后剥离 branch-c 。这次 L K 变得无法访问。不过,从分支-b 开始,从 H开始工作,节点 J / code>至 G J 。在 K L 提交中,只有 L 是悬空的,因为 L 指向 K



使用 git fsck ,正如我在其他答案中指出的那样, - lost-found 复活(一些)悬挂对象把它们的ID或内容写入 .git / lost-found /



(记住提交点以前的提交,而blob只是文本,从不指向任何东西,例如,当你删除一个分支时,或者当被重新绑定并因此被放弃的提交链丢失了reflog引用时,你会得到悬而未决的提交,因此它们非常正常。当你 git add 一个文件的内容,然后 git reset 它或 git时获得悬空斑点在不提交的情况下添加新内容,因此悬挂的斑点是非常正常的 git fsck 不会保存悬挂的树或标记对象。悬挂树木:树木物件只能指向到更多的树木和斑点,任何悬挂的树木通常都应该被指出;你必须手动使用 git write-tree ,然后永远不要引用该树,以获得一棵悬挂树。我不确定为什么标记对象不会复活,因为意外删除注释标记的外部引用导致悬挂标记对象,并且可能很容易让这些对象返回。)
$ b

摘要: git fsck 检测并恢复悬挂或未引用的对象



无法访问的对象是那些从外部引用无法访问的对象(主要是分支和标记名称,尽管还有一些像 refs / stash ,由 git stash )。悬空对象是不可达对象的一个​​子集,特别是那些没有入站弧的对象(以图表理论来说)。



添加 - lost-found 标志将保存悬挂提交的ID - 这会使得这些提交以及任何额外的未提交提交(全部被再次引用),并解压缩并提供所有悬空的blob对象。 / p>

I've recently found about git fsck, but the linked answers and git help fsck give a list of various alternative options, some of which seem to mean the same to an untrained eye. To be able to use the tool well, I'd love to learn what's the difference between below commands?

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

Also, can/should they be used together in some combinations, or better not?

(As a side note, I'm particularly interested in using this in git log -G$REGEX $(git fsck --something), to cast the net as wide as possible, in a faint hope of finding something I remember writing at some point, but that I can't find with a git log -G$REGEX -a.)

解决方案

Part of the answer is in the git glossary, where we find this:

dangling object

An unreachable object which is not reachable even from other unreachable objects; a dangling object has no references to it from any reference or object in the repository.

(all links theirs). Reachability (follow their link if you like) is a basic concept in git's commit graph, where we start with some external reference like a branch or tag name to get starting points within the graph, then follow the outbound edges from each node to find all other nodes.

(There's a glossary entry for ref but not for reference, but reference just has its regular dictionary meaning here.)

I think this is best explained illustratively, though. Suppose we have a commit DAG that looks like this:

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

Nodes always point left-ish, while possibly also pointing up or down, so node E, for instance, points back at D, which points at C which points at B which points at A. (A points nowhere: it is a root node.) Node G is a merge and points back at both F and J. Every node in this graph is reachable: we start from all the external references (branches) and walk left-ish and discover that nodes A through E are on branch-a; nodes A, B, and F through G are on branch-b; and so on. (Note that nodes A and B are on every branch. The fact that a node can be on many branches is one of the things that is a bit unusual about git. In mercurial, for instance, each node is only ever on one branch. In this particular way, git's branches are fluid while mercurial's are fixed.)

Now let's see what happens if we erase one of the branch labels. Let's peel off the branch-a label first.

Commit E no longer has anything pointing to it. It is unreachable, and also—in git's term here—dangling. Commit D has only commit E pointing to it. Since E is unreachable, D is also unreachable, but D is not dangling, because E points to D. C is in the same state as D. Node B, on the other hand, is reachable from branch-b by following H to G to F to B, and by following H to G to J to I to B, and from branch-c by following L to K to J to I to B.

Let's put the branch-a label back (so that C through E are reachable again) and peel off branch-c instead. This time L and K become unreachable. Node J remains reachable, though, by starting with branch-b and working from H to G to J. Of the K and L commits, only L is dangling, because L points to K.

When using git fsck, as I noted in that other answer, --lost-found "resurrects" (some) dangling objects by writing their IDs or contents into .git/lost-found/.

(Remember that commits point back to previous commits, while blobs are just text and never point to anything. You get dangling commits when you delete a branch, or when rebased-and-thus-abandoned commit chains lose their reflog reference, for instance, so they are pretty normal. You get dangling blobs when you git add a file's contents, then either git reset it or git add new contents without committing first, so dangling blobs are pretty normal. git fsck does not save dangling tree or tag objects. Normally there should be no dangling trees: tree objects can only point to more trees and to blobs, and any dangling tree should normally have been pointed-to by a commit; and you have to use git write-tree manually, and then never reference the tree, to get a dangling tree. I'm not sure why tag objects are not resurrected, since accidentally deleting the external reference for an annotated tag will result in dangling tag objects, and it might be nice to be able to get those back.)

Summary: git fsck detection and restoration of dangling or unreferenced objects

Unreachable objects are those not reachable from external references (principally branch and tag names, though there are others like refs/stash, used by git stash). Dangling objects are a subset of unreachable objects, specifically those with no inbound arcs (in graph theoretic terms).

Adding the --lost-found flag will save the IDs of dangling commits—which makes these commits, and hence any additional unreferenced commits, all referenced again—and decompress and make available all dangling blob objects.

这篇关于git fsck:怎么--dangling与--unreachable与--lost-found不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆