Git:"腐败的松散物体"

asg*_*las 293 git version-control

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

$ git gc
error: Could not read 3813783126d41a3200b35b6681357c213352ab31
fatal: bad tree object 3813783126d41a3200b35b6681357c213352ab31
error: failed to run repack
Run Code Online (Sandbox Code Playgroud)

有谁知道,该怎么办?

从cat-file我得到这个:

$ git cat-file -t 3813783126d41a3200b35b6681357c213352ab31
error: unable to find 3813783126d41a3200b35b6681357c213352ab31
fatal: git cat-file 3813783126d41a3200b35b6681357c213352ab31: bad file
Run Code Online (Sandbox Code Playgroud)

从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
Run Code Online (Sandbox Code Playgroud)

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

cub*_*uce 329

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

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

但它有一些缺点:

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

修复

从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

在Windows上,您将需要使用:

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

现在foo的原始.git子目录已经恢复,但所有本地更改仍然存在.git status,commit,pull,push,,因为他们应该再等方面的工作.

  • 是的,未提交的提交信息将丢失.但是在常见的情况下(没有多个本地分支,其他的当前分支没有被删除的更改),所有最新的文件修改(墨水删除)仍然在光盘上,因此,可以轻松地重复任何先前的未提交的提交.由于我总是在任何提交序列之后推送,我甚至没有遇到这个麻烦. (30认同)
  • 这种方法对我有用.但是,我相信所有未提交的提交都会丢失.回购数据未受影响. (11认同)
  • 简单明了.这是IMO,如果您不了解git的所有内容并且您不想使用您的存储库,那么这是最有效的解决方案. (7认同)
  • 我认为它会删除所有的藏匿处,因为它们存储在.git子目录下. (4认同)
  • 如果项目中有子模块,则需要在检索`.git`文件夹之前初始化它们. (3认同)
  • 它解决了问题,但我失去了除 master 之外的所有其他重要分支,所以使用非常非常小心 (2认同)

小智 214

你最好的选择可能只是从远程仓库(即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  
Run Code Online (Sandbox Code Playgroud)

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

  • 恕我直言,这应该是公认的答案.比删除回购和重新克隆要容易得多!:)虽然你确实失去了任何上演的提交...... (11认同)
  • 显然,如果在腐败发生时您在主人以外的分支中,请用您的分支名称替换`master`. (6认同)
  • 我今天做了这个,并且没有丢失对文件的未提交的更改:)(git 2.17.1) (4认同)
  • 如果您看到此消息,则可能需要将“master”分支更改为“main”分支。 (2认同)

Fel*_*ira 135

在我的笔记本电脑上工作,电池坏了,得到了这个错误;

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

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

find .git/objects/ -size 0 -exec rm -f {} \;
git fetch origin
Run Code Online (Sandbox Code Playgroud)

之后我跑了一个git status,回购很好,有我的变化(等待承诺,现在就做......).

git版本1.9.1

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

  • `find .git/objects/-size 0 -exec rm -f {} \;`对我有用;) (9认同)
  • 在删除空对象后,您可能需要运行`git symbolic-ref HEAD refs/heads/master`. (6认同)
  • 我可以建议 `find .git/objects/ -empty -delete` (3认同)
  • 遇到了同样的问题,运行命令,在 Mint VM 上对我来说完美无缺。 (2认同)
  • 不是在虚拟机上,这对我有用很多次。IDK 为什么这在我当前的项目中不断发生,但每次都会修复它。 (2认同)

Ada*_*ruk 55

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

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

看看Scott Chacon关于git内部的Git Screencast.这将向您展示git如何在幕后工作以及如果您真的陷入困境并且无法从其他人那里获得该对象,那么该怎么做这个侦探工作.

  • 你能指点一下我应该看哪些命令吗?:) (17认同)
  • 它可以存储在包文件中。这就是 git 通过存储增量来压缩对象存储的方式。松散对象是尚未在包中的对象。谷歌搜索包文件,git 中的索引文件,你应该能够根据需要深入研究。 (2认同)
  • 你能否在回答Chacon的Git截屏时提供一个链接? (2认同)
  • 现在请用英语重复 (2认同)

dec*_*lan 39

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

但是,当我试图跑步时,git status我得到了

error: object file .git/objects/xx/12345 is empty
fatal: loose object xx12345 (stored in .git/objects/xx/12345 is corrupt
Run Code Online (Sandbox Code Playgroud)

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

概观

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

细节

可能的选择似乎是

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

方法1:删除目标文件

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

mv .git/objects/xx/12345 ..
Run Code Online (Sandbox Code Playgroud)

这没用 - git开始抱怨链接断了.方法2.

方法2:修复文件

Linus Torvalds有一篇关于如何恢复一个能够解决问题的目标文件的精彩文章.这里总结了关键步骤.

$> # 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
Run Code Online (Sandbox Code Playgroud)

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

$> git hash-object -w path/to/your_file.whatever
Run Code Online (Sandbox Code Playgroud)

做完这个后,我检查了.git/objects/xx/12345,它不再是空的,git停止抱怨.


小智 13

我的 linux mint 崩溃后遇到同样的问题,我按电源按钮关闭我的笔记本电脑,这就是我的 .git 损坏的原因

find .git/objects/ -empty -delete
Run Code Online (Sandbox Code Playgroud)

之后,我收到致命错误:坏对象头。我刚刚重新初始化了我的 git

git init
Run Code Online (Sandbox Code Playgroud)

并从远程仓库获取

git fetch
Run Code Online (Sandbox Code Playgroud)

要检查你的 git,请使用

git status
Run Code Online (Sandbox Code Playgroud)

又开始工作了。我不会丢失本地更改,因此我可以提交而无需重写代码


Art*_*hur 12

尝试

git stash
Run Code Online (Sandbox Code Playgroud)

这对我有用.它隐藏了你没有做过的任何东西,并解决了这个问题.

  • 真是太好了......对我来说不起作用;) (6认同)
  • @go2null 我在这方面有点晚了,但输入/输出错误通常意味着硬盘问题。虽然我相信你现在已经想通了。 (2认同)

小智 8

simply running a git prune fixed this issue for me

  • 原因可能是 git prune 根本不能解决问题。 (6认同)

Jag*_*ago 7

一个垃圾收集固定我的问题:

git gc --aggressive --prune=now
Run Code Online (Sandbox Code Playgroud)

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

  • “无法运行重新记录” (6认同)
  • 这是一个很好的解决方案。为我工作。我的系统意外关闭。然而,这个命令使我免于克隆和所有这些繁重的任务。谢谢杰戈。 (2认同)
  • 来自[另一个问题](/sf/ask/133340231/#29203553):***“仅*** *使用 `git gc --prune=now` 将不起作用,因为这些提交仍然在引用日志中引用。因此,必须清除引用日志。"* (2认同)

Waj*_*ath 6

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

(请注意,您损坏的提交会丢失,但更改会保留。您可能需要在此过程结束时重新创建这些提交)

  • 备份你的代码。
  • 转到您的工作目录并删除该.git文件夹。
  • 现在将遥控器克隆到另一个位置并复制其中的.git文件夹。
  • 将其粘贴到您的工作目录中。
  • 随心所欲地提交。


Ert*_*oğa 5

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
Run Code Online (Sandbox Code Playgroud)

  • git 分支 (--set-upstream-to=<上游> | -u <上游>) [<分支名称>] (2认同)

hal*_*fer 5

我刚刚经历了这个 - 我的机器在写入 Git 存储库时崩溃了,它被损坏了。我按如下方式修复了它。

我首先查看我没有推送到远程仓库的提交数量,因此:

gitk &
Run Code Online (Sandbox Code Playgroud)

如果你不使用这个工具,它非常方便——据我所知,它在所有操作系统上都可用。这表明我的遥控器缺少两次提交。因此,我单击了指示最新远程提交(通常是/remotes/origin/master)的标签以获取散列(散列长度为 40 个字符,但为简洁起见,我在这里使用 10 个字符 - 这通常可以正常工作)。

这里是:

14c0fcc9b3

然后我单击以下提交(即远程没有的第一个提交)并在那里获取哈希:

04d44c3298

然后我使用这两个来为此提交制作补丁:

git diff 14c0fcc9b3 04d44c3298 > 1.patch
Run Code Online (Sandbox Code Playgroud)

然后我对另一个丢失的提交做了同样的处理,即我使用了之前提交的哈希值和提交本身的哈希值:

git diff 04d44c3298 fc1d4b0df7 > 2.patch
Run Code Online (Sandbox Code Playgroud)

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

git clone git@github.com:username/repo.git
Run Code Online (Sandbox Code Playgroud)

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

patch -p1 < 1.patch
git commit

patch -p1 < 2.patch
git commit
Run Code Online (Sandbox Code Playgroud)

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

git fsck 
Run Code Online (Sandbox Code Playgroud)

你会得到这样的东西:

error: object file .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d is empty
error: unable to find ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d
error: sha1 mismatch ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d
Run Code Online (Sandbox Code Playgroud)

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

rm .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d
cp ../good-repo/.git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d
Run Code Online (Sandbox Code Playgroud)

即删除损坏的文件并用一个好的文件替换它。您可能需要多次执行此操作。最后,您可以毫无错误地运行fsck。您可能会在报告中包含“dangling commit”和“dangling blob”行,这些是您在此文件夹中重新设置和修改的结果,并且没问题。垃圾收集器会在适当的时候删除它们。

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


geo*_*geo 5

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

find .git/objects/ -size 0 -exec rm -f {} \;
git fetch origin
git symbolic-ref HEAD refs/heads/${BRANCH_NAME}
Run Code Online (Sandbox Code Playgroud)