Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write git object file from remote repo clone

Tags:

git

I have been wrestling with this problem for hours. My local repo is somehow missing a commit

> git reflog expire --stale-fix --all
error: refs/tags/12.01.02 does not point to a valid object!
error: Could not read 95eeac3b5f441c9ebbd89508896c572e3eb17205
fatal: Failed to traverse parents of commit 6c24f6ea7c0452e70dea6332c6959dad6c71305f

and

$ git fsck --full
Checking object directories: 100% (256/256), done.
Checking objects: 100% (159800/159800), done.
error: refs/tags/12.01.02: invalid sha1 pointer 95eeac3b5f441c9ebbd89508896c572e3eb17205
error: HEAD: invalid reflog entry 95eeac3b5f441c9ebbd89508896c572e3eb17205

I've been running through questions on fixing the problem. Specifically, I ran into this answer:

The first thing you can try is to restore the missing items from backup. For example, see if you have a backup of the commit stored as .git/objects/98/4c11abfc9c2839b386f29c574d9e03383fa589. If so you can restore it.

So, I found the commit was in the remote on GitHub. So I made a fresh clone in a different directory, but /objects is mostly empty. Is there a way to regenerate the objects file for just one commit?

like image 209
Machavity Avatar asked Feb 01 '19 21:02

Machavity


2 Answers

If you found that the commit is in the remote, then the easiest thing may be to fetch the commit (which will also pull in any dependent objects, such as the commit's content, or other commits that make up the history of that commit).

You probably can't fetch a specific commit directly from the remote, because arbitrary commit ID's are not generally accepted as arguments to fetch. But you made a local clone, so you could

$ cd path/of/new/clone
$ git checkout 95eeac3

The checkout should put you in detached HEAD state, which will print a lengthy warning and explanation; but it should succeed. If it errors, then perhaps some observation about the commit being in the remote (and/or new clone) was in error.

Assuming the checkout does work, then you would

$ git branch my_temp_branch
$ cd path/of/original/clone
$ git remote add temp file://localhost/path/of/new/clone
$ git fetch temp my_temp_branch

(There are many variations on that sequence of commands; this one uses familiar enough syntax that I'm reasonably sure I have it right in spite of not having a test instance in front of me, though other ways are perhaps more concise.)

like image 69
Mark Adelsberger Avatar answered Sep 19 '22 21:09

Mark Adelsberger


A fresh clone from elsewhere will have the object in a pack file, if it has the object at all. See How do I unpack a single git object? for a method for extracting one packed object from a pack file.

You may find that once you have the first missing object, you need more objects. It's technically OK to have an object more than once (e.g., in several packs) as long as looking up the object in any pack that has it and using the result gets you the same bits as looking up the same object in any other pack that also has it. If the repositories are related, this should be the case, so you can just drop the pack file into the "bad" repo to add all its objects (some perhaps redundantly).

If and when you do get Git to be OK with the "bad" clone, it's a good idea to re-clone it to a new clone (you may want to use git clone --mirror for this).

like image 22
torek Avatar answered Sep 18 '22 21:09

torek