Как восстановить объекты Git, поврежденные сбоем жесткого диска?
у меня был сбой жесткого диска, который привел к повреждению некоторых файлов репозитория Git. При запуске git fsck --full Я получаю следующий вывод:
error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch
error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid code lengths set)
error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid stored block lengths)
error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack
fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted
у меня есть резервные копии репозитория, но единственная резервная копия, которая включает файл пакета, уже повреждена. Поэтому я думаю, что мне нужно найти способ получить отдельные объекты из разных резервных копий и каким-то образом поручить Git создать новый пакет с только правильными объектами.
не могли бы вы дать мне подсказывает, как исправить мой репозиторий?
7 ответов:
в некоторых предыдущих резервных копиях ваши плохие объекты могут быть упакованы в разные файлы или еще могут быть свободными объектами. Так что ваши объекты могут быть восстановлены.
кажется, есть несколько плохих объектов в базе данных. Так что вы можете сделать это вручную.
из-за
git hash-object,git mktreeиgit commit-treeне записывайте объекты, потому что они находятся в пакете, а затем начните делать это:mv .git/objects/pack/* <somewhere> for i in <somewhere>/*.pack; do git unpack-objects -r < $i done rm <somewhere>/*(ваши пакеты перемещаются из репозитория, и распаковал снова в нем; только хорошие объекты теперь находятся в базе данных)
вы можете сделать:
git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978eeи проверьте тип объекта.
если тип blob: извлеките содержимое файла из предыдущих резервных копий (с
git showилиgit cat-fileилиgit unpack-file, потомgit hash-object -wдля перезаписи объекта в текущем репозитории.если тип дерева: вы могли бы использовать
git ls-treeдля восстановления дерева из предыдущих резервных копий; затемgit mktreeto запишите его снова в текущем репозитории.если тип commit: то же самое с
git show,git cat-fileиgit commit-tree.конечно, я бы сделал резервную копию вашей оригинальной рабочей копии перед началом этого процесса.
кроме того, взгляните на как восстановить поврежденный объект Blob.
Banengusk ставил меня на правильный путь. Для получения дополнительной информации я хочу опубликовать шаги, которые я предпринял, чтобы исправить повреждение репозитория. Мне посчастливилось найти все необходимые объекты либо в старых пакетах, либо в резервных копиях репозитория.
# Unpack last non-corrupted pack $ mv .git/objects/pack .git/objects/pack.old $ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack $ git log fatal: bad object HEAD $ cat .git/HEAD ref: refs/heads/master $ ls .git/refs/heads/ $ cat .git/packed-refs # pack-refs with: peeled aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master $ git fsck --full error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1 error: refs/heads/master does not point to a valid object! missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919 missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc # Copy HEAD object from backup of repository $ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa # Now copy all missing objects from backup of repository and run "git fsck --full" afterwards # Repeat until git fsck --full only reports dangling objects # Now garbage collect repo $ git gc warning: reflog of 'HEAD' references pruned commits warning: reflog of 'refs/heads/master' references pruned commits Counting objects: 3992, done. Delta compression using 2 threads. fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232) error: failed to run repack # Check reflogs... $ git reflog # ...then clean $ git reflog expire --expire=0 --all # Now garbage collect again $ git gc Counting objects: 3992, done. Delta compression using 2 threads. Compressing objects: 100% (3970/3970), done. Writing objects: 100% (3992/3992), done. Total 3992 (delta 2060), reused 0 (delta 0) Removing duplicate objects: 100% (256/256), done. # Done!
сначала попробуйте выполнить следующие команды (при необходимости повторите их):
$ git fsck --full $ git gc $ git gc --prune=today $ git fetch --all $ git pull --rebaseи тогда у вас все еще есть проблемы, попробуйте может:
удалите все поврежденные объекты, например
fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt $ rm -v .git/objects/06/91c5...51e5удалить все пустые объекты, например,
error: object file .git/objects/06/91c5...51e5 is empty $ find .git/objects/ -size 0 -exec rm -vf "{}" \;проверьте сообщение "сломанная ссылка":
git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8это будет говорит вам, какой файл коррумпированный blob пришел откуда?
чтобы восстановить файл, вам может очень повезти, и это может быть версия, которую вы уже проверили в своем рабочем дереве:
git hash-object -w my-magic-fileснова, и если он выводит отсутствующий SHA1 (4b945..) вы теперь все сделали!
предполагая, что это была какая-то более старая версия, которая была сломана, самый простой способ сделать это-сделать:
git log --raw --all --full-history -- subdirectory/my-magic-fileи что покажет вам весь журнал для этого файла (пожалуйста, поймите что дерево, которое у вас было, может быть не деревом верхнего уровня, поэтому вам нужно выяснить, в каком подкаталоге он был самостоятельно), то теперь вы можете снова воссоздать отсутствующий объект с помощью hash-object.
чтобы получить список всех ссылок с отсутствующими коммитами, деревьями или блобами:
$ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; doneвозможно, невозможно удалить некоторые из этих ссылок с помощью обычных команд branch-d или tag-d, поскольку они умрут, если git заметит повреждение. Так что используйте сантехнику команда git update-ref-d $ref вместо этого. Обратите внимание, что в случае локальных ветвей эта команда может оставить устаревшую конфигурацию ветвей позади.git / config. Его можно удалить вручную (найдите раздел [branch "$ref"]).
после того, как все рефы чистые, есть все еще может быть нарушена совершает в reflog. Вы можете очистить все рефлоги с помощью Git reflog expire --expire=now --all. Если вы не хотите потерять все свои рефлоги, вы можете искать отдельные ссылки для сломанных reflogs:
$ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done(обратите внимание на добавленную опцию-g в Git rev-list.) Затем используйте git reflog expire --expire=now $ref на каждом из них. Когда все сломанные ссылки и рефлоги исчезли, запустите git fsck --full, чтобы проверить, что репозиторий чист. Висячие объекты в порядке.
ниже вы можете найти расширенное использование команд, которые потенциально могут привести к потере ваших данных в вашем репозитории git, если они не используются разумно, поэтому сделайте резервную копию раньше вы случайно делаете дальнейшие повреждения своему git. Попробуйте на свой страх и риск, если вы знаете, что делаете.
чтобы вытащить текущую ветвь поверх восходящей ветви после извлечения:
$ git pull --rebaseвы также можете попробовать проверить новую ветку и удалить старую:
$ git checkout -b new_master origin/master
чтобы найти поврежденный объект в git для удаления, выполните следующую команду:
while [ true ]; do f=`git fsck --full 2>&1|awk '{print }'|sed -r 's/(^..)(.*)/objects\/\//'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; doneдля OSX, используйте
sed -Eвместоsed -r.
другая идея состоит в том, чтобы распаковать все объекты из файлов пакета, чтобы восстановить все объекты внутри .git / objects, поэтому попробуйте выполнить следующие команды в вашем репозитории:
$ cp -fr .git/objects/pack .git/objects/pack.bak $ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done $ rm -frv .git/objects/pack.bak
если выше не помогает, вы можете попробовать rsync или скопировать объекты git из другого РЕПО, например
$ rsync -varu git_server:/path/to/git/.git local_git_repo/ $ rsync -varu /local/path/to/other-working/git/.git local_git_repo/ $ cp -frv ../other_repo/.git/objects .git/objects
чтобы исправить сломанную ветку при попытке проверки следующим образом:
$ git checkout -f master fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625Попробуйте удалить его и загрузить из вверх по течению снова:
$ git branch -D master $ git checkout -b master github/masterв случае, если git приведет вас в отстраненное состояние, проверьте
masterи слиться с ней в отдельной ветке.
другая идея состоит в том, чтобы перебазировать существующее мастер рекурсивно:
$ git reset HEAD --hard $ git rebase -s recursive -X theirs origin/master
Читайте также:
- некоторые трюки для восстановления объектов blob, чтобы исправить поврежденный репозиторий.
- как исправить сломанный хранилище?
- Как удалить все сломанные ссылки из репозитория?
- как исправить поврежденный репозиторий git? (seeques)
- как исправить поврежденный репозиторий git? (qnundrum)
- ошибка при использовании SourceTree с Git: 'Summary' failed with code 128: fatal: не удается прочитать дерево
- Восстановить Поврежденный Git Голый Репозиторий
- восстановление поврежденного репозитория git
- как исправить ошибку git: объект empy / поврежден
- как диагностировать и исправить git fatal: невозможно прочитать дерево
- как справиться с этой ошибкой git
- как исправить поврежденный репозиторий git?
- как мне "перезаписать", а не "объединить" ветку на другой ветке в гите?
- как заменить главную ветвь в git, полностью, из другой ветви?
- Git: "коррумпированный свободный объект"
- git reset = fatal: не удается прочитать дерево
вот шаги, которые я следовал, чтобы восстановить из поврежденного объекта blob.
1) Определить коррумпированный blob
git fsck --full error: inflate: data stream error (incorrect data check) error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing ...коррумпированный blob - это 241091723c324aed77b2d35f97a05e856b319efd
2) переместить поврежденный blob в безопасное место (на всякий случай)
mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/3) получить родитель коррумпированного blob
git fsck --full Checking object directories: 100% (256/256), done. Checking objects: 100% (70321/70321), done. broken link from tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180 to blob 241091723c324aed77b2d35f97a05e856b319efdродитель хэш -0716831e1a6c8d3e6b2b541d21c4748cc0ce7180.
4) получить соответствующее имя файла чтобы испортить blob
git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180 ... 100644 blob 241091723c324aed77b2d35f97a05e856b319efd dump.tar.gz ...найдите этот конкретный файл в резервной копии или в вышестоящем репозитории git (в моем случае это свалка.смола.ГЗ). Затем скопируйте его где-нибудь в локальном репозитории.
5) Добавить ранее поврежденный файл в базу данных объектов git
git hash-object -w dump.tar.gz6) празднуем!
git gc Counting objects: 75197, done. Compressing objects: 100% (21805/21805), done. Writing objects: 100% (75197/75197), done. Total 75197 (delta 52999), reused 69857 (delta 49296)
git checkout может фактически выбрать отдельные файлы из ревизии. Просто дайте ему хэш фиксации и имя файла. Более подробная информация здесь.
Я думаю, что самый простой способ исправить это безопасно-вернуться к новейшей незафиксированной резервной копии, а затем выборочно выбрать неповрежденные файлы из новых коммитов. Удачи вам!
вот две функции, которые могут помочь, если ваша резервная копия повреждена или у вас есть несколько частично поврежденных резервных копий, а также (это может произойти, если вы резервное копирование поврежденных объектов).
запустите оба в репо, которое вы пытаетесь восстановить.
стандартное предупреждение: используйте только если вы действительно в отчаянии, и вы создали резервную копию своего (поврежденного) РЕПО. Это может ничего не решить, но по крайней мере должно подчеркнуть уровень коррупция.
fsck_rm_corrupted() { corrupted='a' while [ "$corrupted" ]; do corrupted=$( \ git fsck --full --no-dangling 2>&1 >/dev/null \ | grep 'stored in' \ | sed -r 's:.*(\.git/.*)\).*::' \ ) echo "$corrupted" rm -f "$corrupted" done } if [ -z "" ] || [ ! -d "" ]; then echo "'' is not a directory. Please provide the directory of the git repo" exit 1 fi pushd "" >/dev/null fsck_rm_corrupted popd >/dev/nullи
unpack_rm_corrupted() { corrupted='a' while [ "$corrupted" ]; do corrupted=$( \ git unpack-objects -r < "" 2>&1 >/dev/null \ | grep 'stored in' \ | sed -r 's:.*(\.git/.*)\).*::' \ ) echo "$corrupted" rm -f "$corrupted" done } if [ -z "" ] || [ ! -d "" ]; then echo "'' is not a directory. Please provide the directory of the git repo" exit 1 fi for p in /objects/pack/pack-*.pack; do echo "$p" unpack_rm_corrupted "$p" done
Comments