Git: «Поврежденный свободный объект»

329

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

$ git gc
error: Could not read 3813783126d41a3200b35b6681357c213352ab31
fatal: bad tree object 3813783126d41a3200b35b6681357c213352ab31
error: failed to run repack

Кто-нибудь знает, что с этим делать?

Из cat-файла я получаю это:

$ git cat-file -t 3813783126d41a3200b35b6681357c213352ab31
error: unable to find 3813783126d41a3200b35b6681357c213352ab31
fatal: git cat-file 3813783126d41a3200b35b6681357c213352ab31: bad file

И из git fsck я получаю это (не знаю, действительно ли это связано):

$ git fsck
error: inflate: data stream error (invalid distance too far back)
error: corrupt loose object '45ba4ceb93bc812ef20a6630bb27e9e0b33a012a'
fatal: loose object 45ba4ceb93bc812ef20a6630bb27e9e0b33a012a (stored in .git/objects/45/ba4ceb93bc812ef20a6630bb27e9e0b33a012a) is corrupted

Может кто-нибудь помочь мне расшифровать это?

asgerhallas
источник
Вы пытались посмотреть на последний объект (45ba4ceb93bc812ef20a6630bb27e9e0b33a012a)?
Гинтаутас Миляускас
4
Спасибо ... но как "посмотреть" на объект? Все еще новенький для
мерзавца
2
«Git show» не дает мне ничего, кроме «git fsck», к сожалению, уже сделанного.
asgerhallas
4
Линус Торвальдс написал следующее полезный документ об этой ошибке и , как вручную восстановить сгустки , если у вас есть файлы: Как восстановить поврежденный объект BLOb Некоторые трюки на объекты реконструировать BLOb для того , чтобы исправить поврежденный архив
Uwe Kleine-König
2
Можете ли вы добавить комментарии или отредактировать принятый ответ? Я нахожусь в точно такой же ситуации, и принятый ответ, по-видимому, не содержит достаточно подробностей для "Just Work TM", но вместо этого заставит меня погрузиться в детали сам.
ripper234

Ответы:

57

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

Вы могли бы на самом деле восстановить его, если не можете найти действительную версию от кого-то другого, угадав, какие файлы должны быть там. Возможно, вы захотите посмотреть, соответствуют ли даты и время объектов. Это могут быть связанные пятна. Из этих объектов можно вывести структуру дерева.

Взгляните на скриншоты Скотта Чакона о Git . Это покажет вам, как работает git под капотом и как выполнять эту детективную работу, если вы действительно застряли и не можете получить этот объект от кого-то другого.

Адам Димитрук
источник
2
это может быть сохранено в файле пакета. Так git сжимает хранилище объектов, сохраняя дельты. Свободные объекты - это те, которых еще нет в упаковке. Google для файлов пакета, индексные файлы в Git, и вы должны быть в состоянии погрузиться так глубоко, как вам нужно.
Адам Димитрук
2
Не могли бы вы дать ссылку в своем ответе на скриншоты Git от Chacon?
Этеш Чоудхури
1
git cat-file -t <SHA1>скажу вам тип. Если он не поврежден, вы можете git cat-file <type> <SHA1>просмотреть его содержимое (я использовал его для blob, я думаю, оно также покажет вам содержимое других типов).
Carl G
1
Также этот пост от Линуса описывает процесс восстановления blob. Однако, когда я следовал этим инструкциям, git statusответил, fatal: unable to read <SHA1>даже если я успешно запустился git hash-object -w <file>(вероятно, потому что, согласно его инструкциям, я переместил этот объектный файл. Возвращение его просто дало мне ту же corrupt loose objectошибку.)
Carl G
2
А теперь повторите на английском, пожалуйста
Мехди
359

У меня была такая же проблема (не знаю почему).

Это исправление требует доступа к не поврежденной удаленной копии хранилища и сохранит вашу локальную рабочую копию нетронутой.

Но у него есть некоторые недостатки:

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

Исправление

Выполните эти команды из родительского каталога над вашим репозиторием (замените 'foo' именем папки вашего проекта):

  1. Создайте резервную копию поврежденного каталога:
    cp -R foo foo-backup
  2. Создайте новый клон удаленного репозитория в новый каталог:
    git clone git@www.mydomain.de:foo foo-newclone
  3. Удалите поврежденный .git подкаталог:
    rm -rf foo/.git
  4. Переместите только что клонированный подкаталог .git в foo:
    mv foo-newclone/.git foo
  5. Удалите оставшуюся часть временного нового клона:
    rm -rf foo-newclone

В Windows вам нужно будет использовать:

  • copy вместо того cp -R
  • rmdir /S вместо того rm -rf
  • move вместо того mv

Теперь у foo есть свой исходный .gitподкаталог, но все локальные изменения все еще там. git status, commit, pull, pushИ т.д. работа снова , как они должны.

кубический салат
источник
11
Этот метод работал для меня. Тем не менее, я считаю, что все невыполненные коммиты были потеряны. Данные репо остались нетронутыми.
Wonton
30
Да, непроверенная информация о фиксации будет потеряна. Но в распространенных сценариях (без нескольких локальных веток с невыпущенными изменениями, отличными от текущих), все самые последние изменения файлов (в том числе удаления) все еще находятся на диске, поэтому можно легко повторить любые предыдущие невыдвинутые коммиты. Поскольку я всегда настаиваю на любой последовательности коммитов, я даже не столкнулся с этой проблемой.
кубический салат
7
Просто и понятно. Это, IMO, самое эффективное решение, если вы не все понимаете в git и не хотите возиться со своим репозиторием.
Oliboy50
4
Я думаю, что это удалит все тайники, так как они хранятся в подкаталоге .git.
Энтони Эллиотт
4
Если в проекте есть подмодули, их необходимо инициализировать перед извлечением .gitпапки.
AdrieanKhisbe
243

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

Сначала сделайте резервную копию ваших локальных файлов. Затем сделайте это из корня вашего рабочего дерева:

rm -fr .git
git init
git remote add origin [your-git-remote-url]
git fetch
git reset --mixed origin/master
git branch --set-upstream-to=origin/master master  

Затем зафиксируйте любые измененные файлы по мере необходимости.

user1055643
источник
12
ИМХО это должен быть принятый ответ. Гораздо проще, чем удаление репо и повторное клонирование! :) Хотя вы теряете любые постановки ...
Ник
6
Очевидно, если вы находились в ветке, отличной от master, когда произошло повреждение, замените его masterна имя ветви.
Тимоти Цорн
В основном работал как есть, но я был в другой ветке, workingкогда она была повреждена, и эти шаги не дали мне локальную копию какой-либо ветки, кроме master (и да, я пытался заменить master выше, workingно это не сработало). В итоге я выполнил вышеописанные шаги master, затем спрятал мои изменения и сделал checkout -b working origin/workingтам сундук . Кажется, сработало - спасибо!
Фантабол
1
В моем хранилище был субмодуль, который не был поврежден. Этот процесс оставил хранилище и его подмодуль в состоянии, когда такие команды, какgit status дали fatal: Not a git repository: submodules/my-sub/../../.git/modules/my-sub. Удаление субмодуля из файловой системы и перезапуск процесса восстановили нормальность. Вероятно, сначала нужно убедиться, что в подмодулях нет
открытых
5
Я сделал это сегодня и не потерял незафиксированные изменения в файлах :) (git 2.17.1)
Фабио Диас
173

Работая на ВМ, у меня в ноутбуке аккумулятор сдох, получил эту ошибку;

ошибка: объектный файл .git / objects / ce / theRef - пустая ошибка: объектный файл .git / objects / ce / theRef - пустой фатальный: свободный объект theRef (хранящийся в .git / objects / ce / theRef) поврежден

Мне удалось заставить репо работать снова, используя всего 2 команды и не теряя своей работы (измененные файлы / незафиксированные изменения)

find .git/objects/ -size 0 -exec rm -f {} \;
git fetch origin

После этого я запустил git statusрепо, все было в порядке, и произошли мои изменения (в ожидании подтверждения, сделайте это сейчас ..).

GIT версия 1.9.1

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

Фелипе Перейра
источник
10
find .git/objects/ -size 0 -exec rm -f {} \;у меня работает;)
Лазаро Фернандес Лима Сулейман
Возникла такая же проблема, запустил команду, отлично работал у меня на Mint VM.
Людвиг Райдал
Также работал отлично, не делая ничего другого.
Халсафар
1
Не на ВМ, и это работало для меня много раз. IDK, почему это происходит в моем текущем проекте, но это исправляет это каждый раз.
Джеймс Л.
7
Возможно, вам придется запустить git symbolic-ref HEAD refs/heads/master.после удаления пустых объектов.
Стефан
43

Мой компьютер вышел из строя, когда я писал сообщение о коммите. После перезагрузки рабочее дерево было таким, каким я его оставил, и я смог успешно зафиксировать свои изменения.

Однако, когда я попытался бежать, git statusя получил

error: object file .git/objects/xx/12345 is empty
fatal: loose object xx12345 (stored in .git/objects/xx/12345 is corrupt

В отличие от большинства других ответов, я не пытался восстановить какие-либо данные . Мне просто нужно, чтобы Git перестал жаловаться на пустой объектный файл.

обзор

«Объектный файл» - это хешированное представление git реального файла, который вас интересует. Git считает, что в нем должна some/file.whateverхраниться хэшированная версия .git/object/xx/12345, и исправление ошибки оказалось главным образом вопросом выяснения, какой файл должен был представлять «свободный объект».

подробности

Возможные варианты казались

  1. Удалить пустой файл
  2. Получить файл в состояние, приемлемое для Git

Подход 1: Удалить объектный файл

Первым делом я попробовал переместить объектный файл

mv .git/objects/xx/12345 ..

Это не сработало - git начал жаловаться на неработающую ссылку. На подходе 2.

Подход 2: исправить файл

У Линуса Торвальдса есть отличная статья о том, как восстановить объектный файл, который решил проблему для меня. Ключевые шаги суммированы здесь.

$> # Find out which file the blob object refers to
$> git fsck
broken link from    tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
           to    blob xx12345
missing blob xx12345

$> git ls-tree 2d926
...
10064 blob xx12345  your_file.whatever

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

$> git hash-object -w path/to/your_file.whatever

После этого я проверил .git/objects/xx/12345, он больше не был пустым, и мерзавец перестал жаловаться.

Деклан
источник
Я находился в ситуации, когда у меня не было удаленной или резервной копии моего репо, и где поврежденный объект был добавлен рядом с начальным коммитом, возможно, в любом случае повредил все дерево. Я пытался воссоздать объект в другом репо, но этот ответ дает тот же результат с большей утонченностью.
Estecka
13

Пытаться

git stash

Это сработало для меня. Он прячет все, что вы не совершали, и это решает проблему.

Артур
источник
Weird!?! Наткнулся на эту ошибку сегодня утром. Вчера совершил, так что ни один вздох не изменился. git stash Выполнено следующее: ... fatal: невозможно создать '/home/<user>/.git/index.lock': touch .git/a касание ошибки ввода / вывода : невозможно касаться '.git / a': ошибка ввода / вывода sudo touch /home/guest/.git/a НЕТ ОШИБКИ git stash Нет локальные изменения для сохранения git status ... нечего
коммитить
1
@ go2null Я немного опоздал с этим, но ошибки ввода / вывода обычно означают проблемы с жестким диском. Хотя я уверен, что вы уже поняли это.
Arleslie
«Невозможно сохранить текущее состояние индекса»
Владимир Бразил
9

Мусора фиксированная моя проблема:

git gc --aggressive --prune=now

Требуется некоторое время для завершения, но каждый свободный объект и / или поврежденный индекс был исправлен.

Яго
источник
Это хорошее решение. Работал на меня. Моя система отключилась случайно. Однако эта команда избавила меня от клонирования и всех этих тяжелых задач. Спасибо, Яго.
Мукеш Кумар
«не удалось запустить reflog»
Владимир Бразил
5

просто git pruneисправил эту проблему для меня

Тайлер Гауч
источник
Это сработало для меня и кажется самым простым решением. Не уверен, почему этот ответ не набрал больше голосов. Единственный недостаток в том, что следующий git pullзанимает немного больше времени, чем обычно, я думаю, потому что он заменяет некоторые удаленные объекты или что-то еще.
steev
1
Причина может быть в том, что git prune вообще не решает проблему.
user3072843
4

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

Я начал с рассмотрения того, сколько коммитов я не выдвинул в удаленный репозиторий, поэтому:

gitk &

Если вы не используете этот инструмент, он очень удобен - насколько мне известно, он доступен во всех операционных системах. Это указывало на то, что на моем пульте не было двух коммитов. Поэтому я нажал на метку, указывающую последний удаленный коммит (обычно это будет /remotes/origin/master), чтобы получить хеш (хеш длиной 40 символов, но для краткости я здесь использую 10 - это обычно работает в любом случае).

Вот:

14c0fcc9b3

Затем я нажимаю на следующий коммит (т. Е. Первый, который удаленный не имеет) и получаю хэш:

04d44c3298

Затем я использую оба из них, чтобы сделать патч для этого коммита:

git diff 14c0fcc9b3 04d44c3298 > 1.patch

Затем я сделал то же самое с другим отсутствующим коммитом, то есть использовал хэш коммита до и сам хэш коммита:

git diff 04d44c3298 fc1d4b0df7 > 2.patch

Затем я переехал в новый каталог, клонировал репозиторий с пульта:

git clone git@github.com:username/repo.git

Затем я переместил файлы исправлений в новую папку, применил их и зафиксировал их с точными сообщениями фиксации (их можно вставить из окна git logили из gitkокна):

patch -p1 < 1.patch
git commit

patch -p1 < 2.patch
git commit

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

git fsck 

Вы получите что-то вроде этого:

error: object file .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d is empty
error: unable to find ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d
error: sha1 mismatch ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d

Чтобы сделать ремонт, я бы сделал это в сломанной папке:

rm .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d
cp ../good-repo/.git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d

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

Таким образом (по крайней мере, в моем случае) поврежденное дерево не означает, что невыдвинутые коммиты будут потеряны.

halfer
источник
3

Я также получал поврежденную ошибку свободного объекта.

./objects/x/x

Я успешно исправил это, зайдя в каталог поврежденного объекта. Я видел, что пользователи, назначенные этому объекту, были не были моим пользователем git. Я не знаю, как это случилось, но я запустил chown git:gitэтот файл, и он снова заработал.

Это может быть потенциальным решением проблем некоторых людей, но не обязательно всех из них.

Ребекка Дессонвилль
источник
2

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

Дин Ратер
источник
2

Runnning git stash; git stash popисправил мою проблему

Симонлука Ланди
источник
2

Я следовал за многими другими шагами здесь; Описание Линуса о том, как посмотреть на дерево / объекты git и найти то, чего не хватает, было особенно полезно. мерзавец восстановить поврежденный блоб

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

В конце концов, я убрал конфликтующие objects/<ha>/<hash>с пути и использовал git unpack-objectsфайл пакета из достаточно современного клона. Он смог восстановить недостающие объекты дерева.

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

davenpcj
источник
2

В ответ @ user1055643 отсутствует последний шаг:

$ rm -fr .git
$ git init
$ git remote add origin your-git-remote-url
$ git fetch
$ git reset --hard origin/master
$ git branch --set-upstream-to=origin/master master  
Эртугрул Алтынбога
источник
это --set-upstream-to действительный аргумент? Я так не думаю!
Шариф Мамун
2
git branch (--set-upstream-to = <upstream> | -u <upstream>) [<branchname>]
Эртугрул Алтынбоя
Если вы удалите .gitи скопируете из клонированного проекта, репозиторий будет работать, но ни локальные ветви, ни тайники не будут сохранены.
Владимир Вуканац
1

У нас только что был случай здесь. Случилось так, что проблема была в том, что владельцем поврежденного файла был root вместо нашего обычного пользователя. Это было вызвано фиксацией, сделанной на сервере после того, как кто-то сделал «sudo su -».

Сначала идентифицируйте ваш поврежденный файл с помощью:

$> git fsck --full

Вы должны получить ответ, подобный этому:

fatal: loose object 11b25a9d10b4144711bf616590e171a76a35c1f9 (stored in .git/objects/11/b25a9d10b4144711bf616590e171a76a35c1f9) is corrupt

Перейдите в папку, где находится поврежденный файл и выполните:

$> ls -la

Проверьте право собственности на поврежденный файл. Если это не так, просто вернитесь в корень вашего репозитория и выполните:

$> sudo chown -R YOURCORRECTUSER:www-data .git/

Надеюсь, поможет!

Томас Лобжуа
источник
1

Для меня это произошло из-за сбоя питания при выполнении git push.

Сообщения выглядели так:

$ git status
error: object file .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74 is empty
error: object file .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74 is empty
fatal: loose object c238824eb3fb602edc2c49fccb535f9e53951c74 (stored in .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74) is corrupt

Я пробовал такие вещи, git fsckно это не помогло. Поскольку сбой произошел во время a git push, он, очевидно, произошел во время перезаписи на стороне клиента, которая происходит после обновления сервера. Я оглянулся и понял, что c2388в моем случае это был объект commit, потому что на него ссылались записи в .git/refs. Так что я знал, что смогу найти, c2388когда посмотрю историю (через веб-интерфейс или второй клон).

На втором клоне я git log -n 2 c2388узнал предшественника c2388. Тогда я вручную изменил .git/refs/heads/masterи .git/refs/remotes/origin/masterстал предшественником c2388вместо c2388. Тогда я мог бы сделать git fetch. Не git fetchудалось несколько раз для конфликтов на пустых объектах. Я удалил каждый из этих пустых объектов, пока не git fetchполучилось. Это исцелило хранилище.

Кристиан Худжер
источник
1

Я решил это следующим образом: я решил просто скопировать не поврежденный объектный файл из клона резервной копии в мой исходный репозиторий. Это сработало так же хорошо. (Кстати: если вы не можете найти объект в .git / objects / по его имени, он, вероятно, был [упакован] [упакован] для экономии места.)

Макгин
источник
0

У меня была такая же проблема в моем голом удаленном репозитории Git. После долгих проблем я обнаружил, что один из моих коллег сделал коммит, в котором некоторые файлы в .git / objects имеют разрешения 440 (r - r -----) вместо 444 (r - r - r). -). После того, как коллега попросил изменить права доступа с помощью «объектов chmod 444 -R» внутри репозитория git, проблема была исправлена.

konyak
источник
0

У меня просто была такая проблема. Моя конкретная проблема была вызвана сбоем системы, который повредил самый последний коммит (и, следовательно, также главную ветку). Я не толкнул и хотел сделать этот коммит заново. В моем конкретном случае я смог справиться с этим так:

  1. Сделайте резервную копию .git/ :rsync -a .git/ git-bak/
  2. Проверьте .git/logs/HEADи найдите последнюю строку с допустимым идентификатором фиксации. Для меня это был второй самый последний коммит. Это было хорошо, потому что у меня все еще были версии файла рабочего каталога, и поэтому каждая версия, которую я хотел.
  3. Сделайте ветку на этом коммите: git branch temp <commit-id>
  4. повторно выполнить битый коммит с файлами в рабочем каталоге.
  5. git reset master temp чтобы переместить основную ветку на новый коммит, который вы сделали на шаге 2.
  6. git checkout masterи проверьте, что это выглядит правильно с git log.
  7. git branch -d temp,
  8. git fsck --fullи теперь должно быть безопасно удалить любые поврежденные объекты, найденные fsck.
  9. Если все выглядит хорошо, попробуйте нажать. Если это работает,

Это сработало для меня. Я подозреваю, что это довольно распространенный сценарий, поскольку наиболее вероятным будет повреждение самого последнего коммита, но если вы потеряете еще один назад, вы, вероятно, все еще можете использовать такой метод, с осторожным использованием git cherrypickи reflog в .git/logs/HEAD.

naught101
источник
0

Когда у меня возникла эта проблема, я скопировал свои последние изменения (поскольку я знал, что я изменил), а затем удалил этот файл, на который он жаловался, в .git / location. Затем я сделал git pull. Будьте осторожны, это может не сработать для вас.

Gareth
источник
0

Я столкнулся с этим, как только моя система сломалась. Что я сделал, это:

(Обратите внимание, что ваши поврежденные коммиты потеряны, но изменения сохраняются. Возможно, вам придется пересоздать эти коммиты в конце этой процедуры)

  • Сделайте резервную копию вашего кода.
  • Перейдите в свой рабочий каталог и удалите .gitпапку.
  • Теперь клонируйте пульт в другом месте и скопируйте в него .gitпапку.
  • Вставьте его в свой рабочий каталог.
  • Фиксируй как хотел.
Wajahath
источник
-7

Просто удалите папку .git и добавьте ее снова. Это простое решение сработало для меня.

Овидиу Матан
источник
3
Это уничтожит ваш локальный репозиторий ..., может иметь довольно нежелательные побочные эффекты :) Пожалуйста, отредактируйте свое предложение и добавьте это предупреждение.
Феликс
1
Если вы удалите .gitи скопируете из клонированного проекта, репозиторий будет работать, но не будут сохранены ни локальные ветви, ни тайники. Также, дружеское предложение, полностью удалите свой ответ, чтобы перестать получать отрицательные голоса.
Владимир Вуканац
1
Вау, Нелли ... поговорим об использовании базуки для работы пинцетом.
Tuncay Göncüoğlu