Git存储库已损坏(错误的头检查;松散的对象已损坏)


74

我昨天晚上在写提交消息时遇到了电源故障。当我启动计算机备份时,我无法完成提交。我跑了git reset,重新添加了更改的文件,然后再次尝试,得到了:

% git commit
error: inflate: data stream error (incorrect header check)
error: unable to unpack a94406345ac44982b00cf57b4b9660a35436637f header
fatal: a94406345ac44982b00cf57b4b9660a35436637f is not a valid object

git fsck 显示以下内容:

% git fsck --full
Checking object directories: 100% (256/256), done.
error: inflate: data stream error (incorrect header check)
error: unable to unpack 4346883490a0990e68db0187241abc1642765a73 header
error: inflate: data stream error (incorrect header check)
fatal: loose object 4346883490a0990e68db0187241abc1642765a73 (stored in .git/objects/43/46883490a0990e68db0187241abc1642765a73) is corrupt

我注意到消息抱怨不同的对象。

我搜索了SO和Web,并尝试了一些不同的方法,但无济于事。

  • 我没有最新的备份副本。
  • 将存储库克隆到另一个目录无济于事;新的存储库也存在同样的问题。
  • git stash给出与相同的消息git commit。所有其他git命令似乎都可以正常工作。

我如何分辨出问题所在并解决?

编辑: git log根据建议输出(仅前几行):

% git log --oneline --decorate --all |head -n 8
253b086 (HEAD, new_tokenize) Normalized tokenizer interface slightly
0f2425a (master) Added procs to eval layer
a4d4c22 Added procedures as a type
d1e15ad (tag: v0.10) Added `if' form with tail call semantics
f94a992 (tag: v0.9) Completed environments
031116e Fixed bug where # on a line by itself caused segfault
3d8b09f Added environments, define and set!
01cc624 Put symbol table implementation into types.c

这是一个很小的个人项目。我通常只是在(master)工作,但当时我正在做一个实验(new_tokenize)。253b086是电源故障之前的最后一次成功提交。


也许尝试agit loggit log --oneline --decorate --all看看历史是什么样子
jkyako 2014年

做完了 不确定您要寻找的是什么,请告诉我您想要完整的输出还是什么。我没有做任何花哨的事情
trentcl 2014年

大多数情况下,只是尝试找出由于报告了损坏的对象而最终丢失/无法访问的内容。假设您有任何未提交的本地更改保存在其他地方,您是否能够查看git checkout日志中列出的每个ID?让我想知道是否蛮力的解决方案是在每个ID上编写脚本,签出ID,将工作树复制到其他地方(可能是新的git存储库),以尝试重建无损坏的仓库。
jkyako 2014年

3
刚读完这篇文章,并认为将损坏的对象临时移动到另一个位置并重试该对象git fsck --full以找出当前引用有问题的对象可能会很有趣。
jkyako

1
谢谢@jkyako,这使我走上了正轨。答案即将来临。
trentcl

Answers:


72

似乎git在.git / objects中为新提交创建了文件,但未成功写入文件。我通过一次删除一个来解决它,然后重新运行git fsck --full以查找下一个。我从最初的报道开始git fsck

% rm -f .git/objects/43/46883490a0990e68db0187241abc1642765a73
% git fsck --full
Checking object directories: 100% (256/256), done.
error: inflate: data stream error (incorrect header check)
error: unable to unpack 86e7247af5865e857a3b61eed99986e2d9538df1 header
error: inflate: data stream error (incorrect header check)
fatal: loose object 86e7247af5865e857a3b61eed99986e2d9538df1 (stored in .git/objects/86/e7247af5865e857a3b61eed99986e2d9538df1) is corrupt
% rm -f .git/objects/86/e7247af5865e857a3b61eed99986e2d9538df1
% git fsck --full
Checking object directories: 100% (256/256), done.
error: inflate: data stream error (incorrect header check)
error: unable to unpack a94406345ac44982b00cf57b4b9660a35436637f header
error: inflate: data stream error (incorrect header check)
fatal: loose object a94406345ac44982b00cf57b4b9660a35436637f (stored in .git/objects/a9/4406345ac44982b00cf57b4b9660a35436637f) is corrupt

等等。在git fsck清理干净之前,我删除了五个对象,它们与我想进行的提交中的五个文件相对应(按照我的设想)。我想文件历史记录根本没有损坏。

顺便说一句,我想到了另一种似乎也可行的方法。git clone复制不良对象,但git push不复制。备份后,我创建了一个新的空存储库(--bare,因为否则将无法推送至主存储库),然后取消暂存我的更改并将两个分支都推送到新存储库中。然后,只需再次签出并从备份中还原最新更改即可。

如果有人愿意在这里阐明故障机制,仍然很感兴趣。


2
此外后这些步骤做del .git\indexgit reset
ozba

@ozba请详细说明。如果有理由这样做,我会将其添加到我的答案中,但是对于我而言,这不是必需的。
trentcl

就我而言,这很有必要,因为索引也已损坏
ozba

@ozba如何确定在这种情况下索引是否已损坏?它会带来其他错误还是略有不同?
trentcl

是的,例如,即使您在说明了所有步骤之后,仍然执行git status,它仍然表示无法读取对象XXX。
ozba

9

对于任何面临此问题的人,此问题的简单答案:git clone命令是解决方案,如果有远程仓库,则将其克隆到本地文件夹(在删除损坏的本地仓库后),以防万一您没有远程仓库。将损坏的存储库推送到github,然后从那里克隆它,我认为损坏的对象不会被推送,它将解决问题


7
它可能会“解决”问题,但是您将丢失损坏的文件。
劳伦斯·多尔

我尝试了接受的答案,但是它对我不起作用,但是wincent.com/wiki/Dealing_with_Git_repo_corruption起作用了,并且与您的想法类似-很大的警告是它失去了对本地分支机构的了解-我很幸运我被推到了一个偏僻的地方文件损坏之前分支,因为我可以在克隆后获取更改
Nathan Beck

8

这个答案中所述,我跑了:

git reflog expire --expire-unreachable=now --all
git gc --prune=now

删除了所有悬空的Blob和悬空的提交以及损坏的db对象。

这比一个一个地追踪他们要快得多!


14
git gc --prune = now只是给了我同样的错误:错误的标头
IcedD​​ante
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.