4

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.

Community
  • 1
  • 1
stripybadger
  • 3,511
  • 3
  • 15
  • 26

5 Answers5

12

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.

jwg
  • 4,761
  • 2
  • 38
  • 56
  • I just hit a scenario where git reflog returned only the last change, since the change before that (the commit that broke) was corrupt. `git reflog` looks in `.git/logs/HEAD` though. That file had my commit hash, so I could check out the commit before everything went wrong. If `git reflog` breaks, check the file it's trying to read: `.git/logs/HEAD` – Steve Armstrong Apr 28 '16 at 18:08
0

In our case the remote git had a corrupted file blob ~28mb. This file should have been ~32mb but somehow became corrupted.

Solution was to copy the blob file from the computer that made the commit, and overwrite the corrupted file on the remote git repository.

AndersLindas
  • 137
  • 1
  • 9
0

I faced a similar problem and followed @jwg solution but couldn't proceed at the git reflog step.

git reflog produced only the following:-

1fd3a1d HEAD@{0}: reset: moving to develop

However, the result was that my git was not corrupt anymore and my code was still untouched after all the modifications. It's just that the changes are un-committed and all the commits I have made were missing.

At this point, I could perform a git-commit -a and lose all the commits but still maintain the latest code.

Then, I noticed a branch temp was created. Inside it was a later version of my code, though not the latest. As an illustration:-

current branch - feature/feature1 (now contains my latest code, but missing most commits)

another branch - temp (does not contain latest code, but has more commits than the current branch

So I proceeded by git commit -a my current branch and then git rebase temp, fixed some conflicts and done! In the end, I still lost some commits but at least the code is the latest.

Edit

turns out I did not have the latest working code, so all I managed to save is some commits. I restored the files with a backup.

daisura99
  • 810
  • 1
  • 10
  • 16
0

This happens when some file(s) in .git folder in the repository is corrupted. Most probably you may not have lost any of your data. File corruption can be caused due to a unexpected power failure. If it is the case, there is a chance for data lose.

In my case, the reason was power failure. I just cloned the remote repo to another location and copied the whole .git folder to my existing local repo. It solved the problem and none of my data was lost.

Mohammed Shareef C
  • 2,784
  • 21
  • 33
-1

An easy fix is to move the old repository somewhere else and reclone it:

$ cd ..
$ mv <repo-name> <repo-name>-original
$ git clone <url> <repo-name>

If there are stuff lost there are ways to retrieve them from the old repository, but first try to reclone it.

Agis
  • 29,320
  • 2
  • 67
  • 77
  • That just gives me `fatal: loose object 7b36029a951eacd979d24e993e020c4d018ca265 (stored in .git/objects/7b/36029a951eacd979d24e993e020c4d018ca265) is corrupt`. – stripybadger Jan 15 '14 at 08:50
  • I can reclone it (I have done actually), but I still have commits in the old working copy that I can't push. "If there are stuff lost there are ways to retrieve them from the old repository" - how? – stripybadger Jan 15 '14 at 09:06
  • @stripybadger This can be tricky but this is the official answer: https://www.kernel.org/pub/software/scm/git/docs/user-manual.html#recovering-from-repository-corruption – Agis Jan 15 '14 at 10:32
  • Thanks for that, I've seen that already in one form or another. It seems to rely on the fact that `git ls-tree` tells you what it is that's corrupt. In my case, `git ls-tree 1df3846c...` gives me the same `fatal: loose ... corrupt` message. So I'm not sure how to apply the instructions given there to my situation. – stripybadger Jan 15 '14 at 13:04
  • This is not an 'easy fix'. It means that all your local commits and branches, everything except the specific version that you currently have in your tree, is lost. – jwg Jun 16 '15 at 14:10