Как восстановить поврежденный объект в репозитории git (для новичков)? - PullRequest
28 голосов
/ 01 сентября 2010

Я попытался открыть свой репозиторий сегодня, и в нем не было истории коммитов.Все, что я пытался (git status, git log, git checkout ...) выдавало ошибку о поврежденном объекте.

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

Затем я вернулся к статье о восстановлении «git-объекты, поврежденные из-за сбоя жесткого диска» и (после удаления объекта-преступника) работали до тех пор, пока

$ cat packed-refs

, и в этот момент мой компьютер сказал: cat: packed-refs: No such file or directory Я пропустилэтот шаг и сделал

$ git fsck --full

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

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

(я думаю, будет справедливо сказать, что я был изначально смущен простой чертой в файле Торвальдса между"git" и "fsck." Так что я ДЕЙСТВИТЕЛЬНО новичок в этом.)

BUG-LIST

Оригинальная ошибка:

$ git status
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

Ошибка после перемещения поврежденного объекта:

$ git status
fatal: bad object HEAD
$ git fsck --full
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

$ git ls-tree 2c1033501b82e301d47dbf53ba0a199003af25a8
040000 tree 4a8b0b3747450085b1cd920c22ec82c18d9311bd    folder1
040000 tree 33298295f646e8b378299191ce20b4594f5eb625    folder2
040000 tree dec82bad6283fc7fcc869c20fdea9f8588a2f1b2    folder3
040000 tree 4544967c6b04190f4c95b516ba8a86cab266a872    folder4

$ git ls-tree dec82bad6283fc7fcc869c20fdea9f8588a2f1b2
100644 blob 67bda6df733f6cd76fc0fc4c8a6132d8015591d8    fileA
100644 blob 4cb7272c9e268bfbd83a04e568d7edd87f78589c    fileB
100644 blob ce9e0f2cc4d3b656fa30340afbdfed47fe35f3ef    fileC

$ git ls-tree 4544967c6b04190f4c95b516ba8a86cab266a872
100644 blob d64fe3add8328d81b1f31c9dbd528956ab391fb6    fileD
100644 blob d1ebd7df7082abc5190d87caa821bf3edb7b68e8    fileE
100644 blob bb6cd264e47a3e5bc7beadf35ea13bac86024b02    ...
100644 blob 995d622b9012f4ef69921091d1e1a73f32aa94e6
100644 blob 9141dbd2b1c7931a6461195934b6599f5dfb485a 
100644 blob ab128da1d82907cd0568448dc089a7996d5f79d3
100644 blob 57b11a7eb408a79739d2bb60a0dc35c591340d18
100644 blob 118105291c1c6ca4a01744889ffafbb018bc7ed3
100644 blob 86b1dfda56d0603f16910228327751f869d16bdc
100644 blob 077fe0cddde0d0be9d0974f928f66815caca7b76
100644 blob c0b32fd0450f21994bdc53ea83d3cf0bccd74004
100644 blob 37b87a4d11453468c4ae04572db5d322cd2d1d80
100644 blob 79d39f8d4e57fa3a71664598a63b6dfd88149638
100644 blob ee07bbe3e8cb5d6bb79fb0cd52cfbc9bd830498d    files

$ git ls-tree 33298295f646e8b378299191ce20b4594f5eb625
100644 blob f9d6f45cd028aec97f761f00c5f4f2f6b50fb925    MoreFiles
100644 blob 0cb9eed1d0dd9214d54a03af1bda21f37b8c0d02
100644 blob 198e4f97ece735cce47b7e99b54f1b5fa99fabf5
100644 blob fc004212fa8e483e5a8ab35b508027c7a9a1cbfa
100644 blob 0c7d74c7a9a8337b4a9f20802b63d71d42287f89

$ git ls-tree 4a8b0b3747450085b1cd920c22ec82c18d9311bd
100644 blob 0320f5b23dd7cce677fac60b9ad03f418cff5c88    oneLASTfile

После перемещения поврежденного объекта обратно:

$ git log --raw --all
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

$ cat packed-refs
cat: packed-refs: No such file or directory

$ git fsck --full
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

После перемещения файла обратно:

$ git fsck --full`  
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

После распаковкифайл .pack:

$ git log
fatal: bad object HEAD

$ cat packed-refs
cat: packed-refs: No such file or directory

$ git fsck --full
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

Ответы [ 3 ]

18 голосов
/ 01 сентября 2010

Хорошо, так. Из второго сообщения об ошибке мы видим, что поврежденный объект, который вы переместили, был коммитом. (HEAD указывал на это!) К сожалению, это означает, что его трудно починить вручную. (Под «жестким» я подразумеваю, вероятно, невозможное, если вы не помните точно, что было сообщением о коммите и в какое время вы сделали коммит.) К счастью, это означает, что легко восстановить новый коммит с тем же содержимым файла - вы будете для этого нужно написать новое сообщение.

Прежде чем начать, посмотрите на содержимое .git/HEAD - если это имя ветки, запомните это на потом.

Во-первых, нам нужно выяснить, кем должен был быть родитель этого коммита. Вы можете использовать git reflog, чтобы просмотреть рефлог HEAD и найти SHA1 того места, где находился HEAD непосредственно перед тем, как сделать коммит 016660b. Это должно выглядеть примерно так:

016660b HEAD@{n}: commit: <subject of commit>
1234abc HEAD@{n-1}: ...

Вы можете скопировать SHA1 из предыдущей позиции HEAD и проверить этот коммит:

git checkout 1234abc

Тогда вы можете прочитать в дереве, что ваш поврежденный коммит имел:

git read-tree 2c1033501b82e301d47dbf53ba0a199003af25a8

А потом коммит!

git commit

Теперь есть некоторый вопрос о том, что должно было случиться с вашими ветвями. Если HEAD указывал на ветку (скажем, master), которая, в свою очередь, указывала на поврежденный коммит, мы определенно хотим это исправить:

git branch -d master       # remove the original master branch
git checkout -b master     # recreate it here

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

9 голосов
/ 21 декабря 2016

FWIW, вот ответ, который более практичен, чем многие из безнадежно оптимистичных ответов на другие вопросы о поврежденных git репозиториях - большинство из которых делают безосновательное предположение, что плохой ОП может «просто клонировать» с удаленного происхождение! Хм. Но. Подождите секунду. Что если Я - источник ?

Ужас

История начинается, когда попытка запустить простое git gc --aggressive показало, что в какой-то момент мое безоговорочное репо каким-то образом полностью скрывалось от моего - полностью локального - git хранилища: оно не могло регистрировать что-либо, кроме нескольких месяцев назад, тем самым потеряв большую часть своей истории, и гортанно кричал всякий раз, когда его просили git fsck --full | grep -v dangling. Несколько объектов были идентифицированы как потерянные git fsck.

git-repair: сокращение ужасающего ручного труда с 2014 года

После паники и нахождения множества вопросов с плохими ответами с чрезмерным количеством голосов, просто сказал: «Просто переклонируйте из удаленного источника!» - который, позвольте мне изложить точку зрения, у меня нет, потому что Я - источник - Я нашел git-repair, сделал простое sudo aptitude install git-repair и пусть он сделает все утомительные автоматические исправления, которые, вероятно, заняли бы у меня часы (пожалуйста: запустите копию вашего поврежденного репо [duh], без --force!)

Это помогло уменьшить количество ужасов, о которых сообщалось git fsck --full | grep -v dangling. Но вещи после середины августа все еще были недоступны.

В частности, все это, казалось, концентрировалось вокруг одного коммита, который не мог быть найден. Как я мог восстановить это? Поиск переполнения стека не сильно помог!

У вас есть резервная копия, верно?

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

Но отсутствующий объект, похоже, не был просто сохранен в этой резервной копии .git/objects/XY/RESTOFHASHBLAHBLAHBLAH. Это, вероятно, потому что это был коммит, а не файл. Я не знаю! git для меня волшебство, навсегда за пределами моей способности постичь. Мне просто нужно исправить, быстро. Разве не поэтому мы все здесь?

Восстановление объектов из резервной копии (которая у вас есть, верно?)

Теперь, когда у вас есть резервное копирование, у меня возникла смешная глупая идея, он сказал: «Это никак не сработает!» И сразу обнаружил, что просто наивно запускает файл cp -fr /path/to/repo_backup/.git/objects/* /path/to/repo_git-repaired/.git/objects в слияние каталога .git/objects резервная копия в ее поврежденном, частично восстановленном репо ... работала, чтобы восстановить всю историю - обратно в доброе старое initial commit lol. Проверка исправления: git fsck --full теперь тоже был счастлив (несмотря на все свисающие биты).

Затем я взял резервные копии живых / поврежденных, частично отремонтированных и, казалось бы, восстановленных репозиториев на отдельный диск, на случай, если мне понадобится какой-либо из них снова.

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

Бесконечные отказы от ответственности в бесконечных комбинациях

Теперь, очевидно, все это идет с предостережениями: вы должны попробовать все на копии вашего поврежденного репо, прочитать всю документацию, подумайте о том, чтобы быть немного более осторожным, чем я (это заставило * 1068) * команда), и не налагайте на меня ответственность или ответственность за абсолютно все, что идет не так * ... но это дает вам что-то лучше, чем «просто клонировать из удаленного источника!», верно?

* Если, однако, все идет правильно , может потребоваться большое пожертвование. ;)

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

5 голосов
/ 28 декабря 2011

У меня была такая же проблема.Однако моя проблема была решена с изменением прав доступа к папкам и подпапкам .git / objects (рекурсивно) на сервере.Что-то вроде:

chmod -R 770 .git/objects

Я думаю, что это не ваша проблема, но в моем случае она была решена.

...