4

I have a corrupted loose object.

I tried checkout, revert, rebase and may be few other things to go to an original commit. In each case I ran git fsck and still had the same problem:

> git fsck 
error: corrupt loose object '25a196217ebb6e341909205575f491022eafc4d9'
fatal: loose object 25a196217ebb6e341909205575f491022eafc4d9 (stored in .git/objects/25/a196217ebb6e341909205575f491022eafc4d9) is corrupt

is there a way to get rid of corrupted objects without simply deleting .git? I don't have another backup so I can't replace the corrupted object.

It's a more narrow question that arose from this git "error: corrupt loose object" after moving a directory

update (1):

> git gc
Counting objects: 747, done.
Delta compression using up to 8 threads.
error: corrupt loose object '25a196217ebb6e341909205575f491022eafc4d9'
fatal: loose object 25a196217ebb6e341909205575f491022eafc4d9 (stored in .git/objects/25/a196217ebb6e341909205575f491022eafc4d9) is corrupt
error: failed to run repack

update (2): this didn't work either Remove file from git repository (history)

update (3): cloning didn't work:

> git clone ../dynamicsCode_good/ .
Cloning into ....
done.
error: corrupt loose object '25a196217ebb6e341909205575f491022eafc4d9'
fatal: loose object 25a196217ebb6e341909205575f491022eafc4d9 (stored in .git/objects/25/a196217ebb6e341909205575f491022eafc4d9) is corrupt

the . directory is empty

update (4): removing a corrupted object.

> git --version
git version 1.7.5.4


> rm -f .git/objects/25/a196217ebb6e341909205575f491022eafc4d9
13:42:57 ~/Dropbox/work/dev/dynamicsCode_torek 
> git fsck --full
missing blob 25a196217ebb6e341909205575f491022eafc4d9
dangling tree 64a970c878fef7deeeb4ce2ffc5e6234a72894ad
dangling tree 528e6c121fb8e56097462b2ebb9ec4de66388ce2

first (initial) comment. this comment doesn't even have the corrupted file.

> git log |tail -5
commit 150ceebafb9c20769386cc7ffba07f6e6565fae6
Author: Kirill ...gmail.com>
Date:   Tue Sep 27 22:51:15 2011 -0400

    state takes input as input
checkout:

> git checkout -b 150ceebafb9c20769386cc7ffba07f6e6565fae6
Switched to a new branch '150ceebafb9c20769386cc7ffba07f6e6565fae6'

> git gc
Counting objects: 783, done.
error: unable to find 25a196217ebb6e341909205575f491022eafc4d9
Compressing objects: 100% (776/776), done.
fatal: unable to read 25a196217ebb6e341909205575f491022eafc4d9
error: failed to run repack
> git fsck --full
broken link from    tree 4668817140320ad2e04aa946d95dec2c3885d97b
              to    blob 25a196217ebb6e341909205575f491022eafc4d9
missing blob 25a196217ebb6e341909205575f491022eafc4d9
dangling tree 64a970c878fef7deeeb4ce2ffc5e6234a72894ad
dangling tree 528e6c121fb8e56097462b2ebb9ec4de66388ce2

I also tried unpacking the only object in the .git/objects/pack/ directory. didn't help.

I also cloned this state into a new directory:

> git gc
Counting objects: 662, done.
error: unable to find 25a196217ebb6e341909205575f491022eafc4d9
Compressing objects: 100% (656/656), done.
fatal: unable to read 25a196217ebb6e341909205575f491022eafc4d9
error: failed to run repack
14:40:34 ~/Dropbox/work/dev/dynamicsCode_torek_commit_clone 
> git fsck 
broken link from    tree b5ab6b287804d5069a3c8648ace38d9d9feac1a5
              to    blob 25a196217ebb6e341909205575f491022eafc4d9
dangling commit dad8edc620248d3911b7b1c0a99608a64e0288a3
missing blob 25a196217ebb6e341909205575f491022eafc4d9
dangling tree 64a970c878fef7deeeb4ce2ffc5e6234a72894ad
dangling commit ae2b2a9edb744d9e91aa78891c849d5a0040ea94
dangling commit 32ed79bd4ac70b118d046cb6093a4710562e95ba
dangling commit 7e45ef0c6ffc46401b1f82bcbf0f7e843abf9e31
dangling tree 528e6c121fb8e56097462b2ebb9ec4de66388ce2
14:40:40 ~/Dropbox/work/dev/dynamicsCode_torek_commit_clone 
> git branch 
* 150ceebafb9c20769386cc7ffba07f6e6565fae6

didn't help either.

The corrupted file is tags from ctags. I don't need it. it's strange that i can't rebuild git without that file. Most importantly, from all my research I don't see neither how it can be done nor why it's not possible.

update (5): checkout without branching

> git checkout 150ceebafb9c20769386cc7ffba07f6e6565fae6
Note: checking out '150ceebafb9c20769386cc7ffba07f6e6565fae6'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 150ceeb... state takes input as input
16:41:40 ~/Dropbox/work/dev/dynamicsCode_torek_commit 
> git fsck --full
broken link from    tree 4668817140320ad2e04aa946d95dec2c3885d97b
              to    blob 25a196217ebb6e341909205575f491022eafc4d9
missing blob 25a196217ebb6e341909205575f491022eafc4d9
dangling tree 64a970c878fef7deeeb4ce2ffc5e6234a72894ad
dangling tree 528e6c121fb8e56097462b2ebb9ec4de66388ce2
Community
  • 1
  • 1
kirill_igum
  • 3,953
  • 5
  • 47
  • 73
  • You might try cloning that repository. Cloning should only take the "necessary" objects into a new repo, so as long as that loose object is really "unnecessary" for your clone, you might have a corruption-free repo in your clone. – Mark Rushakoff Apr 07 '12 at 05:32
  • If you want to remove the corrupt object, you can simply delete it. E.g. `rm .git/objects/25/a196217ebb6e341909205575f491022eafc4d9` from the repo root. But I'm not sure what will happen if another object references it. – svick Apr 07 '12 at 09:20
  • @MarkRushakoff cloning didn't work. see update (3) – kirill_igum Apr 07 '12 at 17:32

1 Answers1

2

If you remove the corrupted object manually, git will generally let you get at everything else. I deliberately corrupted a git blob (just forced a few bad bytes in the front) and got the following:

$ git fsck
fatal: object bd1b260b0ef92d1a219e1183953fa1ac7cdb4cad is corrupted
$ git gc
Counting objects: 23, done.
error: unable to unpack bd1b260b0ef92d1a219e1183953fa1ac7cdb4cad header
error: inflateEnd: failed
Delta compression using up to 2 threads.
Compressing objects: 100% (12/12), done.
fatal: object bd1b260b0ef92d1a219e1183953fa1ac7cdb4cad is corrupted
error: failed to run repack
$ git fsck --full
fatal: object bd1b260b0ef92d1a219e1183953fa1ac7cdb4cad is corrupted
$ rm -f .git/objects/bd/1b260b0ef92d1a219e1183953fa1ac7cdb4cad
$ git fsck --full
broken link from    tree a3070cb66fd169e1443867a8bb137a44103c9f24
              to    blob bd1b260b0ef92d1a219e1183953fa1ac7cdb4cad
missing blob bd1b260b0ef92d1a219e1183953fa1ac7cdb4cad
$ git cat-file -p 2418b6ba8fd0289933c9351260a272b8e410867f
tree a3070cb66fd169e1443867a8bb137a44103c9f24
parent 8d945134b0cead535d66af29c8eb4228b5dc3763
author [redacted] 1333789753 -0600
committer [redacted] 1333789753 -0600

test corrupted object
$ git checkout 2418b6ba8fd0289933c9351260a272b8e410867f
error: git checkout-index: unable to read sha1 file of morefile (bd1b260b0ef92d1a219e1183953fa1ac7cdb4cad)
D   morefile
Note: checking out '2418b6ba8fd0289933c9351260a272b8e410867f'.

You are in 'detached HEAD' state. ...

Note, somewhere along the way it re-pointed the branch master to a previous "good" commit (not the immediately-previous one, and I have no idea why) so you may then have to repair your commit history, etc. But everything was there, except for the missing file "morefile" whose blob I corrupted. (I restored it from a backup copy I made in advance and was even able to get the file back, with git checkout -- morefile. You could mv the corrupted blob somewhere and see if you can recover some of your data from it.)

I'd certainly back up the broken git repo first, Just In Case. :-)

torek
  • 448,244
  • 59
  • 642
  • 775
  • our git fsck is a little different. I did the same thing that you did. And, tried cloning. didn't work. see update(4). Either way, I appreciate a detailed answer from you. – kirill_igum Apr 07 '12 at 19:18
  • BTW the magic number above (2418b...) came from scrolling back up to see what it was before I smashed the one blob-object. When you say "didn't work", you mean "git checkout " doesn't get you a populated working tree? I was testing this on my laptop where I have 1.7.0.3 installed. – torek Apr 07 '12 at 20:08
  • 1) yes, i figured that. I used my initial comment (see `git log |tail -n5` in update (4)). the comment doesn't even have the corrupted file; so it is a good comment. 2) i'm not sure if it populates the tree or not but `fit fsck` still gives an error, see update (5). – kirill_igum Apr 07 '12 at 20:50
  • 1
    The "broken link" is fine; the goal here is to be able to check out all (or at least "enough") good commits to have something useful. If you get a good work tree, you can copy (or `git archive` or whatever) it over to a new place and build a whole new git repo, minus the bad file(s), that retains as much history as you care to recover. Or, you can use `filter-branch` to truncate some history from the (duplicate of) the original repo. Either way you'll wind up with new commit IDs though. – torek Apr 07 '12 at 21:36
  • Ah, that make sense now. I can access the previous builds. so I guess I have to just copy the tree. Do you know a good way to do it? the ones that I saw relied on `.git/objects/pack` but in my case it's empty. should I write a script that checkouts each commit, copies files to a new directory and than commits it to new .git? – kirill_igum Apr 07 '12 at 21:43
  • I haven't actually tried to recover a broken git repo like this so I don't know if there's a "best way". Seems like a sequence of `git archive` ops, or `git checkout`s with `GIT_DIR` and `GIT_WORK_TREE` env vars set up, would be a good way to get the tree copied elsewhere. Or, grab a copy of the actual filter-branch script (it's `/usr/libexec/git-core/git-filter-branch` or similar), and whack on it. :-) – torek Apr 07 '12 at 21:49