Восстановление поврежденного 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 не распознал репозиторий.

Как я это исправил:

  1. Клонировал свежую копию с пульта.
  2. Скопировано файлов .git / index и .git / HEAD в поврежденный репозиторий .git.
  3. git наконец-то распознал репо, поэтому я выполнил жесткую проверку.
  4. Успех

Примечание. Если у вас были незафиксированные изменения, этот метод их переопределит.

git-ремонт ( sudo apt install git-repair) и у меня сработало несколько дополнительных команд:

  1. Создайте резервную копию поврежденного репозитория.

  2. Удалить неработающие ссылки:
    find .git/refs -size 0 -delete -print

  3. Восстановить репозиторий с удаленного(-ых):
    git-repair --force

  4. Очистите оборванные коммиты:
    git gc --prune=now

  5. Получить последнее состояние с удаленного компьютера:
    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
Другие вопросы по тегам