Повреждение git "невозможно прочитать [sha]", но git fsck не сообщает об ошибках

У меня есть репозиторий git, в котором, похоже, отсутствует blob. git gc или git repack не справляются с жалобой «фатальный: невозможно прочитать 89a9259486af9e3f0b24f3338ec39b18a7ba39c3». Однако git fsck не обнаруживает проблемы. Я знаю, что мне, вероятно, придется где-то удалить и обрезать ветку, но я не могу понять, где. Может ли кто-нибудь указать мне, как отладить и исправить проблему «невозможно читать»?

Версия git - 2.16.4, но возможно, что повреждение произошло в версии 2.8.3.

Большой двоичный объект не существует в "официальном" репозитории, поэтому он, скорее всего, принадлежит локальной ветке / reflog / и т. д. Есть много местных отделений и

В этом репо много рабочих деревьев, и они могли быть добавлены, удалены и сокращены в течение его жизненного цикла.

отладочная информация:

git repack -adfb --max-pack-size=256m --window=40 --window-memory=100m Counting objects: 5999778, done. Delta compression using up to 4 threads. Compressing objects: 100% (5983452/5983452), done. warning: disabling bitmap writing, packs are split due to pack.packSizeLimit fatal: unable to read 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

Я пробовал несколько разных командных строк fsck с одинаковыми результатами:

$ > git fsck --cache --no-dangling --name-objects --progress
Checking object directories: 100% (256/256), done.
Checking objects: 100% (14155357/14155357), done.
Checking connectivity: 6003771, done.

.

git show 89a9259486af9e3f0b24f3338ec39b18a7ba39c3
fatal: bad object 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

.

$ > git branch --contains 89a9259486af9e3f0b24f3338ec39b18a7ba39c3 --all
error: no such commit 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

Это сценарий, который я ранее получил из Интернета для других целей, но я подумал, что он может помочь:

$ > /tmp/git_blob_to_commit.pl 89a9259486af9e3f0b24f3338ec39b18a7ba39c3
[no ouptput]

Обратите внимание, что это огромное репо, поэтому операции gc / repack занимают очень много времени, поэтому, если вы дадите мне совет, я не игнорирую его, я, вероятно, пробую его, но пройдут часы, прежде чем я смогу вернуться к вам с тем, как это пошли.

Обновлять повторно запустив команду, нажав [return] несколько раз, вы увидите, что ошибка не в фазе сжатия. Возможно, он находится в стадии написания. (?)

Counting objects: 6006957, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5990610/5990610), done.
Writing objects:  19% (1193602/6006957)
warning: disabling bitmap writing, packs are split due to pack.packSizeLimit
Writing objects:  26% (1579434/6006957)
Writing objects:  63% (3802470/6006957)
fatal: unable to read 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

У вас есть другие рабочие деревья (git worktree list не пуст)? Я столкнулся с ошибкой в ​​Git с добавленными рабочими деревьями, которая вызывает подобные проблемы. Похоже, что некоторые операции не были осторожны при сканировании хеш-идентификаторов во вспомогательных рабочих деревьях и отсекали объекты, которые все еще используются. (Я считаю, что ошибка была исправлена ​​между 2,8 и 2,16.)

torek 10.08.2018 17:20

Да, в этом репо определенно много рабочих деревьев. Фактически, я обновлю вопрос, чтобы сказать это, потому что это очень актуально.

Mort 10.08.2018 17:22

@torek, у вас есть какие-нибудь советы, как диагностировать / исправить эту ошибку?

Mort 10.08.2018 17:40

git config fsck.skipList что-нибудь печатает?

max630 10.08.2018 17:56

В моем конкретном случае мне не понадобились дополнительные рабочие деревья, поэтому я выбросил их, и Git снова был счастлив. Не лучший общий способ продолжения ...

torek 10.08.2018 18:27

@ max630, нет, ничего в этом конфиге.

Mort 10.08.2018 18:53

@torek есть ли у вас какие-нибудь идеи о том, какую еще отладку я могу сделать?

Mort 14.08.2018 16:08

Я сдался задолго до этого момента с моей собственной настройкой, но: проверьте каталог .git / worktrees, найдите там необработанные хэши в файлах HEAD (возможно, их нет); и используйте git ls-files --stage в каждом индексе для каждого рабочего дерева, чтобы увидеть, является ли это хешем большого двоичного объекта в индексе.

torek 14.08.2018 17:39
2
8
115
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

git repack -adfb --max-pack-size=256m --window=40 --window-memory=100m
...
Compressing objects: 100% (5983452/5983452), done.
...
fatal: unable to read 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

похоже, что на объект нигде нет ссылок, иначе вы не пройдете фазу «Сжатие», и сбой произойдет во время очистки объектов. Вы можете проверить это, запустив fsck с --dangling и --unreachable - он напечатает его в списке или даже не сработает.

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

torek 10.08.2018 20:27

@ max630: Спасибо. Это не в фазе сжатия. См. Мое обновление исходного вопроса выше. Я повторно запустил fsck с --dangling и --unreachable, как вы предложили, и действительно есть болтающиеся и недоступные капли / коммиты / деревья, но я не совсем уверен, что делать с этой информацией. До fsck я уже делал git prune --expire=1.day -v на репо.

Mort 13.08.2018 20:35

@ max630 у вас есть идеи о том, какую еще отладку я могу сделать?

Mort 14.08.2018 16:08
Ответ принят как подходящий

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

Вот примерный подход, который я выбрал. Конечно, его можно было бы оптимизировать, но я надеюсь, что больше никогда не придется этого делать.

for i in $(git worktree list | awk '{print $1}')
do
    cd $i
    echo "TITLE $i"
    git ls-files --stage
done  >> /tmp/blobs.txt         # This is potentially a massive file

for i in $(cat /tmp/blobs.txt | awk '{print $2}')  # Brute force, could be optimized
do
    git show $i >/dev/null || echo "NOT FOUND $i"
done

Для каждой записи «НЕ НАЙДЕНО» запустите egrep "TITLE|<sha>" /tmp/blobs.txt, чтобы найти рабочее дерево, в котором она находится. Затем перейдите к рабочему дереву и отключите что-либо в индексе. Это должно решить проблему (ы).


Спасибо @torek за предоставленную информацию, чтобы прийти к такому выводу. (У вас достаточно ТАКОЙ репутации, что я не думаю, что вы будете возражать, если не получите баллов за этот ответ.)

Другие вопросы по теме