Git存储库损坏(不正确的标头检查;松散的对象已损坏)

tre*_*tcl 62 git corrupt

昨天晚上我在写一个提交消息时遇到了电源故障.当我启动机器备份时,我无法完成提交.我跑了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
Run Code Online (Sandbox Code Playgroud)

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

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

我搜索了SO和网络并尝试了一些不同的东西,但无济于事.

  • 我没有最近的备份副本.
  • 将存储库克隆到另一个目录没有帮助; 新的存储库展示了完全相同的问题.
  • 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
Run Code Online (Sandbox Code Playgroud)

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

tre*_*tcl 66

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

等等.我在git fsck清理之前删除了五个对象,对应(我猜)对应的提交中的五个文件.我想文件历史记录根本没有损坏.

顺便说一下,我想到了另一种似乎也能起作用的方法.git clone复制坏对象,但git push不复制.备份后,我创建了一个新的空存储库(--bare,因为否则你无法推送到主服务器),然后取消暂停我的更改并将两个分支推送到新的存储库.然后只需再次检查它并从备份中恢复最新的更改.

仍有兴趣,如果有人关心这里的失败机制.

  • 在这些步骤之后还要执行`del .git\index`和`git reset` (2认同)

Too*_*ooL 8

面对这个问题的任何人都可以简单回答这个问题:git clone命令是修复,如果有远程仓库然后将其克隆到本地文件夹(删除损坏的本地仓库后),万一你没有远程仓库然后尝试将腐败的repo推送到github,然后从那里克隆它,我认为被破坏的对象不会被推,它将解决问题

  • 它可能会"修复"问题,但您将丢失损坏的文件. (5认同)

Bit*_*Bot 7

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

git reflog expire --expire-unreachable=now --all
git gc --prune=now
Run Code Online (Sandbox Code Playgroud)

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

这比一对一地追踪它们要快得多!

  • git gc --prune = now只给我同样的错误re:错误的头 (3认同)