2013-02-10 45 views
3

注意:我没有任何此存储库的损坏前克隆。我相信我的情况与这里描述的其他人不同,因为我错过了一棵树,而不是一个blob。Git恢复:“目标文件为空”。如何重新创建树木?

发生了什么事:

当我试图克隆了LAN(通过SSH)存储库,Git会返回一个错误,指出该库已损坏:

remote: error: object file ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4 is empty 
remote: fatal: loose object 2e223ce259e9e33998d434acc778bc64b393d5d4 (stored in ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4) is corrupt 
error: git upload-pack: git-pack-objects died with error. 
fatal: git upload-pack: aborting due to possible repository corruption on the remote side. 
remote: aborting due to possible repository corruption on the remote side. 

我在什么地方发现git fsck可用于诊断腐败,但它并没有告诉我任何新的东西:

git fsck --full 
error: object file ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4 is empty 
fatal: loose object 2e223ce259e9e33998d434acc778bc64b393d5d4 (stored in ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4) is corrupt 

我试图克隆reposito本地(使用--no-hardlinks)查看会发生什么,但我得到的结果完全相同。

然后我在this question迷迷糊糊的,谁回答的家伙刚刚删除的空文件(步骤3),所以我这样做(即我已经删除了子目录​​文件223ce259e9e33998d434acc778bc64b393d5d4)。

git fsck一遍,我看到:

Checking object directories: 100% (256/256), done. 
broken link from tree 838e437f371c652fa4393d25473ce21cbf697d7a 
       to tree 2e223ce259e9e33998d434acc778bc64b393d5d4 
dangling commit 54146bc0dc4eb3eede82a0405b749e05c11c5522 
missing tree 2e223ce259e9e33998d434acc778bc64b393d5d4 
dangling commit 864864feec207786b84158e526b2faec7799fd4e 
dangling blob d3cfd7cc7718d5b76df70cf9865db01c25181bfb 

所以,现在有树木838e437f37问题。这不是上面提到的那个家伙发生的事情,所以我去谷歌搜索,发现some information from Linus

所以,我做了git ls-tree 838e437f371c652fa4393d25473ce21cbf697d7a和输出有这样一行:

040000 tree 2e223ce259e9e33998d434acc778bc64b393d5d4 moje 

现在,“moje”是目录(不像莱纳斯解释说,这是一个文件中的示例)。我想这就是为什么Linus建议下一步,git hash-object moje返回fatal: Unable to hash moje

但无论如何,这只是一个小的机会,这是我所需要的,所以我进一步寻找。我跑了git log --raw --all --full-history -- moje/,根据Linus的指南,应该有一个提交列出2e223作为一些内容的SHA-2散列,但没有。并且列表以

fatal: unable to read source tree (2e223ce259e9e33998d434acc778bc64b393d5d4) 

我试着查看错误之前列出的最后一个提交,但是我没有找到这个哈希。我见过this,但它没有帮助我,可能是因为有问题的版本和工作树的当前状态之间的一些变化。

有一件事情可能很重要:在moje/里面有一个目录cli/,它是一个Git仓库本身(一个子模块)。我已经在那里寻找有问题的SHA-2哈希,但还没有找到它。

我该怎么办?

+1

很好的意见,但你也可以将它张贴作为自己的回答你的问题。你甚至可以接受你自己的答案,但不要这样做;)Chronial的答案赢得了公平和正确的“刻度标记”。 – VonC 2013-02-13 11:45:49

+1

当然,Chronial的答案将保持公认的答案:)我已经将解决​​方案移至单独的答案中,正如所建议的那样。 – 2013-02-14 09:21:27

回答

2

使用此命令来获取包含丢失的树提交列表:

git rev-list --all | xargs -l -I '{}' sh -c 'if git ls-tree -rt {} > /dev/null 2>&1 ; then true; else git log --oneline -1 {}; git ls-tree -r -t {} | tail -1; fi' 

现在,您需要重新创建丢失的树,通过将完全相同的内容,在那里你必须在那里返回然后再将该树添加到回购。最简单的方法是重新创建内容,然后将它们提交到回购站(之后您可以删除该提交)。

+0

谢谢,它工作!我发现了有问题的提交,查看了它的父代和未损坏的第一个后代之间的差异,并设法重新创建树。我将编辑我的问题以详细显示解决方案。 – 2013-02-13 09:51:29

+0

很高兴我能帮到你。不过,我认为您应该将解决方案的细节移至单独的答案。 (是的,你可以回答你自己的问题)。 – Chronial 2013-02-13 11:45:20

+0

更新:根据Chronial的建议,我将解决方案移至[单独的答案](http://stackoverflow.com/a/14871420/2058424)。 – 2013-02-14 11:21:24

5

命令(由Chronial建议的)

git rev-list --all | xargs -l -I '{}' sh -c 'if git ls-tree -rt {} > /dev/null 2>&1 ; then true; else git log --oneline -1 {}; git ls-tree -r -t {} | tail -1; fi' 

返回的第一提交其依赖于丢失2e223ce对象 - 其SHA-2的散列是499b8fb。它的父母是没事的(我可以看到它的内容,检查出来等等),并且我也能够在破坏后的下一个提交(89b0fc4)后检查下一个提交。

现在我需要看到之间发生了什么样的变化这两个“好”的承诺 - 这很简单:git diff 499b8fb~ 89b0fc4返回

diff --git a/somefile b/somefile 
deleted file mode 100644 
index f5d1e1e..0000000 
--- a/somefile 
+++ /dev/null 
@@ -1,79 +0,0 @@ 
[ contents of the deleted "somefile"... ] 
diff --git a/moje/cli b/moje/cli 
index 640a825..c0b1a24 160000 
--- a/moje/cli 
+++ b/moje/cli 
@@ -1 +1 @@ 
-Subproject commit 640a825cd671dfba83601d6271e7e027665eaca8 
+Subproject commit c0b1a24aa246289831ec7db3a8596376db1f625a 

现在我知道了不好的父母之间的承诺和良好的提交文件somefile已删除,子模块的HEAD从640a825更改为c0b1a24。我去了子模块库,并要求之间发生了什么事的提交这两个:

git log --oneline 640a825..c0b1a24 
其返回

c0b1a24 <commit message> 
8be9433 <commit message> 
02564e1 <commit message> 

现在我知道四件事499b8fb~89b0fc4之间发生

  • somefile被删除
  • /moje/cli HEAD被更改为fr OM 640a82502564e1
  • /moje/cli HEAD从02564e1变更为8be9433
  • /moje/cli HEAD从8be9433改为c0b1a24

我不知道在哪一部分499b8fb发生(坏提交),以及在89b0fc4。但幸运的是没有那么多的可能性,所以我只尝试了其中的每一种。对于每个组合,我都进行了一次提交,以便Git计算适当的对象并将它们存储在数据库中。原来,当/moje/cli HEAD在8be9433,git commit导致创建缺少2e223ce对象 - 万岁!注意:如果你有类似的情况,并且你正在四处寻找哪些提交是好的以及Git可以告诉你关于它们的信息,请记住,能够提交checkout和提交show这是两个不同的事情。例如,我最初认为,如果git show somesha引发错误,则意味着somesha提交已损坏,并且我无法将其用于任何操作。原来这是错误的:虽然git show 89b0fc4返回一个错误,我可以git checkout 89b0fc4git diff 499b8fb~ 89b0fc4工作。

我想这是因为git show somesha显示somesha引入的变化,因为Git需要读取先前提交(在这种情况下是损坏的)的内容。显然,Git不需要看以前的提交来检查一个。

(我设法这得益于做Chronial's answer - !荣誉给他有人劝我张贴这是我自己的答案。)

+1

优秀的反馈。 +1 – VonC 2013-02-14 09:23:33

+0

非常感谢您为解决问题而制定的步骤!帮助我保存损坏的回购的历史。 – ramiro 2014-06-11 13:08:42

+0

感谢您的答复,但对我来说确实返回了同样的错误: ''' 错误:目标文件的.git /反对/ 9C/e0546f12bffd80d73f648586a9d399b27ad201是EMP TY 错误:目标文件的.git /对象/ 9C/e0546f12bffd80d73f648586a9d399b27ad201是EMP TY 致命:松散对象9ce0546f12bffd80d73f648586a9d399b27ad201(存储在的.git/OBJ 学分/ 9C/e0546f12bffd80d73f648586a9d399b27ad201)已损坏 ''' – 2014-07-29 06:29:02