从崩溃中恢复git

时间:2017-02-24 15:55:52

标签: git github gerrit

我的git服务器崩溃,现在我的回购处于不一致的状态。 RUnning git fsck --full显示以下输出。

error: refs/heads/data-8989 does not point to a valid object! dangling commit b8cfe9e3e58c64411795cf9676ff228b12607e95 dangling commit a817ef9d4a423b6efee62b9af16979e6433943b1 dangling commit 4f9d59b0dcfa34dd9592474fe487f568a20b07ea dangling commit 22af4033b6224d2b075db7138801fd7b8244eb37 missing commit d2b142ca7e165429a47b6e303fad349f3ae51cc7

有没有办法恢复这个?

2 个答案:

答案 0 :(得分:0)

来自git-fsck documentation

  

git-fsck测试SHA-1和一般对象的健全性,并且它已经完整   跟踪产生的可达性和其他一切。它打印   它找到的任何腐败(丢失或坏的对象),如果你使用   --unreachable标志它也会打印出存在的对象但是   无法从任何指定的头节点(或   默认设置,如上所述。)

     

您必须在备份或其他档案中找到任何损坏的对象   (即,您可以删除它们并与其他网站进行rsync   希望别人有你腐败的对象。

您需要备份或克隆本地存储库。

答案 1 :(得分:0)

“悬挂”提交即使在健康的存储库中也是正常的:它们是一组无法访问的提交的提示,通常来自git rebasegit commit --amend(故意放弃一个或多个) “old”承诺支持“新的和改进的”副本或副本)。但是,在一个有缺陷的存储库中,这些悬空提交中的一些 - 以及其他可以“在它们后面”提交的提交 - 可能是您可以并且想要恢复的。

缺少提交是一个更严重的问题。鉴于只显示了一个这样的引用,分支data-8989无效,可能缺少的提交是{{1}的提示提交的提交。 }。在这种情况下,悬挂提交中的一个(但只有一个)可能会在该链中进一步提交。

直观地表示,正常的图形可能如下所示:

data-8989

其中每个 o--o--o <-- feature / \ ...--o--o--o------o--*--o <-- branch1 \ o--o-----------o <-- branch2 \ o----o--o <-- branch3 代表一个提交。每次提交“指回”到其直接父提交,或者,在合并提交(标记为o)的情况下,指向两个父项,即合并的两个提交。名称*feature等等是Git查找分支的提示的方式。一旦Git提交了这个提示,Git就会使用内部向后箭头来查找父提交,然后使用父对象查找祖父提交,依此类推。

运行branch1只需确保以这种方式找到存储库中的所有提交(到达)。某些是正常的。例如,我们可能会认为git fsck很糟糕,只是删除标签,即删除分支。现在放弃了仅从branch3可以 的三个提交。 提示是“悬空”而另外两个,Git没有提及。

请注意,分支提示不需要作为链的末尾。它只是处理就像它是最后一个,每当你从那个提示开始。例如,branch3就属于这种情况。 Git不能 - 可以不能,至少不容易 - 沿着链看前进,因为连接提交的所有Git内部箭头只向向后 ,从孩子到父母。 (这是feature相对较慢的主要原因:它必须完成大量工作,实际上是反转内部箭头。)从git fsck的尖端开始很容易,向后工作,找到合并,回溯工作,并发现你有branch1的提示提交。另一方面很难走。因此,Git通常会倒退。

现在,当存储库被损坏时,我们可能会丢失标签本身,或者我们可能会丢失一些提交或其他内部对象(总共有四种对象类型,但我们将专注于承诺在这里)。 最有可能损坏的是最近创建的(对象)或更新的(对于标签)。这是因为,一旦创建,任何对象都不会被更改 1 计算机崩溃往往会丢失或损坏最近触摸的文件,而不是旧的活动较少的文件。

考虑如果我们输了会发生什么,而不是名称 feature,但是提示提交:

branch2

在这种情况下,我们会收到投诉,指出缺少提交,因为名称 o--o--o <-- feature / \ ...--o--o--o------o--*--o <-- branch1 \ o--o ? <-- branch2 \ o----o--o <-- branch3 说“找到提交1234567”或其他什么,而且不存在。这是我们失去的那个。

我们不会得到任何悬空提交,因为branch2的父提交也在branch2上。现在提交仅在branch3 ,而不是在两个分支上,因为传出的向后箭头是我们丢失的提交的一部分。

如果我们丢失branch3的提示,我们获得悬挂提交:

branch1

合并提交 o--o--o <-- feature / \ ...--o--o--o------o--* ? <-- branch1 \ o--o-----------o <-- branch2 \ o----o--o <-- branch3 不再有任何方法可以找到,所以它是“悬空”。其中一个父项可以在名称*下找到,如果我们恢复合并提交本身就可以找到另一个父项,但如果我们不这样做,我们让Git垃圾收集不可达的提交,图剥离到这个:

feature

因此,如果存储库损坏,如果有备份或其他克隆来从中恢复“丢失”的项目,那么停止修改它是明智的(不要添加任何内容 it)并运行 o--o--o <-- feature / ...--o--o--o ? <-- branch1 \ o--o-----------o <-- branch2 \ o----o--o <-- branch3 使Git将任何“悬空”提交保存到git fsck --lost-found。然后,您可以查看这些内容(使用哈希ID .git/lost-found/commit/)查看它们是否有价值。 Git还会将无法访问的blob(文件)保存到git log;您可以使用任何文件查看器直接查看文件的内容,并以这种方式恢复丢失的文件。

但最好的办法是另外克隆(或适当的备份)。

1 但是对象可以打包重新打包,这会触及它们存储的方式,所以这不是一个难点和 - 快速统治。