Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git: fetch a specific object from a remote

Tags:

git

At work we have to cope with a very huge git repository (90Go). After having tried to tweak some things on my local copy (I had errors with a pack file, tried to unpack it), I might have deleted some object files. For instance:

> git gc

error: Could not read af9ed8[:snip:]

fatal: bad tree object af9ed8[:snip:]

error: failed to run repack

How can I fetch a specific object (in that case the one with the hash af9ed8...) from a remote repository?

like image 837
Yves Parès Avatar asked Jan 31 '12 16:01

Yves Parès


1 Answers

If you have filesystem access to the remote or any other intact repository containing this object, you should be able to go there and run:

git cat-file tree af9ed8 > 9ed8...

Note that this only requires read-only access to the repo (you can write the file elsewhere) so it should be very safe, and you could even do it as a user who doesn't have write permissions to the filesystem. You can then transfer/copy it into the appropriate place in your repo:

cp path/to/9ed8... .git/objects/af/9ed8...

Loose objects are stored in directories with the first two digits of the hash; the filenames are the rest of the hash.

Edit: If the object is loose on the remote end you could also just directly copy it out of .git/objects, but if it's packed, you'd have to unpack it with git unpack-objects, and I imagine the packfiles in that repo are prohibitively large. The nicest way to do that would be to copy the packfile into your corrupted repo, delete any corrupted objects, and then use git unpack-objects < packfile, which will not unpack any objects which already exist.

I'm not sure how to do it via normal remote commands; even the lower-level git fetch-pack still operates at a ref level, fetching a pack with the necessary commits to complete the ref. I suspect that you might be able to do something sneaky like deleting all of the commit objects which reference that tree (git fsck might help you find them). I was really hoping you might be able to create a tag pointing to that object, push it to the remote, then try to fetch the tag from the remote (coaxing it into fetching the object) but it looks like Git is quite careful not to let you make or manipulate a tag pointing to a nonexistent object.

like image 64
Cascabel Avatar answered Oct 07 '22 03:10

Cascabel