3

I'm not entirely sure what happened, but for some reason my git repository's master ref file is now empty. We're hosting the repository on Dropbox, so maybe it has to do with that..but now I can't pull from it. It says this:

Your configuration specifies to merge with the ref 'master' from the remote, but no such ref was fetched.

Dropbox keeps versions of files, so if I go back to the previous version of 'master' it says:

fatal: object 2d154f82e59a4156a5d3ea04a0617c243ae6dc3a is corrupted
fatal: The remote end hung up unexpectedly

How do I recover from this?

Phil Miller
  • 36,389
  • 13
  • 67
  • 90
robev
  • 1,909
  • 3
  • 23
  • 32
  • Is the commit referred to by the previous verson of the remote's master branch available in your local repository (or anyone else's)? – Cascabel Mar 09 '11 at 04:53
  • the one on my local repository gives me the corruption error above when I replace it with the current one. – robev Mar 09 '11 at 16:11
  • So... your local repository is corrupt? (run `git fsck`) Your question really implied these issues were with the remote. – Cascabel Mar 09 '11 at 19:09
  • They are. The local repository isn't – robev Mar 10 '11 at 18:35

1 Answers1

7

Sigh.

I like Dropbox, but I would never recommend it for “hosting” Git repositories. Its synchronization works well enough for single-file documents, but it does not come close to providing the distributed/remote filesystem semantics that would be required for safe hosting of a Git repository.

Hopefully you are just “hosting” a bare Git repository on Dropbox. If so, you should be able to cobble together the commits and references from your non-bare (working) repositories. It should also be possible to manually recover your existing repository, but you will likely end up needing to copy objects from your other repositories anyway, so you might as well do it the following “high level” way (instead of going “low level” and dealing with copying objects from other repositories (or copying pack files and unpacking parts of them)).

Start by making an independent clone of one of your working directories.

git clone file://path/to/myrepo /path/to/myrepo-recovery-work

Import the refs and objects from your other working repositories.

# If you have network access to the other repositories:
cd /path/to/myrepo-recovery-work
git remote add other1 user@machine:path/to/other/working-repo-1
git remote add other2 ssh://user@machine/path/to/other/working-repo-2
# etc.
git fetch --all


# If you do not have network access:
cd /path/to/other/working-repo-1 &&  # on machine with working-repo-1
  git bundle create /path/to/other1.gitbundle --all HEAD
cd /path/to/other/working-repo-2 &&  # on machine with working-repo-2
  git bundle create /path/to/other2.gitbundle --all HEAD
# etc.
# Transfer the bundle files to the machine that has "myrepo-recovery-work"
# (Dropbox is OK to copy the bundles, they are just single files),
# then on that machine:
cd /path/to/myrepo-recovery-work
git remote add other1 /path/to/transferred/other1.gitbundle
git remote add other2 /path/to/transferred/other2.gitbundle
# etc.
git fetch --all

Then, look through all the branches on your new remotes and determine which branches should point to which commits for your rebuilt central repository.

git log --oneline --graph --decorate --abbrev-commit --all
# In addition to looking at the history graph, you might need to examine
# the content of certain commits. Just check them out as a detached HEADs.
git branch recovered/maintenance decafbad
git branch recovered/master cafebabe
git branch recovered/development deadbeef
git branch recovered/bug-1234 8badf00d

The create and push your recovered branches (and tags) to a new bare repository.

git init --bare /path/to/new-central-bare-repo.git # or real Git hosting service!
git remote add new /path/to/new-central-bare-repo.git
git push --tags new 'refs/heads/recovered/*:refs/heads/*'
Chris Johnsen
  • 214,407
  • 26
  • 209
  • 186