Восстановление поврежденного Git-репозитория
Мой репозиторий Git был поврежден после нескольких жестких перезагрузок из-за проблем с питанием, и теперь я не могу это исправить (я был в процессе подготовки некоторых файлов при последнем сбое питания):
$ git status
fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument
$ git fsck
fatal: failed to read object 24377c609184c192f3f3c1733bac7115c1080758: Invalid argument
$ git branch -a
(...works, lists branches...)
$ git checkout someotherbranch
fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument
$ git log
fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument
$ git log someotherbranch
(...works, shows commits...)
Итак, как вы можете видеть, моя текущая ветка довольно испорчена, и я, похоже, не могу это исправить. Что я могу попытаться исправить это?
14 ответов
Мое решение для подобной ситуации состояло в том, чтобы заменить хэш поврежденного объекта в .git/refs/heads/my-working-branch
с хешем предыдущего коммита (который можно найти в .git/logs/HEAD
).
Это только что случилось со мной. Я откладываю репозиторий в новую папку и перемещаю свои последние изменения вручную. Низкая технология, но она работает каждый раз. Надеюсь, вы можете вспомнить свои последние изменения.
Самое простое решение для меня: ты мог git clone
в новой папке, затем замените чистую new_folder/.git на старую папку (сломанная папка). Это хорошо работает для меня!
git clone ...(remote) new_folder
mv old_folder/.git old_folder/.git_old
cp -R new_folder/.git old_folder/
Попробуйте сделать резервную копию хранилища и затем запустите git reset --hard HEAD@{1}
вернуться к предыдущему HEAD
и посмотреть, если это работает. Это может быть просто ток HEAD
который поврежден.
(Вы также должны запустить fsck
на вашем диске, если вы еще этого не сделали.)
Для меня я включил TRIM в OS X с SSD не от Apple (что не рекомендуется) и, очевидно, вызвал различные повреждения на моем загрузочном диске. Так что коррумпированный коммит был глубоко в истории.
Я не слишком беспокоюсь о восстановлении своего репозитория, за исключением того, что у меня есть несколько локальных веток, которые были слишком экспериментальными, чтобы потрудиться надавить на удаленный репозиторий, и я хотел бы спасти работу в этих ветках.
Теоретически, поскольку это локальный репозиторий, я чувствую, что Git должен иметь возможность восстанавливать / восстанавливать себя, используя origin. Почему это невозможно?
Во всяком случае, я наткнулся на эту классную стратегию, чтобы перенести ветку в другой локальный репозиторий Git. К сожалению, клонирование хранилища в ../repo_copy
а затем использование этого в качестве локального пульта привело к следующей ошибке:
! git push --force local_remote HEAD
fatal: failed to read object e0a9dffddeeca96dbaa275636f8e8f5d4866e0ed: Invalid argument
error: failed to push some refs to '/Users/steve/Dev/repo_copy'
Вместо этого я начал с пустого хранилища, а затем вставил в него ветки, и все было в порядке. Так что для любого местного филиала у меня был чей git log
не заканчивается
....
Fixing cukes
fatal: failed to read object e0a9dffddeeca96dbaa275636f8e8f5d4866e0ed: Invalid argument
Я просто проверил бы это и затем сделал бы git push --force local_remote HEAD
, Последнее, что я сделал, было:
! cd ~/Dev/repo_copy
! git remote add origin git@github.com:sdhull/my_repo.git # real remote
Затем я вошел в git config -e
и настроил мою основную ветку и снова заработал, ничего не потеряв!
Другой альтернативой, которая работала для меня, было сбросить заголовок Git и индекс до его предыдущего состояния, используя:
git reset --keep
Я также попробовал следующие команды, но они не работали для меня, но они могли бы для вас:
git reset --mixed
git fsck --full
git gc --auto
git prune --expire now
git reflog --all
У меня была такая же проблема, и я сделал следующие шаги, используя git-repair
cp myrepo myrepo.bak
cd myrepo
git repair --force
(сначала попробуйте безforce
)
После этого дерево вернулось к последнему рабочему коммиту.
Тогда я сделал meld myrepo myrepo.bak
применить изменения из рабочего дерева поврежденного хранилища к фиксированному хранилищу.
Я смог восстановить свой репозиторий из:
zsh(broken)% git log master
error: object file .git/objects/7f/cab8648a989d9bb3f5246e6be7220395493395 is empty
error: object file .git/objects/7f/cab8648a989d9bb3f5246e6be7220395493395 is empty
fatal: loose object 7fcab8648a989d9bb3f5246e6be7220395493395 (stored in .git/objects/7f/cab8648a989d9bb3f5246e6be7220395493395) is corrupt
zsh(broken)% cat .git/refs/heads/master
7fcab8648a989d9bb3f5246e6be7220395493395
e311726c4eb970f4d4f504ad86248d322855018f da9c14d03e4849394087b61ff6272399937f7cce Nikolay Orliuk <virkony@gmail.com> 1379583764 +0300 commit: plan: timings
Путем сброса master
предварительно совершить da9c14d03e4849394087b61ff6272399937f7cce
как сказал @Nash Bridges:
zsh(broken)% echo da9c14d03e4849394087b61ff6272399937f7cce > .git/refs/heads/master
zsh(broken)% git log --oneline -1 master
da9c14d plan: timings
zsh(broken)% git fsck
Checking object directories: 100% (256/256), done.
error: object file .git/objects/0e/ace931fdc851da254e9522596d1517d0ed51c5 is empty
error: object file .git/objects/0e/ace931fdc851da254e9522596d1517d0ed51c5 is empty
fatal: loose object 0eace931fdc851da254e9522596d1517d0ed51c5 (stored in .git/objects/0e/ace931fdc851da254e9522596d1517d0ed51c5) is corrupt
Создание нового пустого репозитория, выборка master
из сломанного:
zsh(broken)% mkdir ../recover && cd ../recover && git init
Initialized empty Git repository in /home/nikolay/talks/y/recover/.git/
zsh(recover)% git fetch ../broken master
remote: Counting objects: 44, done.
remote: Compressing objects: 100% (44/44), done.
remote: Total 44 (delta 20), reused 0 (delta 0)
Unpacking objects: 100% (44/44), done.
From ../broken
* branch master -> FETCH_HEAD
zsh(recover)% git reset --hard FETCH_HEAD
HEAD is now at da9c14d plan: timings
zsh% git fsck
Checking object directories: 100% (256/256), done.
Чтобы восстановить те изменения, которые были на пути к master
:
zsh(recover)% rm -rf * && cp -a ../broken/* ./
zsh(recover)% git add -u && git commit -m 'prepare for publishing'
Я следовал инструкциям из раздела Восстановление из Git-хранилища:
$ cd /tmp/
$ git clone good-host:/path/to/good-repo
$ cd /home/user/broken-repo
$ echo /tmp/good-repo/.git/objects/ > .git/objects/info/alternates
$ git repack -a -d
$ rm -rf /tmp/good-repo
Это сработало для меня.
Если восстановить невозможно, иногда полезно восстановить содержимое. Следующая команда распечатает все содержимое неповрежденных объектов.
$ git cat-file --batch-check --batch-all-objects 2>&1 | grep blob | grep -v empty | awk '{ print $1; }' -
Если объекты существуют неповрежденными на удаленном компьютере, вы можете:
git fetch-pack --thin --keep <remote URL> <object-id(s)>
Получите URL-адрес отgit remote --verbose
.
Примечание:https://
не работает, это должен бытьgit://
URL-адрес.
Другой вариант:
Я создал полный клон репозитория в другой папке, а затем импортировал из него объекты.
В исходном репозитории (сначала сделайте резервную копию) я запустил:
git pull
git reset --hard origin/main # DESTRUCTIVE - reset index to a known good state
git unpack-objects < /path/to/new/clone/.git/objects/pack/<hash>.pack
git fsck --no-dangling
ИЛИ Неопробовано:
- Создайте новый клон пульта
- Добавьте новый клон в качестве альтернативы git.
- Бегать
git fsck
снова со всеми объектами, присутствующими через альтернативный
Винда давала синий экран, пока я менял ветки. Произошла загрузка резервной копии, все файлы были повреждены, и git не распознал репозиторий.
Как я это исправил:
- Клонировал свежую копию с пульта.
- Скопировано файлов .git / index и .git / HEAD в поврежденный репозиторий .git.
- git наконец-то распознал репо, поэтому я выполнил жесткую проверку.
- Успех
Примечание. Если у вас были незафиксированные изменения, этот метод их переопределит.
git-ремонт (
sudo apt install git-repair
) и у меня сработало несколько дополнительных команд:
Создайте резервную копию поврежденного репозитория.
Удалить неработающие ссылки:
find .git/refs -size 0 -delete -print
Восстановить репозиторий с удаленного(-ых):
git-repair --force
Очистите оборванные коммиты:
git gc --prune=now
Получить последнее состояние с удаленного компьютера:
git fetch
При желании переключитесь на master и сбросьте его на origin/master:
git checkout master
git reset --hard origin/master
Проверьте с помощью git fsck:
git fsck
У меня были поврежденные файлы, и я исправил их с помощью git-repair:
sudo apt install git-repair
git repair