如何修复Git中丢失的blob?

20

因为我一直在各个地方同步我的 Git 仓库,现在我被困在一个损坏的 Git 仓库中。当我执行 git log 命令时,我可以获得正确的历史记录,但是当我执行 git status 命令时,会出现...

fatal: unable to read 563e4c9abcd4114e08255db989f0f53426bdeff7

所以在搜索了一番后,我尝试了git fsck

Checking object directories: 100% (256/256), done.
missing blob 33244941016301570dccdcdc95e543910109d0a8
dangling blob 59f44441e6437ebc4d40182eb8a10d3e07fe367b
missing blob 5dc8ab1804acb58fc658bcd6152fbb246290c8ae
dangling blob 698c775f2599fad3d09906dead4dc67743a984bd
dangling blob 922003b8433bcad6ce9778a37628d738faa26389
dangling blob c33c0528bfee55b04d99de4580da49de4413329b
dangling blob e5107c118bde0edbe5dfb994cb6a50d235c3f06b
dangling blob 437573e539572454cb868ca5a0f5074b96d777ac
missing blob 468d1856336eaa1ce8006f38ce779c0d997c8d48
dangling blob 6fc9c88708d7d5ca455e68781472bdea119997eb
dangling blob 7225d0147fa566369ba3024324b527a7adeac094
dangling blob bb8125d15579fcf37925f09cd1883b15272f9f0d
missing blob c8095f49253ac3787a6f86943160eda2c78a6a28
dangling blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
dangling blob 0bdaed084e15add987ef86fe84f435d085475995
dangling blob 36ee13c9b334da090ea6b194606df8a2852b3b3a
missing blob 563e4c9abcd4114e08255db989f0f53426bdeff7   <= the one which results in the fatal error.
dangling blob 84f2f2a9d1d051e6418a787ca90e75446f712866
dangling blob c636d85269838efecbb496eda5a8cfd8ec753d69
dangling blob cb7a8494bfc86e894c0c6e268308ddc1dd6d713c
dangling blob d166fff9e1c85ab9f0f4f620119181c5f76c2a53
dangling blob d3b6f194df857412481a318d4275faeb6689e4a0
missing blob db9a6744bc0df03cf685296695bea6324f23e0ac
dangling blob def6a6a18457989c7d18825c7c1bbfeefc8b261d
and about 20 more..

从这里开始我有点迷茫了。我看到了一些关于运行git reflog expire --expire=now --all的内容,但对我没有任何作用。

我的仓库中的所有文件仍然存在并安全备份,所以这不是问题。但我想恢复我的仓库历史记录。从这一点出发我可以采取哪些步骤呢?


https://git.wiki.kernel.org/index.php/GitFaq#How_to_fix_a_broken_repository.3F - 0xAX
一个提示:在尝试修复任何东西之前,请先复制您的损坏的存储库。这样,如果最终使情况变得更糟,您总是可以回到原来的状态。此外,为了查看潜在的问题,您可以运行 git fsck --no-dangling。悬空对象不是问题。但缺少对象才是问题。 - Alderath
4个回答

29

我在尝试修复"object file is empty" error时,遇到了“missing blob”错误(实际上,我最终将对象文件.git/objects/f7/880aa1d1a76bfff73f3d602e15b4bc829d6a07从文件系统中删除)。

为了解决这个问题,我按照以下步骤进行:

  1. Use the Bash script found here in order to detect a commit containing this missing blob. Put it in the repository's root directory with the find.sh name:

    #!/bin/sh
    obj_name="$1"
    shift
    git log "$@" --pretty=format:'%T %h %s' \
    | while read tree commit subject ; do
        if git ls-tree -r $tree | grep -q "$obj_name" ; then
            echo $commit "$subject"
        fi
    done
    

    And then run it, passing the SHA-1 hash of the missing blob as the argument:

    ./find.sh f7880aa1d1a76bfff73f3d602e15b4bc829d6a07
    
    629afc4 ESLint warning in layers' configuration file is fixed.
    

    629afc4 is part of the commit's SHA-1 (it was a last commit I tried to push to remote repository).

  2. Find a file associated with this blob:

    git ls-tree -r 629afc4 | grep f7880aa1d1a76bfff73f3d602e15b4bc829d6a07
    
    100644 blob f7880aa1d1a76bfff73f3d602e15b4bc829d6a07    src/config/layers.js
    

    It's src/config/layers.js in my case.

  3. Check whether hash of the file matches the hash in Git tree:

    git hash-object src/config/layers.js
    
    f7880aa1d1a76bfff73f3d602e15b4bc829d6a07
    
  4. If so then we can write file contents to the blob:

    git hash-object -w src/config/layers.js
    
这些步骤帮助我解决了错误并修复了一个损坏的本地存储库。解决方案可以在这篇文章中找到。

3
非常感谢,这真的很有帮助。 - fralau
1
对我有用。在我的情况下,文件是存在的,但是它是空的,所以最后一个命令没有做任何事情。我不得不删除该文件(例如 rm -f .git/objects/f7/880aa1d1a76bfff73f3d602e15b4bc829d6a07)并再次运行 git hash-object -w 命令。 - jadkik94
我尝试将单个文件还原到先前提交的状态,结果陷入了这种状态,所以我知道我需要哪个文件并跳过了第4步。我不知道发生了什么,但它起作用了,谢谢! - derpedy-doo
这是一个非常神一般的答案,虽然它超出了我的 Git 技能范围,难以理解。 - kap
我无法进行 git push,它提示远程出现 EOF 错误。我使用新的 checkout 进行了检查,并确认 push 仍然正常工作。一旦我理解了 git fsck 的输出,我就能够发现缺失的文件,其中有很多。手动为每个文件编写文件内容,使用 'git hash-object -w file` 解决了问题。非常感谢这些线索。 - obj-D

4

接受的答案帮助我解决了问题。

然而,如果缺少的blob是当前目录下的文件(这是我的情况),我建议采用更快的解决方法

这意味着由于某种原因,一个文件没有被git正确地索引,从而导致了missing blob

要查找04da887681cecfd6cd59a928008b0e52ffe2a2bf的丢失blob,您可以进入 .git 目录,并运行:

find . -type f -print -exec git hash-object {} \; | grep -B1 04da887681cecfd6cd59a928008b0e52ffe2a2bf

这将检查您的数据以找到未索引的文件。 如果找到了什么东西,现在您就有了要索引的文件:

./myfile.php
04da887681cecfd6cd59a928008b0e52ffe2a2bf

然后,您可以使用以下命令将其编入索引中:git hash-object -w ./myfile.php

如果没有找到该文件,则说明这可能是之前的版本或已丢失的文件。


3
接受的答案或任何变体对我都不起作用,因为git fsck没有显示缺失的 blob,也没有。

$ git ls-tree -r HEAD | grep <missing blob hash id>

返回任何内容。

对我有用的是我采用的一个小技巧。我在这里分享一下,以防万一有人遇到类似问题。

我在新位置克隆了该仓库,并将其检出到我正在工作的分支。我将当前损坏的存储库中的更改保存起来(因为我有一些更改不能承受丢失),然后从新克隆的存储库复制了 .git 文件夹到旧存储库。然后我运行了 git pull ,接着它就工作了。


0

我知道这是一个相当老的问题,但我刚刚遇到了同样的问题,其他SO答案对我都没有用,这里提供的答案也不行。

阅读您的问题,我从您的第一句话中得到了一个想法:

因为我一直在各个地方同步我的git repo,现在我被卡在了一个损坏的git repo上。

我正在使用USB存储设备进行同步。这样,我可以在任何一个设备上的工作目录中只需执行git pull <path/to/usb/repo> master即可从USB存储设备中拉取,并且要“推送”到USB存储设备,我只需更改目录到USB存储库并使用git pull <path/to/working/directory> master。它已经成功运行了几次,直到今天。在我的一个工作目录中执行git pull <path/to/usb/repo> master时,我得到了以下错误信息:

errror: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due emote: fatal: unable to read 8f6d079cdb5243f5a2d1000e31967f4c361b7966
remote: aborting due to possible repository corruption on the remote side.

在我的 USB 存储库中执行 git fsck 时,我得到了 missing blob ...... 的错误提示(抱歉我没有复制,但只有两个缺失的 blob)。总而言之,我的问题与你的非常相似。在阅读了你的文章后,我有了以下想法:

概述: 最终,我按照 此处 所示进行了 Windows 扫描和修复 操作,这实际上每次我插入任何一个 USB 闪存驱动器时都会弹出,并且从未为我提供任何有用的帮助 - 直到现在。它实际上解决了整个问题。


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