Git:“腐败的松散物体”

时间:2010-11-23 09:16:30

标签: git version-control

每当我从遥控器拉出时,我都会收到有关压缩的以下错误。当我运行手动压缩时,我得到相同的结果:

$ git gc
error: Could not read 3813783126d41a3200b35b6681357c213352ab31
fatal: bad tree object 3813783126d41a3200b35b6681357c213352ab31
error: failed to run repack

有谁知道,该怎么办?

从cat-file我得到了这个:

$ git cat-file -t 3813783126d41a3200b35b6681357c213352ab31
error: unable to find 3813783126d41a3200b35b6681357c213352ab31
fatal: git cat-file 3813783126d41a3200b35b6681357c213352ab31: bad file

从git fsck我得到了这个(不知道它是否真的相关):

$ git fsck
error: inflate: data stream error (invalid distance too far back)
error: corrupt loose object '45ba4ceb93bc812ef20a6630bb27e9e0b33a012a'
fatal: loose object 45ba4ceb93bc812ef20a6630bb27e9e0b33a012a (stored in .git/objects/45/ba4ceb93bc812ef20a6630bb27e9e0b33a012a) is corrupted

任何人都可以帮我解读这个吗?

27 个答案:

答案 0 :(得分:305)

我有同样的问题(不知道为什么)。

此修补程序需要访问存储库的未损坏的远程副本,并保持本地工作副本的完整。

但它有一些缺点:

  • 您将丢失未被推送的任何提交的记录,并且必须重新发送它们。
  • 你会失去任何藏匿处。

修复

从repo上方的父目录执行这些命令(将'foo'替换为项目文件夹的名称):

  1. 创建损坏目录的备份:
    cp -R foo foo-backup
  2. 将远程存储库的新克隆创建到新目录:
    git clone git@www.mydomain.de:foo foo-newclone
  3. 删除损坏的.git子目录:
    rm -rf foo/.git
  4. 将新克隆的.git子目录移动到foo:
    mv foo-newclone/.git foo
  5. 删除临时新克隆的其余部分:
    rm -rf foo-newclone
  6. 在Windows上,您需要使用:

    • copy代替cp -R
    • rmdir /S代替rm -rf
    • move代替mv

    现在foo的原始.git子目录已经恢复,但所有本地更改仍然存在。 git statuscommitpullpush等再次按原样运作。

答案 1 :(得分:194)

你最好的选择可能只是从远程仓库(即Github或其他)重新克隆。不幸的是,您将丢失任何未提交的提交和隐藏的更改,但是您的工作副本应保持不变。

首先制作本地文件的备份副本。然后从工作树的根目录执行此操作:

rm -fr .git
git init
git remote add origin [your-git-remote-url]
git fetch
git reset --mixed origin/master
git branch --set-upstream-to=origin/master master  

然后根据需要提交任何已更改的文件。

答案 2 :(得分:106)

在虚拟机上工作,在我的笔记本中,电池坏了,出现了这个错误;

  

错误:目标文件.git / objects / ce / theRef为空错误:对象   文件.git / objects / ce / theRef为空致命:松散对象theRef   (存储在.git / objects / ce / theRef中)已损坏

我设法让只有2个命令再次使用repo并且而不会丢失我的工作(修改后的文件/未提交的更改)

find .git/objects/ -size 0 -exec rm -f {} \;
git fetch origin

之后我跑了git status,回购很好,有我的更改(等待提交,现在就做......)。

git version 1.9.1

请记住备份您记住的所有更改,以防万一此解决方案不起作用,并且需要更激进的方法。

答案 3 :(得分:54)

看起来你有一个损坏的树对象。您需要从其他人那里获取该对象。希望他们有一个没有破坏的版本。

如果您无法通过猜测应该在哪些文件中找到其他人的有效版本,您实际上可以重新构建它。你可能想看看日期和时间。对象的次数与之匹配。那些可能是相关的blob。您可以从这些对象推断树对象的结构。

看一下关于git内部的Scott Chacon's Git Screencasts。这将向您展示git如何在幕后工作以及如果您真的陷入困境并且无法从其他人那里获得该对象,那么如何进行这项侦探工作。

答案 4 :(得分:38)

我在编写提交消息时计算机崩溃了。重新启动后,工作树就像我离开它一样,我能够成功提交更改。

然而,当我试图运行git status时,我得到了

error: object file .git/objects/xx/12345 is empty
fatal: loose object xx12345 (stored in .git/objects/xx/12345 is corrupt

与大多数其他答案不同,我并没有尝试恢复任何数据。我只是需要Git来停止抱怨空目标文件。

概述

“目标文件”是你关心的真实文件的git散列表示。 Git认为它应该有一个存储在some/file.whatever中的.git/object/xx/12345的散列版本,修复错误主要是找出“松散对象”应该代表哪个文件。

详细

可能的选项似乎是

  1. 删除空文件
  2. 将文件置于Git
  3. 可接受的状态

    方法1:删除目标文件

    我尝试的第一件事就是移动目标文件

    mv .git/objects/xx/12345 ..
    

    那没用 - git开始抱怨链接断了。方法2。

    方法2:修复文件

    Linus Torvalds有一篇很好的how to recover an object file文章,为我解决了这个问题。这里总结了关键步骤。

    $> # Find out which file the blob object refers to
    $> git fsck
    broken link from    tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
               to    blob xx12345
    missing blob xx12345
    
    $> git ls-tree 2d926
    ...
    10064 blob xx12345  your_file.whatever
    

    这告诉你空对象应该是什么文件的散列。现在你可以修复它。

    $> git hash-object -w path/to/your_file.whatever
    

    执行此操作后,我检查了.git/objects/xx/12345,它已不再为空,git停止抱怨。

答案 5 :(得分:12)

尝试

git stash

这对我有用。它隐藏了你没有做过的任何事情,并解决了这个问题。

答案 6 :(得分:7)

garbage collection解决了我的问题:

git gc --aggressive --prune=now

需要一段时间才能完成,但每个松散的对象和/或损坏的索引都已修复。

答案 7 :(得分:4)

我刚刚经历过这个 - 我的机器在写入Git仓库时崩溃了,它已经损坏了。我把它固定如下。

我开始查看有多少提交没有推送到远程仓库,因此:

gitk &

如果您不使用此工具,它非常方便 - 据我所知,所有操作系统都可以使用。这表明我的遥控器丢失了两次提交。因此,我点击标签指示最新的远程提交(通常这将是/remotes/origin/master)以获取哈希值(哈希值为40个字符长,但为了简洁起见,我在这里使用10个 - 这通常无论如何都适用)。 / p>

这是:

  

14c0fcc9b3

然后我点击下面的提交(即遥控器没有的第一个提交)并在那里获取哈希:

  

04d44c3298

然后我使用这两个来为这个提交做一个补丁:

git diff 14c0fcc9b3 04d44c3298 > 1.patch

然后我用其他缺少的提交做了同样的事情,即我之前使用了提交的哈希和提交本身的哈希:

git diff 04d44c3298 fc1d4b0df7 > 2.patch

然后我移动到一个新目录,从远程克隆了repo:

git clone git@github.com:username/repo.git

然后我将补丁文件移动到新文件夹中,并应用它们并使用其确切的提交消息(可以从git loggitk窗口粘贴)提交它们:

patch -p1 < 1.patch
git commit

patch -p1 < 2.patch
git commit

这为我恢复了一些东西(注意,对于大量的提交,可能有更快的方法)。但是我很想看看损坏的回购中的树是否可以修复,答案是可以的。如上所述修复了repo,请在损坏的文件夹中运行此命令:

git fsck 

你会得到这样的东西:

error: object file .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d is empty
error: unable to find ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d
error: sha1 mismatch ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d

要进行修复,我会在损坏的文件夹中执行此操作:

rm .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d
cp ../good-repo/.git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d

即。删除损坏的文件并将其替换为一个好的文件。您可能需要多次这样做。最后,您可以毫无错误地运行fsck。您可能在报告中有“悬挂提交”和“悬空blob”行,这些是您在此文件夹中的rebase和修改的结果,并且没问题。垃圾收集器将在适当的时候删除它们。

因此(至少在我的情况下)损坏的树并不意味着丢失了提交的提交。

答案 8 :(得分:3)

我也遇到了腐败的松散物体错误。

./objects/x/x

我通过进入腐败对象的目录成功修复了它。我看到分配给该对象的用户我的git用户。我不知道它是怎么发生的,但是我在那个文件上运行chown git:git然后再次工作了。

对于某些人的问题,这可能是一个潜在的解决方案,但并非所有问题都是必要的。

答案 9 :(得分:2)

回答@ user1055643错过了最后一步:

$ rm -fr .git
$ git init
$ git remote add origin your-git-remote-url
$ git fetch
$ git reset --hard origin/master
$ git branch --set-upstream-to=origin/master master  

答案 10 :(得分:2)

Felipe Pereira(上文)提供的解决方案以及 Stephan 对该答案的评论当对象损坏时我所在的分支的名称对我有用。

find .git/objects/ -size 0 -exec rm -f {} \;
git fetch origin
git symbolic-ref HEAD refs/heads/${BRANCH_NAME}

答案 11 :(得分:2)

我的系统崩溃后就遇到了这个问题。我所做的是这样:

(请注意,丢失的提交已丢失,但是更改已保留。您可能必须在此过程结束时重新创建这些提交)

  • 备份您的代码。
  • 转到工作目录并删除.git文件夹。
  • 现在将远程克隆到另一个位置,并在其中复制.git文件夹。
  • 将其粘贴到您的工作目录中。
  • 按需提交。

答案 12 :(得分:2)

只需运行git prune即可为我解决此问题

答案 13 :(得分:2)

我的(Windows)机器决定重新启动后出现此错误。 值得庆幸的是,我的远程仓库是最新的,所以我只是做了一个新的git-clone ..

答案 14 :(得分:2)

我在这里遵循了许多其他步骤;莱纳斯&#39;描述如何查看git树/对象并找到缺少的内容特别有用。 git-git recover corrupted blob

但最后,对我来说,由于部分磁盘故障导致了松散/损坏的树对象,并且该对象不容易恢复/不被该文档覆盖。

最后,我将冲突的objects/<ha>/<hash>移开了,并将git unpack-objects与来自合理最新克隆的包文件一起使用。它能够恢复丢失的树对象。

仍然给我留下了许多悬空斑点,这可能是解包以前存档的东西的副作用,并在其他问题中解决here

答案 15 :(得分:1)

对我来说,这是因为在执行git push时发生电源故障。

消息看起来像这样:

$ git status
error: object file .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74 is empty
error: object file .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74 is empty
fatal: loose object c238824eb3fb602edc2c49fccb535f9e53951c74 (stored in .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74) is corrupt

我试过像git fsck这样的东西,但这没有帮助。 由于崩溃发生在git push期间,它显然发生在客户端重写期间,这在服务器更新后发生。我环顾四周,发现在我的案例中c2388是一个提交对象,因为.git/refs中的条目引用了它。所以我知道当我查看历史记录时(通过网络界面或第二次克隆),我将能够找到c2388

在第二个克隆上,我做了一个git log -n 2 c2388来识别c2388的前身。然后,我手动修改了.git/refs/heads/master.git/refs/remotes/origin/master,使其成为c2388的前身,而不是c2388。 然后我可以做git fetch。 对于空对象的冲突,git fetch失败了几次。我删除了每个空对象,直到git fetch成功。这已经治愈了存储库。

答案 16 :(得分:1)

我这样解决了: 我决定简单地将未损坏的目标文件从备份克隆复制到我的原始存储库。这也很有效。 (顺便说一下:如果你无法通过名称找到.git / objects /中的对象,它可能已经[打包] [pack]来节省空间。)

答案 17 :(得分:1)

Runnning git stash; git stash pop解决了我的问题

答案 18 :(得分:0)

我刚遇到这样的问题。我的特殊问题是由于系统崩溃导致最近的提交(以及主分支)损坏。我没有推,并想重新做出承诺。在我的特殊情况下,我能够像这样处理它:

  1. 备份.git/rsync -a .git/ git-bak/
  2. 检查.git/logs/HEAD,找到具有有效提交ID的最后一行。对我来说,这是最近的第二次承诺。这很好,因为我仍然有文件的工作目录版本,所以我想要的每个版本。
  3. 在该提交中创建一个分支:git branch temp <commit-id>
  4. 使用工作目录中的文件重新执行损坏的提交。
  5. git reset master temp将主分支移动到您在步骤2中进行的新提交。
  6. git checkout master并使用git log检查其是否正确。
  7. git branch -d temp
  8. git fsck --full,现在可以安全地删除fsck找到的任何损坏的对象。
  9. 如果一切看起来都不错,请尝试推送。如果有效,
  10. 这对我有用。我怀疑这是一个相当常见的情况,因为最近的提交最有可能被破坏,但如果你再失去一个,你可能仍然可以使用这样的方法,小心使用{{1} },以及git cherrypick中的reflog。

答案 19 :(得分:0)

我在裸机远程git仓库中遇到了同样的问题。经过多次故障排除后,我发现我的一个同事提交了一个提交,其中.git / objects中的某些文件的权限为440(r - r -----)而不是444(r - r - r - )。在要求同事用裸git仓库中的“chmod 444 -R objects”更改权限后,问题得到解决。

答案 20 :(得分:0)

当我遇到这个问题时,我备份了我最近的更改(因为我知道我已经更改了)然后删除了它在.git / location中抱怨的文件。然后我做了一个git pull。请注意,这可能不适合你。

答案 21 :(得分:0)

我们刚才有这个案子。碰巧问题是腐败文件的所有权是root而不是普通用户。这是因为在某人完成了&#34; sudo su - &#34;之后在服务器上完成了提交。

首先,使用以下命令识别损坏的文件:

$> git fsck --full

你应该得到这样一个答案:

fatal: loose object 11b25a9d10b4144711bf616590e171a76a35c1f9 (stored in .git/objects/11/b25a9d10b4144711bf616590e171a76a35c1f9) is corrupt

进入损坏文件所在的文件夹并执行:

$> ls -la

检查损坏文件的所有权。如果情况不同,只需返回您的仓库的根目录并执行以下操作:

$> sudo chown -R YOURCORRECTUSER:www-data .git/

希望它有所帮助!

答案 22 :(得分:0)

创建备份并将存储库克隆到新目录中

WHERE DATE(CreatedDatetime, "+03:00") = CURRENT_DATE("+03:00")

(可选)如果您在与 master 不同的分支上工作,请切换它。

cp -R foo foo-backup
git clone git@url:foo foo-new

同步更改,不包括 .git 目录

cd foo-new
git checkout -b branch-name origin/branch-name

答案 23 :(得分:0)

在同一个git checkout上使用不同版本的各种git客户端时,通常会出现这个问题。想想:

  • 命令行
  • IDE 内置 git
  • docker / vm 容器内部
  • GIT gui 工具

确保使用与创建提交相同的客户端进行推送。

答案 24 :(得分:0)

为了不丢失其他未推送的分支,我所做的一切: 对损坏对象的引用应该在 refs/heads/<current_branch> 中。如果您转到 .git\logs\refs\heads\<current_branch>,您可以看到最后一次提交具有完全相同的值。我将上一次提交中的一个复制到第一个文件中,它解决了问题。

答案 25 :(得分:0)

您不需要克隆,也不需要丢失未提交的更改。只需使用 git rm -rf .git/ 删除 .git 文件夹,然后通过启动新存储库、设置远程和重置头来恢复 git 文件夹。我在此处添加了恢复已删除 git 文件夹的说明:

https://stackoverflow.com/a/67610397/7584643

答案 26 :(得分:-6)

只需删除.git文件夹并重新添加即可。这个简单的解决方案对我有用。