9

I have a Windows box which has taken it into it's head to delete most of a Git repository (must have tripped the Important Work Detector ;). All I have left (that I can find) is the objects. I'm not sure how complete the collection of objects is, either. Is it possible to recover things from just the objects? As far as I can tell, the object tree is intact. All the packs and loose objects are in place; I just don't have the metadata to convince Git.

Jashank Jeremy
  • 360
  • 1
  • 4
  • 14

3 Answers3

16

The first thing that I would try is to initialize a new repository with git init. Then I'd copy the objects directory from the dead repository into the new repository. Then I'd run git fsck in the new repository.

With some luck you'll see a whole lot of dangling objects and with a bit more luck some of the dangling objects will be commit objects which will be the tips of lost branches.

If you run git show and/or git log on these commits you may be able to recognize some of the branches.

To "recover" them you can just use git branch to recreate named branches.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • Awesome! I have one bad SHA-1 file which I need to work out how to rename (Witless renamed it to `e` which isn't helpful), and I need to reattach my HEAD, but that worked excellently. Cheers, Charles! – Jashank Jeremy Apr 24 '11 at 00:02
  • 1
    I'm not sure how to find the original name of a commit, but reattaching the HEAD was as simple as `git checkout ` then creating a `master` branch. Now, I need to find what `00/e` _should_ be. – Jashank Jeremy Apr 24 '11 at 01:09
  • @Jashank: If the loose object is valid, you can also “trick” Git into reading it from a (presumably) unrelated loose object pathname (“corruption” demonstrated in [SO5585388](http://stackoverflow.com/questions/5585388)) and then writing it to the right path. `bash -c 'i=1; while n=$(printf %040x $i) && git cat-file -s "$n" >/dev/null 2>&1; do let i++; done; p=$(printf .git/objects/%.2s/%s "$n" "${n#??}"); echo "using temp object name $n at $p"; set -x; cp -p "$1" "$p" && t=$(git cat-file -t "$n") && git cat-file "$t" "$n" | git hash-object --stdin -t "$t" -w && rm -f "$p"' - .git/objects/00/e` – Chris Johnsen Apr 24 '11 at 04:08
  • @Chris - That's just ... woah. That takes the cake for the best twisted Bash I've ever seen. I _did_ manage to recover the file: Git reported a file deleted from the checkout, so I went hunting, found the file, and moved it in. – Jashank Jeremy Apr 25 '11 at 04:23
0

If you haven't already tried git checkout master, I'd start with that.

Ben Hocking
  • 7,790
  • 5
  • 37
  • 52
  • 1
    It can't find a Git repository. "fatal: Not a git repository (or any parent up to mount parent ). Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)." – Jashank Jeremy Apr 23 '11 at 23:22
0

try using this post

How to recover Git objects damaged by hard disk failure?

that answer may have some *nix related info. Let me know if it helps.

Ill see what it does.

Community
  • 1
  • 1
The Lazy Coder
  • 11,560
  • 4
  • 51
  • 69
  • it looks like the first couple commands may be helpful. It shows you how to unpack the pack folder from the objects – The Lazy Coder Apr 23 '11 at 23:35
  • Yeah, I'll take that for a spin. Do I need to init a new Git repo now? – Jashank Jeremy Apr 23 '11 at 23:36
  • probably not. I would recommend backing up what you have so you dont lose any more. I gotta run for now. Ill check back in when I get back. – The Lazy Coder Apr 23 '11 at 23:37
  • I don't think that this is the optimal approach. There's no evidence that objects have been damaged so unpacking and recovering objects shouldn't be necessary. It should be enough to recover the objects - packed or loose - into a working git repository and going from there. – CB Bailey Apr 23 '11 at 23:48
  • If you have examples of how to do that I will be more then willing to put them up – The Lazy Coder Apr 24 '11 at 03:18