如何恢复受硬盘故障损坏的Git对象?

我遇到了硬盘故障,导致Git存储库的某些文件被损坏。 当运行git fsck --full我得到以下输出:

error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch
error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid code lengths set)
error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid stored block lengths)
error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack
fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted

我有备份的存储库,但唯一包含包文件的备份已经损坏。 所以我认为我必须找到一种方法来从不同备份中检索单个对象,并以某种方式指示Git生成仅包含正确对象的新包。

你能给我提示如何修复我的仓库?


在以前的一些备份中,你的坏对象可能已经被打包在不同的文件中,或者可能是松散的对象。 所以你的对象可能会被恢复。

看起来你的数据库中有一些不好的对象。 所以你可以用手动方式来做。

由于git hash-objectgit mktreegit commit-tree不会编写对象,因为它们在包中找到,然后开始执行此操作:

mv .git/objects/pack/* <somewhere>
for i in <somewhere>/*.pack; do
  git unpack-objects -r < $i
done
rm <somewhere>/*

(您的包从存储库中移出,并再次解压缩;只有好的对象现在在数据库中)

你可以做:

git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

并检查对象的类型。

如果类型为blob:从以前的备份中检索文件的内容(使用git showgit cat-filegit unpack-file ;那么您可以使用git hash-object -w重写当前存储库中的对象。

如果类型是树:你可以使用git ls-tree tree从前面的备份中恢复树; 然后git mktree再次将它写入当前的存储库。

如果类型是commit:与git showgit cat-filegit commit-tree

当然,在开始这个过程之前,我会备份您的原始工作副本。

另外,请看如何恢复损坏的Blob对象。


Banengusk让我走上正轨。 为了进一步参考,我想发布我修复我的存储库损坏的步骤。 我很幸运地找到所有需要的对象,无论是在较旧的包中还是在存储库备份中。

# Unpack last non-corrupted pack
$ mv .git/objects/pack .git/objects/pack.old
$ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack
$ git log
fatal: bad object HEAD

$ cat .git/HEAD 
ref: refs/heads/master

$ ls .git/refs/heads/

$ cat .git/packed-refs 
# pack-refs with: peeled 
aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master

$ git fsck --full 
error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1
error: refs/heads/master does not point to a valid object!
missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919
missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b
dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc

# Copy HEAD object from backup of repository
$ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa
# Now copy all missing objects from backup of repository and run "git fsck --full" afterwards
# Repeat until git fsck --full only reports dangling objects

# Now garbage collect repo
$ git gc
warning: reflog of 'HEAD' references pruned commits
warning: reflog of 'refs/heads/master' references pruned commits
Counting objects: 3992, done.
Delta compression using 2 threads.
fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232)
error: failed to run repack

# Check reflogs...
$ git reflog

# ...then clean
$ git reflog expire --expire=0 --all

# Now garbage collect again
$ git gc       
Counting objects: 3992, done.
Delta compression using 2 threads.
Compressing objects: 100% (3970/3970), done.
Writing objects: 100% (3992/3992), done.
Total 3992 (delta 2060), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.
# Done!

首先尝试以下命令(如果需要,再次运行):

$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase

然后你仍然有问题,试试可以:

  • 删除所有损坏的对象,例如

    fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
    $ rm -v .git/objects/06/91c5...51e5
    
  • 删除所有空的对象,例如

    error: object file .git/objects/06/91c5...51e5 is empty
    $ find .git/objects/ -size 0 -exec rm -vf "{}" ;
    
  • 通过以下方式检查“断开的链接”消息:

    git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
    

    这将告诉你什么文件的腐败blob来自!

  • 要恢复文件,您可能真的很幸运,它可能是您已在工作树中检出的版本:

    git hash-object -w my-magic-file
    

    再次,如果它输出缺少的SHA1(4b945 ..),你现在都完成了!

  • 假设它是一些破旧的旧版本,最简单的方法是:

    git log --raw --all --full-history -- subdirectory/my-magic-file
    

    并且会显示该文件的整个日志(请注意,您拥有的树可能不是顶级树,因此您需要确定它自己在哪个子目录中),那么现在可以重新创建再次丢失散列对象的对象。

  • 获取缺少提交,树木或blob的所有ref的列表:

    $ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
    

    可能无法使用常规分支-d或标记-d命令删除其中的一些ref,因为如果git发现损坏,它们将会死亡。 因此,请使用管道命令git update-ref -d $ ref来代替。 请注意,对于本地分支,此命令可能会在.git / config中将陈旧的分支配置留在后面。 可以手动删除它(查找[branch“$ ref”]部分)。

  • 毕竟refs是干净的,在reflog中可能仍然存在违规提交。 您可以使用git reflog expire --expire = now --all清除所有reflog。 如果您不想丢失所有推荐日志,则可以搜索单个参考文献以查看是否有损坏的推文日志:

    $ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
    

    (注意git rev-list中添加了-g选项。)然后,使用git reflog expire --expire = now $ ref对其中的每一个。 当所有损坏的ref和reflog都没有了,运行git fsck --full来检查版本库是否干净。 摇晃的物体是好的。


  • 下面你可以找到高级命令的用法,如果不明智地使用,可能会导致你的数据在你的git仓库中丢失,所以在你意外地对你的git造成进一步的损害之前进行备份。 如果你知道自己在做什么,试试你自己的风险。


    在获取之后将当前分支拉到上游分支的顶部:

    $ git pull --rebase
    

    您也可以尝试结帐新分支并删除旧分支:

    $ git checkout -b new_master origin/master
    

    要在git中查找损坏的对象以进行删除,请尝试以下命令:

    while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects/1/2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done
    

    对于OSX,请使用sed -E而不是sed -r


    其他想法是从pack文件中解压缩所有对象以重新生成.git / objects内的所有对象,因此请尝试在存储库中运行以下命令:

    $ cp -fr .git/objects/pack .git/objects/pack.bak
    $ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
    $ rm -frv .git/objects/pack.bak
    

    如果上面没有帮助,你可以尝试rsync或从其他仓库复制git对象,例如

    $ rsync -varu git_server:/path/to/git/.git local_git_repo/
    $ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
    $ cp -frv ../other_repo/.git/objects .git/objects
    

    尝试结帐时要修复损坏的分支,如下所示:

    $ git checkout -f master
    fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625
    

    尝试将其从上游移除并重新签出:

    $ git branch -D master
    $ git checkout -b master github/master
    

    如果git让你进入detached状态,checkout master并合并到detached branch中。


    另一个想法是递归地重新设置现有的主设备:

    $ git reset HEAD --hard
    $ git rebase -s recursive -X theirs origin/master
    

    也可以看看:

  • 一些技巧来重建Blob对象以修复损坏的存储库。
  • 如何修复损坏的存储库?
  • 如何从存储库中删除所有损坏的引用?
  • 如何修复损坏的git存储库? (seeques)
  • 如何修复损坏的git存储库? (qnundrum)
  • 与Git一起使用SourceTree时出现错误:'摘要'因代码128失败:致命:无法读取树
  • 恢复损坏的Git裸库
  • 恢复损坏的git存储库
  • 如何解决git错误:对象是empy / corrupt
  • 如何诊断和修复git fatal:无法读取树
  • 如何处理这个git错误
  • 如何修复损坏的git存储库?
  • 我如何在Git的另一个分支上“覆盖”而不是“合并”分支?
  • 如何从另一个分支完全替换git中的master分支?
  • Git:“腐败的松散物体”
  • Git reset =致命:无法读取树
  • 链接地址: http://www.djcxy.com/p/94803.html

    上一篇: How to recover Git objects damaged by hard disk failure?

    下一篇: Git push won't do anything (Everything up