【问题标题】:Git repository corrupt (incorrect header check; loose object is corrupt)Git 存储库损坏(标头检查不正确;松散对象已损坏)
【发布时间】:2014-07-06 17:10:25
【问题描述】:

昨天晚上我在写提交消息时遇到了电源故障。当我重新启动机器时,我无法完成提交。我跑了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

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

我搜索了 StackOverflow 和 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 是断电前最后一次成功的提交。

【问题讨论】:

  • 也许可以试试git loggit log --oneline --decorate --all 看看历史是什么样子的
  • 完成。不确定您到底在寻找什么,如果您想要完整的输出或什么,请告诉我。我没有做任何花哨的事情
  • 鉴于报告的损坏对象,主要是想弄清楚最终丢失/无法访问的内容。假设您在其他地方保存了任何未提交的本地更改,您可以git checkout 日志中列出的每个 id 吗?让我想知道是否暴力解决方案是在每个 id 上编写脚本,签出 id,将工作树复制到其他地方(可能是一个新的 git 存储库)以尝试重建一个非损坏的存储库。
  • 刚刚阅读了this post 并认为将损坏的对象临时移动到另一个位置并重试git fsck --full 以找出当前引用有问题的对象可能会很有趣。
  • 感谢@jkyako,这让我走上了正轨。答案即将到来。

标签: git corrupt


【解决方案1】:

似乎 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,否则您无法推送到 master),然后取消暂存更改并将两个分支都推送到新存储库中。然后只需再次检查它并从我的备份中恢复最新更改即可。

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

【讨论】:

  • 在这些步骤之后也做del .git\indexgit reset
  • @ozba 请详细说明。如果有理由这样做,我会将其添加到我的答案中,但在我的情况下没有必要。
  • 在我的情况下这是必要的,因为索引也已损坏
  • @ozba 在这种情况下如何判断索引是否损坏?它会给出额外的或略有不同的错误吗?
  • 是的,如果你做 git status 例如,即使在你说明的所有步骤之后,它仍然说它无法读取对象 XXX。
【解决方案2】:

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

【讨论】:

  • 它可能会“修复”问题,但您会丢失损坏的文件。
  • 我尝试了接受的答案,但它对我不起作用,但 wincent.com/wiki/Dealing_with_Git_repo_corruption 起作用并且与您的想法相似 - 有一个很大的警告是它失去了对本地分支机构的跟踪 - 我很幸运我有在文件损坏之前推送到远程分支,因为我可以在克隆后获取更改
【解决方案3】:

this answer中所述,我跑了:

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

这删除了我所有的悬空 blob 和悬空提交,以及损坏的数据库对象。

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

【讨论】:

  • git gc --prune=now 只是给了我同样的错误:不正确的标题
【解决方案4】:

我降落在同一个地方并以一种奇怪的方式固定, 在 Windows 上, 删除了.git 文件夹, 在另一个文件夹上克隆了相同的 repo 将 .git 文件夹从新文件夹复制到旧仓库 然后 git add . git commit -m ... git push ....

【讨论】:

    猜你喜欢
    • 2011-05-14
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 2010-12-05
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多