1

I keep a bare git repository (call it mylibs) on an external drive, in which I have a dev branch. I recently did:

git clone /media/extdrive/mylibs; cd mylibs
git checkout dev

And was surprised to receive:

fatal: unable to read tree 03e99624424e6bd337ee16122567338751abef05

Running git fsck in the bare repository, reports:

Checking object directories: 100% (256/256), done.
broken link from    tree 892d4fd7eb30964eb33de9ac707b4b0edbc919a5
              to    tree 03e99624424e6bd337ee16122567338751abef05
              missing tree 03e99624424e6bd337ee16122567338751abef05
              dangling blob e94d7824aca487641c11ff8312915fae5ef62cbe
              dangling blob 27afaaaa0f9979b4963d86bb1e5ddc3fe0d50d8b
              dangling blob e3d72157044f5b6808881025102764726f672d61

I know this topic has been discussed to death (ex: 1, 2, 3), but the answers which I have found all seem rather complicated, and a bit over my head. More importantly, none seemed to work (certainly because of something I was doing wrong, not because the answers were incorrect).

I have this repo cloned all over the place, and while I have no backups of the bare repository, the working clones are all up-to-date and do have the 03/e99624424e6bd337ee16122567338751abef05 object.

My question is: can I simply copy the 03/e99624424e6bd337ee16122567338751abef05 object directly from a working clone into the .git/objects directory of the bare repo on my external drive, or is that an incomplete procedure?

i.e. is this sufficient?

# assuming I'm in a working copy
cp .git/objects/03/e99624424e6bd337ee16122567338751abef05 \
   /media/extdrive/mylibs/.git/objects/03/.

The path /media/extdrive/mylibs/.git/objects/03/ already exists and contains a few other objects.

Notes:

  1. I made a copy of the bare repository, and tested the above and it seemed to work fine. But I want to be sure that I'm not missing something.
  2. The .git/objects/pack/ directory is empty in the bare repository, and in all of my working clones. I don't know if that's indicative of anything, but it precludes use of some of the solutions that I have found.
Blair Fonville
  • 908
  • 1
  • 11
  • 23
  • Incidentally, I cannot imagine how the object went missing. I never had any interruptions during a push, and both repos are collocated on my system, so the transfer is practically immediate. The fact that this corruption (of sorts) occurred is a little concerning. Now I feel as though I'll need to periodically check that everything is still ok with my bare repositories. – Blair Fonville Oct 09 '18 at 19:56

1 Answers1

1

That ought to work, although it having the tree in place might reveal that you've got more missing objects (which you can just keep copying over). A tree doesn't contain anything that is specific to the location or configuration of the repo - it's just a list of names, hashes, and modes of the contents of a directory. However, you should check that both repositories have the same value for git config core.compression; otherwise, the copied file will be compressed at a different level than the repo expects (not sure if git can deal with that or not).

If that somehow doesn't work, you could try using update-index and write-tree to manually recreate the tree. Note that you can use update-index without actually having the files in the right state: you can supply both the mode, the sha, and the file name to --cacheinfo.

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81
  • Thanks. It does seem to work, and luckily no other missing objects were revealed. After copying, `git fsck` returns no issues. I checked `git config --get core.compression` on both repos, and apparently the value is not set on either. So, I assume they will be equivalent. – Blair Fonville Oct 09 '18 at 19:52
  • Great! If it's blank, the default is [zlib](https://zlib.net/manual.html)'s `Z_DEFAULT_COMPRESSION`, which "requests a default compromise between speed and compression (currently equivalent to level 6)" (out of 1-9). – Aasmund Eldhuset Oct 10 '18 at 00:27