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

Хтось може мені допомогти розшифрувати це?


Ви спробували подивитися на останній об’єкт (45ba4ceb93bc812ef20a6630bb27e9e0b33a012a)?
Gintautas Miliauskas

4
Дякую ... але як можна "дивитися" на об'єкт? Ще новинка в git :)
asgerhallas

2
"Git show" дає мені не що інше, як "git fsck", який, на жаль, зробив.
asgerhallas

4
Лінус Торвальдс написав наступний корисний документ про цю помилку та про те, як вручну реконструювати краплі, якщо у вас є файли: Як відновити пошкоджений об’єкт блобу. Деякі хитрощі відновити об’єкти блобу, щоб виправити пошкоджене сховище
Uwe Kleine-König,

2
Чи можете ви додати коментарі чи відредагувати прийняту відповідь? Я перебуваю в точно такій же ситуації, і, здається, прийнята відповідь не містить достатньо деталей до "Просто працюю ТМ", але натомість змусить мене сам зануритися в деталі.
ripper234

Відповіді:


57

Схоже, у вас зіпсований деревний об’єкт. Вам потрібно буде отримати цей об’єкт у когось іншого. Сподіваємось, у них з’явиться непорушена версія.

Насправді ви можете її реконструювати, якщо не зможете знайти дійсну версію від когось іншого, здогадавшись, які файли там мають бути. Ви можете побачити, чи відповідають дату та час об’єктів. Це можуть бути споріднені краплі. Ви могли зробити висновок про структуру дерева об'єкта з цих об'єктів.

Погляньте на екрани Git Скотта Чакона, що стосуються внутрішніх справ git. Це покаже вам, як працює git під кришкою і як робити цю детективну роботу, якщо ви дійсно застрягли і не можете отримати цей об’єкт від когось іншого.


2
він може бути збережений у пакувальному файлі. Таким чином git стискає зберігання предметів, зберігаючи дельти. Сипучі об'єкти - це ті, яких ще немає в пакеті. Google для пакування файлів, індексування файлів у git, і ви повинні мати можливість зануритися в глибину, як вам потрібно.
Адам Дімітрук

2
Не могли б ви надати посилання у своїй відповіді на екрани Git Chacon's Git?
Ехтеш Чудхурі

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помилку.)
Карл 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
Цей метод спрацював для мене. Однак я вважаю, що всі невдоволені зобов'язання були втрачені. Дані Repo були недоторкані.
wonton

30
Так, незабруднена інформація про фіксацію втрачається. Але у загальних сценаріях (немає декількох локальних гілок із неспроможними змінами інших, ніж поточний), всі останні модифікації файлів (включно з видаленнями) все ще є на диску, таким чином, ви можете легко повторити будь-які попередні незапущені коміти. Оскільки я завжди наполягаю на будь-якій послідовності доручень, я навіть не стикався з цією проблемою.
кубічний салат

7
Простий і прямолінійний. Це, IMO, найефективніше рішення, якщо ви не розумієте все про git і не хочете поспілкуватися зі своїм сховищем.
Oliboy50

4
Я думаю, що це видалить усі скрині, оскільки вони зберігаються у підкаталозі .git.
Ентоні Елліотт

4
Якщо в проекті є підмодулі, потрібно запустити їх до отримання .gitпапки.
AdrieanKhisbe

242

Ваша найкраща ставка - це, ймовірно, просто повторне клонування з віддаленого репо (наприклад, 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  

Потім виконайте будь-які змінені файли за необхідності.


12
ІМХО, це має бути прийнятою відповіддю. Набагато простіше, ніж видалення репо і повторне клонування! :) Хоча ви втрачаєте будь-які поетапні зобов’язання ...
Нік

6
Очевидно, якщо ви були у відділенні, відмінному від майстра, коли сталася корупція, замініть masterйого ім'ям вашої філії.
Тимофій Зорн

В основному працював так, як є, але я був на іншій гілці, workingколи вона пошкодилася, і ці кроки не дали мені локальної копії будь-якої гілки, крім 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)
Fábio Dias

173

Працюючи над VM, у моєму ноутбуці акумулятор помер, отримав цю помилку;

Помилка: файл об'єкта.

Мені вдалося змусити репо знову працювати лише з 2 командами і не втрачаючи свою роботу (змінені файли / незахищені зміни)

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

Після цього я запустив a git status, репо було добре, і там відбулися мої зміни (чекаю, коли буде вчинено, зробіть це зараз ..).

git версія 1.9.1

Не забудьте створити резервну копію всіх запам’ятованих змін, на випадок, якщо це рішення не працює, і потрібен більш радикальний підхід.


10
find .git/objects/ -size 0 -exec rm -f {} \;працює для мене;)
Лазаро Фернандес Ліма Сулейман

Була така ж проблема, виконував команду, прекрасно працював для мене на Mint VM.
Людвіг Ридах

Також працював ідеально, не роблячи нічого іншого.
Халсафар

1
Не на VM, і це працювало для мене багато разів. 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 вважає, що він повинен мати хешовану версію, що some/file.whateverзберігається в .git/object/xx/12345, і виправлення помилки виявилося здебільшого питанням з'ясування того, який файл повинен містити "вільний об'єкт".

Деталі

Можливі варіанти, здавалося, були

  1. Видаліть порожній файл
  2. Переведіть файл у стан, прийнятний для Git

Підхід 1: Видаліть файл об'єкта

Перше, що я спробував - це просто переміщення файлу об'єкта

mv .git/objects/xx/12345 ..

Це не спрацювало - Гіт почав скаржитися на пошкоджене посилання. Про підхід 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, що він більше не порожній, і git перестав скаржитися.


Я опинився в ситуації, коли у мене не було жодного віддаленого або резервного копіювання мого репо, і де пошкоджений об’єкт був доданий біля початкового коду, ймовірно, все-таки зіпсувавши все дерево. Я мав свій спосіб намагатися відтворити об’єкт в іншому репо, але ця відповідь досягає того ж результату з більшою тонкістю.
Естечка

13

Спробуйте

git stash

Це працювало для мене. Це приховує все, чого ви не зробили, і це вирішило проблему.


Дивно!?! Ця помилка зіткнулася сьогодні вранці. Зробив вчора, тому жодне неспокійне не змінилося. git stash Зробило наступне: ... фатально: Не вдається створити '/ home / <user> /.git/index.lock': помилка вводу / виводу touch .git/a touch: не може торкатися '.git / a': помилка вводу / виводу sudo touch /home/guest/.git/a НЕ ПОМИЛКУ git stash Ні локальні зміни, щоб зберегти git status ... нічого не робити, робочий каталог очистити
go2null

1
@ go2null Я трохи запізнююся з цим, але помилки введення / виводу, як правило, означають проблеми на жорсткому диску. Хоча я впевнений, що ви вже це зрозуміли.
arleslie

"Неможливо зберегти поточний стан індексу"
Володимир Бразиль

9

Збір сміття вирішив мою проблему:

git gc --aggressive --prune=now

Потрібно пройти деякий час, але кожен нескінченний об'єкт та / або пошкоджений індекс був виправлений.


Це хороше рішення. Працювали для мене. Моя система відключилась випадково. Однак ця одна команда врятувала мене від клонування та всіх тих важких завдань. Дякую Джаго.
Мукеш Кумар

"не вдалося запустити рефлог"
Vladimir Brasil

5

просто git pruneзафіксував цю проблему для мене


Це працювало для мене і, здається, найлегше рішення. Не впевнений, чому ця відповідь не отримала більше голосів. Єдиний недолік - це те, що наступний git pullзаймає трохи більше часу, ніж зазвичай, тому що він замінює вилучені об’єкти чи щось.
steev

1
Причиною може бути те, що чорнослив зовсім не вирішує проблему.
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без помилок. У звіті, ймовірно, будуть рядки "звисання" та "звисання", вони є наслідком ваших знижок та змін у цій папці. Сміттєзбиральник їх буде своєчасно вивозити.

Таким чином, (принаймні в моєму випадку) зіпсоване дерево не означає, що втрачені нечисті втрати.


3

Я також отримував корумповану помилку з вільним об’єктом.

./objects/x/x

Я успішно виправив це, зайшовши в каталог корумпованого об’єкта. Я бачив, що користувачі, призначені для цього об’єкта, не є моїм користувачем git. Я не знаю, як це сталося, але я запустив chown git:gitцей файл і потім він знову працював.

Це може бути потенційним виправленням проблем деяких народів, але не обов'язково для всіх.


2

Я отримав цю помилку після того, як моя (Windows) машина вирішила перезавантажитись. На щастя, моє віддалене репо було оновлене, тому я щойно зробив свіжий клон git ..



2

Я дотримувався багатьох інших кроків тут; Особливо корисним був опис Лінуса про те, як подивитися на git дерево / предмети та знайти те, чого немає. git-git відновити зіпсовану крапку

Але врешті-решт, у мене з’явилися розпущені / пошкоджені дерева-об’єкти, спричинені частковою відмовою диска, а дерева-об’єкти не так легко відновити / не покрити цим документом.

Врешті-решт, я перемістив конфліктуючу objects/<ha>/<hash>сторону і використав git unpack-objectsіз файлом пакету від досить сучасного клону. Це вдалося відновити відсутні об'єкти дерева.

Все-таки залишив у мене багато звисаючих крапель, що може бути побічним ефектом розпакування раніше заархівованих матеріалів, а також вирішених в інших питаннях тут


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  

є - встановити-вгору-до-правильний аргумент? Я не думаю, що так!
Шаріф Мамун

2
git гілка (--set-upstream-to = <upstream> | -u <upstream>) [<ім'я власника>]
Ertuğrul Altınboğa

Якщо ви вилучите .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але це не допомогло. Оскільки збій стався під час git push, це, очевидно, сталося під час перезапису на стороні клієнта, що відбувається після оновлення сервера. Я озирнувся і зрозумів, що c2388в моєму випадку це об'єкт фіксації, оскільки на нього посилаються записи в .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 / object / за його ім'ям, він, ймовірно, був [packed] [pack] для економії простору.)


0

У мене була така ж проблема в моєму голому віддаленому репо-релізі. Після довгого усунення несправностей я зрозумів, що один із моїх колег здійснив фіксацію, коли деякі файли в .git / об’єктах мали дозволи 440 (r - r -----) замість 444 (r - r - r -). Після того як попросити колегу змінити дозволи на "chmod 444 -R об'єкти" всередині голого git repo, проблема була усунена.


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та рефлогуванні в .git/logs/HEAD.


0

Коли у мене виникла ця проблема, я створив резервну копію своїх останніх змін (оскільки я знав, що я змінив), а потім видалив цей файл, на який скаржився у .git / location. Тоді я зробив git тягнуть. Але будьте обережні, це може не підійти для вас.


0

Я стикався з цим, як тільки моя система вийшла з ладу. Що я зробив, це це:

(Зверніть увагу, що ваші корупційні комісії втрачені, але зміни зберігаються. Можливо, вам доведеться відтворити ці комісії в кінці цієї процедури)

  • Створіть резервну копію коду.
  • Перейдіть у свій робочий каталог та видаліть .gitпапку.
  • Тепер клонуйте пульт в іншому місці та скопіюйте .gitпапку в нього.
  • Вставте його у свій робочий каталог.
  • Здійсніть так, як хотіли.

-7

Просто видаліть папку .git і додайте її знову. Це просте рішення працювало для мене.


3
Це призведе до пошкодження вашого локального сховища ..., може мати небажані побічні ефекти :) Будь ласка, відредагуйте пропозицію та додайте це попередження.
Фелікс

1
Якщо ви вилучите .gitта скопіюєте проект, який клонується, репо буде працювати, але ні місцеві відділення, ні сховища не збережуться. Також, дружню пропозицію, видаліть свою відповідь повністю, щоб перестати отримувати голоси.
Володимир Вуканак

1
хоч нелі ... поговоримо про використання базуки для роботи пінцетом.
Tuncay Göncüoğlu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.