git "loose object ... is corrupt" - what data have I lost?

git

Solution

I fixed this problem on my git repository, where I believe it was caused by a dodgy filesystem (on a Linux virtual machines hosted on Windows) acting up on a hard reset.

I started out in the same place as you, with:

jack@machine:~/git/cs$ git status
error: object file .git/objects/2e/f529faaaed03b2384b9f4d49a2ea95d7833894 is empty
error: object file .git/objects/2e/f529faaaed03b2384b9f4d49a2ea95d7833894 is empty
fatal: loose object 2ef529faaaed03b2384b9f4d49a2ea95d7833894 (stored in .git/objects/2e/f529faaaed03b2384b9f4d49a2ea95d7833894) is corrupt

Before doing anything, I backed up the whole tree by making a recursive copy of it into another folder. Do this.

Then I forcibly removed the object which was corrupt:

jack@machine:~/git/cs$ rm .git/objects/2e/f529faaaed03b2384b9f4d49a2ea95d7833894 
rm: remove write-protected regular empty file ‘.git/objects/2e/f529faaaed03b2384b9f4d49a2ea95d7833894’? y

I then got a different problem which prevented me from running any git commands:

jack@machine:~/git/cs$ git status
fatal: bad object HEAD

Instead of doing a `checkout` as some people recommend to get `HEAD` back to a good state, I did `reset`. `checkout` changes both the state of your tree and the branch that you are on. `reset` (without `--hard`) changes the branch that you are on, but doesn't change any of the files. I wanted to keep all the files I had in their current state, all the more so since they are the only record of my recent commits (since the branch that I am on, has some problem, and can't be logged).

When I last could use git, I was on a feature branch, call it `feature_foo`. I couldn't reset to `feature_foo` since it pointed to the deleted commit `2ef529fa..` I reset to `master`. I believe it doesn't matter where you reset to, any other branch should do.

jack@machine:~/git/cs$ git reset master
Unstaged changes after reset:
M   a/bunch/of_changes
M   more/changes
error: Trying to write ref ORIG_HEAD with nonexistent object 2ef529faaaed03b2384b9f4d49a2ea95d7833894
error: Cannot update the ref 'ORIG_HEAD'.

Now I am on `master`, but with the same file tree that I had before. Since `feature_foo` was quite different from `master`, I see loads of unstaged, uncommitted changes. This is normal. I think the message about `ORIG_HEAD` just means that git records my previous location somewhere, and right now it's not happy because my previous location is the deleted commit.

Now that I have a proper `HEAD`, I can do `git reflog`:

jack@machine:~/git/cs$ git reflog
61ac654 HEAD@{0}: commit: Commit message from a commit I did earlier
f9a1ce9 HEAD@{1}: commit: Another commit message
b26a6e9 HEAD@{2}: commit: Yet another commit message

Here I see that all the commits I did on the feature branch before losing my work are still there. I think that only the most recent one, `2ef529fa..` was lost of course. I would like to reset to `HEAD@{1}` to be back on a branch with these commits.

jack@machine:~/git/cs$ git reset HEAD@{1}
fatal: Log .git/logs/HEAD is corrupt.

So I open this file to edit it:

jack@machine:~/git/cs$ vim .git/logs/HEAD

This file looks like a bunch of SHA1s and commit messages, until the last few lines:

b26a6e99762e703914dc3749fe136d99e100ac74 f9a1ce9c9eaa54b51aa29efdeafec023202de470 Jack <jack@example.com> 1434447540 +0100  commit: Another commit message
f9a1ce9c9eaa54b51aa29efdeafec023202de470 420ded21ffed88a2865cc0adaf3f54b0b44864e2 Jack <jack@example.com> 1434449503 +0100  commit: Commit message from a commit I did earlier
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@2ef529faaaed03b2384b9f4d49a2ea95d7833894 53b404d482a426046f2de6484b8855d1154b7fca Jack <jack@example.com> 1434465895 +0100  reset: moving to master

In other words, I see the same valid commits in the reflog, then a bunch of garbage, then a commit which shows me resetting to `master` FROM the invalid commit (scroll right to see it).

I delete all the garbage and everything past it, then save the file. Now I can look at the reflog again:

jack@machine:~/git/cs$ git reflog
61ac654 HEAD@{0}: commit: Commit message from a commit I did earlier
f9a1ce9 HEAD@{1}: commit: Another commit message
b26a6e9 HEAD@{2}: commit: Yet another commit message

Now, the abbreviated SHA1 from the first line, `61ac654`, seems to point to `master`. This is confirmed by me looking further down the reflog and seeing the same SHA1 appear in other places, when I was on `master`. Furthermore, doing `git reset HEAD@{0}` doesn't do anything at all. But if I do:

jack@machine:~/git/cs$ git reset HEAD@{1}
Unstaged changes after reset:
M   just/a/few_changes

The small number of unstaged changes shows me that my file tree is now very close to what I have committed in Git. Doing `git log` confirms that I have all the commits I saw in the reflog in my history now, except for the first one. So I just have to re-commit this commit, and the naughty one `2ef529f` to get exactly back to where I started!

This took some figuring out, but meant I didn't lose the dozen or so commits since my last push.

Problem

I have made a few commits to a local branch, then I tried to do `git fetch`. It failed with the following errors: ``` fatal: loose object 7b36029a951eacd979d24e993e020c4d018ca265 (stored in .git/objects/7b/36029a951eacd979d24e993e020c4d018ca265) is corrupt fatal: unpack-objects failed ``` Running `git fsck` just shows the same as the first line. Any command that would actually commit or push my changes seems to fail for the same reason. The file appears to just contain a load of zeros. I've seen how to fix GIT error: object file is empty? in which someone reports success resolving this by deleting the file that is corrupt. My question is: if I go through deleting every file that it says is corrupt, what will I lose? Will I actually lose any commits? Note I'm not sure how I got into this state, though it happened after my pc blue-screened, so maybe that caused it.

Original source

Related problems