3

注意:我没有此存储库的任何损坏前克隆。我相信我的情况与这里描述的其他人不同,因为我缺少一棵树,而不是一团。

发生了什么:

当我尝试通过 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

我尝试在本地(使用--no-hardlinks)克隆存储库以查看会发生什么,但我得到了完全相同的结果。

然后我偶然发现了这个问题,回答的人刚刚删除了空文件(第 3 步),所以我这样做了(即我已经223ce259e9e33998d434acc778bc64b393d5d4从子目录中删除了文件objects/2e/)。

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

所以,现在 tree 有问题了838e437f37。上面提到的那个人不是这样的,所以我去谷歌搜索了一下,从 Linus 那里找到了一些信息

所以,我做到了git ls-tree 838e437f371c652fa4393d25473ce21cbf697d7a,在输出中有一行阅读:

040000 tree 2e223ce259e9e33998d434acc778bc64b393d5d4    moje

现在,“moje”是一个目录(与 Linus 解释的示例不同,它是一个文件)。我想这就是 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)

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

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

我该怎么办?

4

2 回答 2

6

命令(由 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 从更改640a825c0b1a24. 我去了子模块存储库并询问这两者之间发生了什么提交:

git log --oneline 640a825..c0b1a24

返回

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

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

  • somefile被删除
  • /moje/cliHEAD 从 更改640a82502564e1
  • /moje/cliHEAD 从 更改02564e18be9433
  • /moje/cliHEAD 从 更改8be9433c0b1a24

我不知道哪一部分发生在499b8fb(错误的提交)中,哪一部分发生在89b0fc4. 但幸运的是没有那么多可能性,所以我只是尝试了每一种。对于每个组合,我都进行了提交,以便 Git 计算适当的对象并将它们存储在数据库中。事实证明,当/moje/cliHEAD 位于 时8be9433git commit导致创建了丢失的2e223ce对象 - 万岁!

注意:如果您遇到类似的情况并且正在四处寻找哪些提交是好的以及 Git 可以告诉您什么,请记住,能够checkout提交show是两件不同的事情。例如,我最初认为如果git show somesha抛出错误,则意味着somesha提交已损坏,我无法将其用于任何事情。结果证明是错误的:虽然git show 89b0fc4返回了错误,但我能够git checkout 89b0fc4并且也git diff 499b8fb~ 89b0fc4工作了。

我想这是因为git show somesha显示了 引入了哪些更改somesha,因此 Git 需要读取上一次提交的内容(在这种情况下是损坏的内容)。显然,Git 不需要查看前一个提交来签出一个。

(感谢Chronial 的回答,我设法做到了这一点- 对他表示敬意!我被建议将其发布为我自己的答案。)

于 2013-02-14T09:20:24.507 回答
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'

现在您需要重新创建丢失的树,方法是在其中放置与当时完全相同的内容,然后将该树添加到 repo。最简单的方法可能是重新创建内容,然后将它们提交到 repo(您可以在之后删除该提交)。

于 2013-02-12T11:34:57.677 回答