如何恢复Git仓库中的“missing tree”错误?

38
我们正在使用Gerrit作为Git仓库。在一个已经活跃了几个月的项目上,我们突然无法推送任何更改。当我们执行git push时,会出现以下错误:

error: unpack failed: error Missing tree 14d62f0ed4385e3f68f226ac133fa9932a9c65c9

执行git fsck --full会得到:

dangling tree 2701c92fb6eab1826482f6bcc9598413e651a92a  
dangling blob c505b3b12cfacd1e26dec8dc559820a30fc20c27  
dangling blob 8907f94b5b4ec881e1b86d50681795e368c167ff  
dangling blob 4938d9fc34c6e2f92c68872bfec6e070b2b3a9c2  
dangling blob 8a5c8b8d35484ea1470e2d8e6c482fcb97b23d0f  
dangling commit 3072d3314e20bf6c6998e1c02986d83019d3e1df  
dangling tree 5377d7f7111d340854c3ee0946667c202227e603  
dangling tree c3783e9ab540457924ceb9f9fb5ea1c2b97472b1  
dangling blob 8b92d1765038e4ec5e721f98a2aabb305a7f9819  
dangling tree 38a03153f0f18ca15846e9bd4983a86800a43a94  
dangling commit 8db2d6ae5364174bebe13720a359ddb2e62d4c9d  

我们所有的开发人员在尝试推送时都遇到了同样的错误。到目前为止,我们已经尝试重新初始化gerrit存储库(git init --bare ...)并将其推送上去。我们还尝试使用单独的repo创建新的gerrit项目。最终,我们仍然得到相同的错误。

请问是否有人知道导致这种情况的原因,或者如何恢复?


请查看我在此处的答案:https://dev59.com/3G445IYBdhLWcg3wnrrM#49737208 - Archmede
14个回答

52

使用git push --no-thin代替git push

来自Git文档:

当发送方和接收方共享许多相同的对象时,细胞传输可以显著减少所发送的数据量。默认情况下是--thin。


6
如果你的分支领先许多次提交,你可能想使用这个选项。它可以很好地工作! - Riverside

21
我在我的乌龟Git上遇到了相同的错误。终于找到了这个错误的根本原因。
导致此错误的步骤如下:
- 在主分支上创建一个新的分支。 - 对新分支进行一些修改。 - 有人同时对主分支进行了修改。 - 尝试推送你的分支。
如果在主分支进行了一些修改但没有推送本地分支,就会出现这个错误。这是正常的,因为远程主分支对你的本地分支一无所知,直到进行推送操作。
要解决这个错误,切换到主分支并进行完全拉取操作。然后切换到你的分支,尝试进行推送。

3
哇,这是一个完全不明显的原因。这个解决方案对我有用! - Mike Schenk

13

我曾经遇到过同样的问题。为了解决它,我使用了git fetch,然后再次推送,这样就可以正常工作了。


9

在尝试任何操作之前,请立即备份。这听起来很不幸。同时,也很遗憾的是您似乎没有常规备份。但有好消息:我敢打赌您的开发人员有这个文件,尽管它可能是在一个打包文件中。尝试在别人的.git目录中执行以下操作。 注意,git使用哈希值的前两个字符作为目录名。

find . -name d62f0ed4385e3f68f226ac133fa9932a9c65c9

如果出现这种情况,请将该文件复制到您服务器上相同的相对路径中,然后一切都应该顺利进行。如果不行,则请尝试以下操作:
find . -name \*.idx -exec cat {} \; | git show-index | grep 14d62f0ed4385e3f68f226ac133fa9932a9c65c9

这不会告诉你它是哪个包文件(你可以快速编写脚本或手动完成),但它会告诉你它在那里。找到正确的包文件并展开它...

git unpack-objects $FILE

接下来,将文件复制到服务器上相同的相对路径。如果这样不行,需要进一步的工作。交换开发人员的最新版本库可能会解决问题。您还可以探索https://git.wiki.kernel.org/index.php/GitFaq#How_to_fix_a_broken_repository.3F,或者发布更新评论并等待我回来处理。


谢谢提供的信息,它对我帮助很大。我能够找到正确的idx文件,但解包pack文件并没有恢复任何内容。同样的情况也发生在其他开发人员身上。最终,由于时间不够用,我们通过初始化一个新仓库来解决这个问题,并将旧仓库保留下来以供历史记录。 - Justin Guertin
我们遇到了类似的问题,由于缺少树形结构而无法推送某些分支。我们已经找到了缺失的对象并将其复制到远程仓库,但问题仍然存在。有什么线索吗? - theintz

7

当我们遇到这种问题时,我通常可以通过运行 git gc 命令来解决:

git gc --aggressive --prune=now

首先要备份您的git仓库!


4
尝试使用 git pull --rebase
我保存了差异(git show > ~/mychanges.txt,删除了文件顶部的提交消息)。然后检出一个新分支(git checkout -b newbranch),应用更改(git apply ~/mychanges.txt),然后执行 git pull --rebase。然后一切都正常了。

1
谢谢你救了我的一天! - simonso

3

如果不在主分支上,您可以通过以下方式简单地删除远程分支:

git push --delete origin <branch_name>

然后将你的分支推送回远端:

git push -u origin <branch_name>

2

先试一下

git gc

然后执行

git push

我也遇到了同样的问题,上述解决方案对我起作用了。


1
奇怪的是,对我来说--no-thin参数不起作用。有效的方法是使用git pull(所以可能是git fetch)。

1
这通常是由于提交和推送时间不同造成的,最终导致两个树之间产生不匹配。假设有一个远程分支 upstream 和本地分支 foo

首先使用以下命令丢弃所有未提交的更改:

git reset --hard foo

然后使用以下命令跟踪远程分支:
git branch --set-upstream-to=upstream/foo

最后。
git pull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接