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

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

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

我搜索了 Stack Overflow 和 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

这是一个小型的个人项目; 我通常只在 (主人)中工作,但当时我正在做一个实验(new _ tokenize)。253b086是停电前的最后一次成功提交。

93114 次浏览

It appears that git created files in .git/objects for the new commit, but didn't successfully write to them. I solved it by deleting them one at a time and re-running git fsck --full to find the next one. I started with the one originally reported by 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

And so on. I deleted five objects before git fsck came up clean, corresponding (as I suppose) to the five files in the commit I was trying to make. I guess that the file history was not corrupted at all.

Incidentally, I thought of another method that seems to work as well. git clone copies the bad objects, but git push does not. After backing up, I created a new empty repository (--bare, because otherwise you can't push to master), then unstaged my changes and pushed both branches into the new repository. Then it was just a matter of checking it out again and restoring the latest changes from my backups.

Still interested if anyone cares to shed light on the failure mechanism here.

Simple answer to this question for anyone facing this problem: the git clone command is the fix, if have a remote repo then clone it to the local folder (after deleting the corrupted local repo), in case you dont have remote repo then try to push the corrupt repo to github and then clone it from there, I think that corrupted objects wont be pushed and it will fix the problem

As described in this answer I ran:

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

Which removed all of my dangling blobs and dangling commits, as well as the corrupt db objects.

It was a lot faster than tracking them down one-by-one!

I landed on the same and fixed with a weird way, on Windows, Deleted the .git folder, Cloned the same repo on another folder Copied the .git folder from the new folder to the old repo then git add . git commit -m ... git push ....