Записать объектный файл git из клона удаленного репо

Я боролся с этой проблемой в течение нескольких часов. В моем локальном репо почему-то отсутствует коммит

> 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

а также

$ 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

Я задавал вопросы по устранению проблемы. В частности, я столкнулся с этим ответом:

Первое, что вы можете попробовать, это восстановить недостающие элементы из резервной копии. Например, посмотрите, есть ли у вас резервная копия фиксации, сохраненная как .git/objects/98/4c11abfc9c2839b386f29c574d9e03383fa589. Если это так, вы можете восстановить его.

Итак, я обнаружил, что коммит был в удаленном на GitHub. Поэтому я сделал новый клон в другом каталоге, но /objects в основном пуст. Есть ли способ восстановить файл объектов всего за один коммит?

Ответ 1

Если вы обнаружили, что коммит находится на удаленном компьютере, то проще всего будет извлечь коммит (который также будет извлекать любые зависимые объекты, такие как содержимое коммита или другие коммиты, которые составляют историю этого коммита).

Вы, вероятно, не можете получить конкретную фиксацию напрямую с удаленного компьютера, потому что произвольный идентификатор фиксации обычно не принимается в качестве аргументов для выборки. Но вы сделали локальный клон, чтобы вы могли

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

Оформление заказа должно привести вас в отключенное состояние HEAD, которое напечатает длинное предупреждение и объяснение; но это должно получиться. Если это ошибка, то, возможно, какое-то наблюдение о коммите в удаленном (и/или новом клоне) было ошибочным.

Если предположить, что проверка работает, то вы бы

$ 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

(Существует много вариантов этой последовательности команд; в этой используется достаточно знакомый синтаксис, поэтому я вполне уверен, что я правильно понял, несмотря на то, что передо мной нет тестового экземпляра, хотя другие способы, возможно, более лаконичны.)

Ответ 2

У нового клона из другого места будет объект в файле пакета, если у него есть объект вообще. Смотрите Как мне распаковать один git-объект? для метода для извлечения одного упакованного объекта из файла пакета.

Вы можете обнаружить, что, как только у вас появится первый отсутствующий объект, вам нужно больше объектов. Технически нормально иметь объект более одного раза (например, в нескольких пакетах), пока поиск объекта в любом пакете, в котором он есть, и использование результата дает вам те же биты, что и поиск одного и того же объекта в любом другом пакете, который также есть это. Если репозитории связаны, это должно быть так, так что вы можете просто поместить файл пакета в "плохое" хранилище, чтобы добавить все его объекты (некоторые, возможно, избыточно).

Если и когда вы добьетесь того, что Git будет в порядке с "плохим" клоном, будет хорошей идеей повторно клонировать его в новый клон (для этого вы можете использовать git clone --mirror).

Ответ 3

Вы можете использовать git fetch чтобы получить конкретный объект с пульта.

Попробуйте запустить:

git fetch origin 95eeac3b5f441c9ebbd89508896c572e3eb17205

Другой аспект: результат git fsck гласит, что единственная неудача в том, что ваш локальный тег 12.01.02 является недействительным.

  • удалите этот локальный тег: git tag -d 12.01.02
  • если вам это нужно, верните его из источника: git fetch origin 12.01.02

Ответ 4

Я буквально только что получил переполнение стека сегодня, и этот мудак пришел и закрыл мою способность делать что-либо. Вы "модерировали" мой пост и сделали меня заблокированным на целую неделю только потому, что вам не понравился вопрос. Это был совершенно обычный вопрос С# о чтении и записи данных из внешних источников. Теперь я не могу использовать переполнение стека ни для чего, кроме комментариев из-за этого рывка. Позор тебе, Мачавити. Вы не заслуживаете ни одной унции той "репутации", которая у вас есть.