如何恢复Git物体损坏的硬盘故障?
-
03-07-2019 - |
题
我有个硬盘故障造成在一些文件的一个混帐存储库获得的损坏。时运行 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 hash-object
, git mktree
和 git 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 show
或 git cat-file
或 git unpack-file
;然后你可以 git hash-object -w
来重写当前存储库中的对象。
如果类型是树:您可以使用 git ls-tree
从以前的备份中恢复树;然后 git mktree
在当前的存储库中再次编写它。
如果类型是commit:与 git show
, git cat-file
和 git 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:
$ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
它不可能去除其中一些裁判使用的正常支d或标签-d命令,因为他们会死如果git通知的腐败。所以用水管的命令git更新ref-d$ref代替。注意情况下的地方分支机构,该命令可能离开旧的分支结构的背后。git/config。它可以手动删除(寻找[部门"$ref"]部分)。
之后所有裁判是干净的,仍然可能破碎的承诺在这种情况。你可以清除所有reflogs令种情况的到期--过期=现在--所有。如果你不想失去所有的reflogs,你可以搜索的个人裁判断reflogs:
$ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
(注意加入-g项下转列表。) 然后,偏种情况的到期--过期=现在$ref上的每一个人。当所有打破裁判和reflogs都走了,git的--全,以便检查存储库是干净的。晃来晃去的目的是确定。
下面你可以找到先进的使用情况的命令,潜在的可能导致失去你的数据仓库,如果不明智地使用,因此作一个备份之前你不小心做进一步损害到你的饭桶。试着在你自己的风险如果你知道你在做什么。
拉目前的分支上的顶级的上游分后取:
$ git pull --rebase
你也可以尝试结帐新的分支,并删除旧的一种:
$ git checkout -b new_master origin/master
找到破坏对象在工清除,尝试以下命令:
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
For OS x,使用 sed -E
而不是的 sed -r
.
其他的想法是要解开所有的对象包文件重新生成的所有物体内。git/对象,因此尝试运行以下命令内的储存库:
$ 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 -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让你进入分离状态,结帐 master
并合并成它的独的分支。
另一个想法是重订现有的总体递归:
$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master
参见:
- 某些技巧,以重建blob对象,以便修复已损坏的储存库。
- 怎么修复一个破碎的仓库?
- 如何消除所有打破裁判从一个仓库?
- 如何修复已损坏的git仓库?(seeques)
- 如何修复已损坏的git仓库?(qnundrum)
- 错误的时候使用SourceTree与文件'Summary'失败的代码128:致命的:无法读取树
- 恢复损坏的Git裸仓库
- 恢复损坏的git仓库
- 如何解决git错误:目的是empy/损坏
- 如何诊断和修复git致命的:无法读取树
- 如何处理这git错误
- 如何修复已损坏的git仓库?
- 我怎么'复盖',而不是"合并"的一个分支在另一个分支?
- 如何更换主分支,完全是,从另一支?
- 文件"腐败的宽松的对象"
- Git重=致命的:无法读取树
以下是我从损坏的blob对象中恢复的步骤。
1)识别腐败斑点
git fsck --full
error: inflate: data stream error (incorrect data check)
error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd
error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing
...
腐败斑点 241091723c324aed77b2d35f97a05e856b319efd
2)将腐败的斑点移到安全的地方(以防万一)
mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/
3)获取腐败blob的父母
git fsck --full
Checking object directories: 100% (256/256), done.
Checking objects: 100% (70321/70321), done.
broken link from tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
to blob 241091723c324aed77b2d35f97a05e856b319efd
父哈希 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180 。
4)获取与腐败blob相对应的文件名
git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
...
100644 blob 241091723c324aed77b2d35f97a05e856b319efd dump.tar.gz
...
在备份或上游git存储库中查找此特定文件(在我的情况下,它是 dump.tar.gz )。然后将其复制到本地存储库中的某个位置。
5)在git对象数据库中添加先前损坏的文件
git hash-object -w dump.tar.gz
6)庆祝!
git gc
Counting objects: 75197, done.
Compressing objects: 100% (21805/21805), done.
Writing objects: 100% (75197/75197), done.
Total 75197 (delta 52999), reused 69857 (delta 49296)
Git checkout实际上可以从修订中挑选出单个文件。只需给它提交哈希和文件名。更详细的信息这里
我想安全修复此问题的最简单方法是恢复到最新的非常规备份,然后从新提交中选择性地挑选未损坏的文件。祝你好运!
如果您的备份已损坏,或者您的备份也有部分损坏,这两个功能可能会有所帮助(如果备份损坏的对象,可能会发生这种情况)。
在您尝试恢复的仓库中运行。
标准警告:仅在您真正绝望并且备份了(已损坏的)回购时才使用。这可能无法解决任何问题,但至少应突出腐败程度。
fsck_rm_corrupted() {
corrupted='a'
while [ "$corrupted" ]; do
corrupted=$( \
git fsck --full --no-dangling 2>&1 >/dev/null \
| grep 'stored in' \
| sed -r 's:.*(\.git/.*)\).*:\1:' \
)
echo "$corrupted"
rm -f "$corrupted"
done
}
if [ -z "$1" ] || [ ! -d "$1" ]; then
echo "'$1' is not a directory. Please provide the directory of the git repo"
exit 1
fi
pushd "$1" >/dev/null
fsck_rm_corrupted
popd >/dev/null
和
unpack_rm_corrupted() {
corrupted='a'
while [ "$corrupted" ]; do
corrupted=$( \
git unpack-objects -r < "$1" 2>&1 >/dev/null \
| grep 'stored in' \
| sed -r 's:.*(\.git/.*)\).*:\1:' \
)
echo "$corrupted"
rm -f "$corrupted"
done
}
if [ -z "$1" ] || [ ! -d "$1" ]; then
echo "'$1' is not a directory. Please provide the directory of the git repo"
exit 1
fi
for p in $1/objects/pack/pack-*.pack; do
echo "$p"
unpack_rm_corrupted "$p"
done
我已经解决了这个问题,添加了一些更改,比如git add -A和git commit。