How can I repair a git repository with a missing object?
Asked Answered
A

5

15

My development repository at some point lost an object.

$ git fsck
fatal: failed to read object 2dddc84156fa30e4614a7ea5a1895885011b8db8: Invalid argument
$ git cat-file -t 2dddc84156fa30e4614a7ea5a1895885011b8db8
error: unable to find 2dddc84156fa30e4614a7ea5a1895885011b8db8
fatal: git cat-file 2dddc84156fa30e4614a7ea5a1895885011b8db8: bad file

A freshly cloned repository has that object.

$ git cat-file -t 2dddc84156fa30e4614a7ea5a1895885011b8db8
tree

I would like to keep my development repository, it has unpushed branches and stashes.

How can I patch that object into my broken repository?

Ashcan answered 1/12, 2011 at 20:24 Comment(1)
similar: #4930174Rivulet
H
10

What you can try, is to get the file .git/objects/2d/ddc84156fa30e4614a7ea5a1895885011b8db8 from the freshly cloned repository and copy it to your development repo ...

Hyperaesthesia answered 1/12, 2011 at 20:35 Comment(2)
Hmm, that doesn't exist in the fresh repo. .git/objects/ contains an empty info/ and pack/pack-dce082ac46b5bd850378e93f384a1b8e01e3b87a.idx plus pack/pack-dce082ac46b5bd850378e93f384a1b8e01e3b87a.pack. git unpack-objects -r < .git/objects/pack/pack-dce082ac46b5bd850378e93f384a1b8e01e3b87a.pack claims it unpacked 100% but I can't find them.Ashcan
OIC, I need to unpack them in a fresh repo. Is there any harm in cd /path/to/broken-repo; git unpack-objects < /path/to/clean-repo/.git/objects/pack/pack-blahblah to just get everything which might be missing or corrupted?Ashcan
E
15

I recently had a bunch of missing objects in a local repository and an uncorrupted reference repository to restore it from. Here's the magic I came up with that worked for me:

cd <path-to-local-repo>
git unpack-objects < <reference-repo-path>/objects/pack/pack-<hash>.pack

It turns out that all of the objects I needed were in a pack file in the reference repository instead of in separate "loose" object files. This simple incantation unpacks that pack file into the local database, filling in the holes. After doing

git gc

to cleanup any dangling commits (i.e. due to rebasing, amend commits, etc.) my git fsck is now clean.

Eimile answered 7/3, 2015 at 4:59 Comment(2)
Perfect! Worked really well! Thanks!Clack
Worked for me as well, can confirm.Pretend
H
10

What you can try, is to get the file .git/objects/2d/ddc84156fa30e4614a7ea5a1895885011b8db8 from the freshly cloned repository and copy it to your development repo ...

Hyperaesthesia answered 1/12, 2011 at 20:35 Comment(2)
Hmm, that doesn't exist in the fresh repo. .git/objects/ contains an empty info/ and pack/pack-dce082ac46b5bd850378e93f384a1b8e01e3b87a.idx plus pack/pack-dce082ac46b5bd850378e93f384a1b8e01e3b87a.pack. git unpack-objects -r < .git/objects/pack/pack-dce082ac46b5bd850378e93f384a1b8e01e3b87a.pack claims it unpacked 100% but I can't find them.Ashcan
OIC, I need to unpack them in a fresh repo. Is there any harm in cd /path/to/broken-repo; git unpack-objects < /path/to/clean-repo/.git/objects/pack/pack-blahblah to just get everything which might be missing or corrupted?Ashcan
R
7

It pretty much boils down to this: do you have a backup of that file (.git/objects/2d/ddc84156fa30e4614a7ea5a1895885011b8db8) anywhere? If you can find it, copy it back to your git repository and everything will be good again. In other words, do you know if the repository has been cloned? If it has, you will find that file in the clone's git folder and copy it to yours. If you have not cloned the repository, have you zipped it up somewhere? If you're on a mac, have you checked Time machine? If you're not on a mac, are you using something to backup your code?

It basically boils down to this: You need a backup of that file. Git is designed so that when this happens, you just use the backup (which is a clone of the repository) to restore the file. That said, the file name is based on an SHA1 hash, so if you can find that filename in anyone else's repository, chances are pretty good that you can use it in your own :)

It is usually good practice to always clone your repositories to another location, for safe keeping in case something like this happens. This is also why services like github and bitbucket are so popular.

You also probably want to look at this question: How to recover Git objects damaged by hard disk failure?

Rodeo answered 1/12, 2011 at 20:54 Comment(2)
He stated that he has a freshly cloned repository (see 2nd code snippet). And just a simple thing: The git file name is sha1, not md5 :)Hyperaesthesia
Thanks. Updated my answer :). Also, if your freshly cloned repository has that object, what @Hyperaesthesia has suggested will fix the problem.Rodeo
L
2

I encountered this issue because some objects in the old branches/tags are missing for unknown reasons. (I suppose it might relate to git gc, and these branches/tags are based on remote usually force-pushed refs)

So the solution is to remove these broken branches/tags.

$ git fsck --name-objects # find the broken refs
$ git for-each-ref
$ git update-ref -d xxx # remove the broken refs found

$ git branch -r | xargs -i git branch --delete --force --remotes {} # delete all remote branches locally
$ git branch -r | xargs -i git update-ref -d refs/remotes/{}
$ git tag -d $(git tag -l) # delete all local tags

Then re-fetch from remote:

$ git fetch origin --prune

Also, you can try git-repair tool:

$ sudo apt install git-repair
$ git repair
Laguna answered 1/2 at 11:25 Comment(0)
C
0

Starting git version 2.36.0 released Apr 15 2022 git fetch --refetch fetches all objects without thinking what it should have locally. If the missing object is at the remote, it'll fix it.

But sometimes the missing object is local. If you have had it locally for example in .git/objects/info/alternates, you need to go see if you still have it somewhere. git fetch --refetch _repository_ to that repository will fetch all that is there.

But if it is gone, it is then gone. In that situation, you need to see what points to it and see if you should salvage anything of those and cherry-pick or go low-level to make new trees (git mktree) for some new commits (git commit-tree) and create or update a ref to point to the commits (git update-ref) before you drop your references to the commits that no longer can reach all objects.

Curb answered 16/8 at 18:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.