Как исправить поврежденный репозиторий git?

Я связал клонирование моего репо, которое я держу на своей ubuntu одной папке на новую машину, и я получил это:

[email protected]:~/source/personal$ git clone ~/Ubuntu\ One\ Side\ Work/projects.git/
Cloning into 'projects'...
done.
fatal: unable to read tree 29a422c19251aeaeb907175e9b3219a9bed6c616
[email protected]:~/source/personal$ 

Итак, я попробовал посмотреть на многие другие вопросы, которые были заданы здесь, и большинство из них говорит, чтобы запустить git fsck --full, а затем я получаю это, когда я это пробую.

[email protected]:~/Ubuntu One Side Work/projects.git$ git fsck --full
Checking object directories: 100% (256/256), done.
Checking objects: 100% (447/447), done.
broken link from  commit 235ae1f48701d577d71ebd430344a159e5ba4881
              to  commit 984c11abfc9c2839b386f29c574d9e03383fa589
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    blob 25a742dff0a403b2b3884f2ffddf63eb45721fac
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    blob dd4e97e22e159a585b20e21028f964827d5afa4e
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    tree 29a422c19251aeaeb907175e9b3219a9bed6c616
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    tree 8084e8e04d510cc28321f30a9646477cc50c235c
broken link from    tree 774b5b4157b4caae1c6cad96c8eaf5d4eba2c628
              to    blob a0daa0c1567b55d8de2b4d7a3bc010f58c047eab
broken link from    tree 774b5b4157b4caae1c6cad96c8eaf5d4eba2c628
              to    blob e9052d35bfb6d30065b206fc43f4200a04d5281b
broken link from    tree 774b5b4157b4caae1c6cad96c8eaf5d4eba2c628
              to    blob 1a3a5e4dd2502ac121c22f743c4250e254a94eeb
broken link from    tree 4aa336dc1a5838e8918e03b85580069d83f4ad09
              to    tree 8cc55ec952dc192a233e062201d1e7e873ac3db0
broken link from    tree e5674a91a53e15575a1f3bf5786bc5cc719fb483
              to    blob 4a994e1e7bb7ce28dcec98bad48b9a891d7dec51
broken link from    tree e5674a91a53e15575a1f3bf5786bc5cc719fb483
              to    blob ac033bf9dc846101320c96a5ce8aceb8c96ec098
broken link from    tree 252ab84542264e1589576b6ee51e7a31e580a0e2
              to    tree 2069041cd5950e529e2991d37b7290ec021d90d4
broken link from    tree 2d4964aa4d4f5d8c7228518ce72ef6a63f820c6d
              to    blob d83690e1b9a6bdd8a08754b38231799acefcb2ab
broken link from    tree c7192e82fc581bd6448bda1a25e8729bdac5f4ff
              to    blob 30d54d47ae82add1917ca173d42e58b396df580b
broken link from    tree 7c66306901fc71389623286936cef172d4ffe408
              to    blob bc7e05d705401273b1df4e939de0f540597c0931
broken link from    tree 0940f5fd227d4c84d6e6749d872db50a4522ae3a
              to    tree 923767594ac22023e824948d65622fe5b407d1a1
broken link from    tree 8eadcd2a971e8357d24f0d80f993d2963452209f
              to    blob 2598bde3dc8cb80ee49510b8159344004b88645f
broken link from    tree ffa302dd0d969172ef23caeefe856ab2f57a4e4d
              to    blob d6925fa431be1ac585bf9a481e98f75107a6e6fb
broken link from    tree 7045b8870a49ce30a2027537a96d73d162bda773
              to    blob 25688652dea26f61f576ca1b52b9d1a18fbfd01d
broken link from    tree 37e4705d34bd440ce681ae32ae9a180a13256d72
              to    tree 246f564d4cee53339b8a4244f3173b61caa518eb
missing blob d6925fa431be1ac585bf9a481e98f75107a6e6fb
missing blob ac033bf9dc846101320c96a5ce8aceb8c96ec098
missing tree 29a422c19251aeaeb907175e9b3219a9bed6c616
missing tree 8084e8e04d510cc28321f30a9646477cc50c235c
missing blob 30d54d47ae82add1917ca173d42e58b396df580b
missing tree 8cc55ec952dc192a233e062201d1e7e873ac3db0
missing blob e9052d35bfb6d30065b206fc43f4200a04d5281b
dangling tree 4b26e95db542c72ac4a22ec25abe38fb2de79752
missing blob d83690e1b9a6bdd8a08754b38231799acefcb2ab
missing blob 25a742dff0a403b2b3884f2ffddf63eb45721fac
missing tree 923767594ac22023e824948d65622fe5b407d1a1
missing blob 25688652dea26f61f576ca1b52b9d1a18fbfd01d
missing blob 2598bde3dc8cb80ee49510b8159344004b88645f
dangling tree 3a683869f1bb0c1634de75700c316b3b36570dbd
dangling blob 4098d30843380d798a811f1aa9a02994f0dbbb27
missing tree 2069041cd5950e529e2991d37b7290ec021d90d4
missing blob 4a994e1e7bb7ce28dcec98bad48b9a891d7dec51
missing blob 1a3a5e4dd2502ac121c22f743c4250e254a94eeb
missing blob a0daa0c1567b55d8de2b4d7a3bc010f58c047eab
dangling tree 6c7b5162aa7a303fa3fe8dc393c5da564e309521
missing commit 984c11abfc9c2839b386f29c574d9e03383fa589
missing blob bc7e05d705401273b1df4e939de0f540597c0931
missing blob dd4e97e22e159a585b20e21028f964827d5afa4e
missing tree 246f564d4cee53339b8a4244f3173b61caa518eb
dangling commit a01f5c1e5315dc837203d6dee00d3493be9c5db9

Это выглядит очень плохо. Когда я делаю git log | head, я получаю это

[email protected]:~/Ubuntu One Side Work/projects.git$ git log | head
error: Could not read 984c11abfc9c2839b386f29c574d9e03383fa589
fatal: Failed to traverse parents of commit 235ae1f48701d577d71ebd430344a159e5ba4881
commit 2fb0d2d0643b445440f01b164f11ee9ee71fca48
Author: christopher <[email protected]>
Date:   Wed Aug 7 15:51:42 2013 -0400

    finishing chapter 7

Другие вопросы здесь говорят о ./git/refs/heads/master. Это голое репо и refs/heads/ существует, но refs/heads/master нет. Голова в голой репо говорит ref: refs/heads/master хотя

packed-refs говорит об этом, хотя

# pack-refs with: peeled 
2fb0d2d0643b445440f01b164f11ee9ee71fca48 refs/heads/master

Другие вопросы предложили запустить git reflog, и при его запуске ничего не выводится.

Поэтому я действительно не знаю, что делать здесь. Какую стратегию следует принять? Возможно ли reset перейти к этой последней фиксации 7 августа.

EDIT:

Выполнение журнала git и переход к нижней части экрана показывают это:

commit 996e03b949aea176238e3c7a8452700bbb987ac9
Author: christopher <[email protected]>
Date:   Wed Jul 3 23:00:44 2013 -0400

    many many changes
error: Could not read 984c11abfc9c2839b386f29c574d9e03383fa589
fatal: Failed to traverse parents of commit 235ae1f48701d577d71ebd430344a159e5ba4881

Кажется, что это препятствует работе git от работы

Ответы

Ответ 1

В качестве альтернативы последней опции CodeGnome, если повреждено только локальное репо, и вы знаете URL-адрес удаленного, вы можете использовать это, чтобы повторно установить свой .git в соответствии с удаленным (заменив ${url} на удаленный URL-адрес):

  mv -v.git.git_old && & & # удалить старый git
git init && # инициализировать новый репо
git remote add origin "$ {url}" && & # ссылка на старый репо
git fetch && # получить старую историю
git reset origin/master --mixed # принудительное обновление старой истории
Код>

Это оставляет ваше рабочее дерево неповрежденным и влияет только на бухгалтерский учет git.
Я также недавно сделал bash script для этой цели  (Приложение A), что немного снижает безопасность этой операции.

Примечание:

Если у вашего репо есть подмодули, этот процесс каким-то образом их испортит, и единственное решение, которое я нашел до сих пор, - это удалить их, а затем с помощью обновления кода git subodule --init клонирование репо, но это тоже выглядит как ).

Приложение A - Полный сценарий

<Предварительно > <код > #!/Bin/Баш # Автор: Zoey Llewellyn "Zobean" Hewll # # Использование: fix-git [REMOTE-URL] # Должен быть запущен из корневого каталога репозитория. # Если пульт не поставляется, он будет считан из .git/config # # Если у вас поврежден локальный репо, но есть доверенный пульт. # Этот script заменяет всю вашу историю удаленной. # Если есть .git, он будет скопирован как .git_old, удалив последнюю резервную копию. # Это не влияет на рабочее дерево. # # В настоящее время это не работает с подмодулями! # Это прервется, если обнаружен подозрительный подмодуль. # Вам сначала нужно удалить их # и повторно клонировать их после (с `git subodule update --init`) # # Коды ошибок: # 1: Если URL-адрес не указан, и его нельзя прочитать из .git/config # 4: Если URL не может быть достигнут # 5: Если обнаружен god-подмодуль if [[ "$ (find -name.git -not -path./.git | wc -l)" -gt 0]]; тогда   echo "Похоже, что это репо использует подмодули" > & 2   echo "Вам нужно будет удалить их, прежде чем script может безопасно выполнить" > & 2   echo "Затем используйте обновление` `git subodule --init \` для повторного клонирования" > & 2   выход 5 фи если [[$ # -ge 1]]; тогда   URL = "$ 1" еще   если! url = "$ (git config --local --get remote.origin.url)";   тогда       echo "Невозможно найти удаленное" происхождение ": отсутствует в '.git/config'" > & 2       выход 1   фи фи url_base = "$ (echo" ${url} "| sed -E ';; ^ ([^/] *://)? ([^/] *) (/.*)? $;\2;' )" echo "Попытка доступа к ${url_base} перед продолжением" если! wget -p "$ {url_base}" -O/dev/null -q --dns-timeout = 5 --connect-timeout = 5; тогда   echo "Невозможно достичь ${url_base}: прерывание до того, как будет выполнен любой урон" > & 2   выход 4 фи эхо echo "Эта операция заменит местное репо на пульте дистанционного управления на:" echo "$ {url}" эхо echo "Это полностью перепишет историю", эхо ", но оставит ваше рабочее дерево неповрежденным" echo -n "Вы уверены? (y/N):" читать подтверждение если! [-t 0]; # Я открыт в трубе тогда   # распечатать входной канал   echo "$ {confirm}" фи if echo "$ {confirm}" | grep -Eq "[Yy] + [EeSs] *"; # это похоже на да тогда   если [[-e.git]];   тогда       # удалить старую резервную копию       rm -vrf.git_old | tail -n 1 & &       # backup.git, если он существует       mv -v.git.git_old   fi & &   git init & &   git remote add origin "$ {url}" && &   git config --local --get remote.origin.url | sed 's/^/Добавлен удаленный источник в /' & &   git fetch & &   git reset origin/master --mixed еще   эхо "Отмена без каких-либо действий" фи Код >

Ответ 2

TL; DR

Git на самом деле не хранит историю так, как вы думаете. Он вычисляет историю во время выполнения на основе цепи предков. Если в вашей родословной отсутствуют капли, деревья или коммиты, вы не сможете полностью восстановить свою историю.

Восстановление отсутствующих объектов из резервных копий

Первое, что вы можете попробовать, - восстановить отсутствующие элементы из резервной копии. Например, посмотрите, есть ли резервная копия фиксации, сохраненная как .git/objects/98/4c11abfc9c2839b386f29c574d9e03383fa589. Если это возможно, вы можете восстановить его.

Вы также можете посмотреть git-verify-pack и git-unpack-objects в том случае, если commit уже упакован, и вы хотите вернуть его в свободный объект для операций с хранилищем.

Хирургическая резекция

Если вы не можете заменить отсутствующие элементы из резервной копии, вы можете урезать недостающую историю. Например, вы можете изучить свою историю или журнал, чтобы найти предок фиксации 984c11abfc9c2839b386f29c574d9e03383fa589. Если вы найдете один неповрежденный, то:

  • Скопируйте рабочий каталог Git во временный каталог где-нибудь.
  • Сделайте жесткий reset неповрежденным фиксатором.
  • Скопируйте ваши текущие файлы обратно в дерево работы Git, но не забудьте скопировать папку .git обратно!
  • Зафиксируйте текущее дерево работы и сделайте все возможное, чтобы рассматривать его как сжатую фиксацию всей отсутствующей истории.

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

Полное восстановление и повторная инициализация

Если ваш репозиторий все еще сломан, то, надеюсь, у вас есть неповрежденная резервная копия или клон, с которого вы можете восстановить. Если нет, но ваш текущий рабочий каталог содержит допустимые файлы, вы всегда можете повторно инициализировать Git. Например:

rm -rf .git
git init
git add .
git commit -m 'Re-initialize repository without old history.'

Это сильно, но это может быть ваш единственный вариант, если ваша история репозитория действительно невосстанавливается. YMMV.

Ответ 3

Здесь script (bash) для автоматизации первого решения с помощью @CodeGnome для восстановления из резервной копии (выполняется с верхнего уровня поврежденного репо). Резервное копирование не должно быть полным, оно должно иметь недостающие объекты.

git fsck 2>&1 | grep -e missing -e invalid | awk '{print $NF}' | sort -u |
    while read entry; do
        mkdir -p .git/objects/${entry:0:2}
        cp ${BACKUP}/objects/${entry:0:2}/${entry:2} .git/objects/${entry:0:2}/${entry:2}
    done

Ответ 4

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

git fetch && git reset --hard

Ответ 5

Если вы в отчаянии, вы можете попробовать следующее:

git clone ssh://[email protected]/path/to/project destination --depth=1

Он получит ваши данные, но вы потеряете историю. Я пошел с проб и ошибок в моем репо и --depth=10 работал, но --depth=50 дал мне сбой.

Ответ 6

Прежде чем попробовать какие-либо исправления, описанные на этой странице, я бы посоветовал сделать копию вашего репо и работать только с этой копией. Затем в конце, если вы можете исправить это, сравните его с оригиналом, чтобы убедиться, что вы не потеряли файл в процессе ремонта.

Другая альтернатива, которая работала для меня, заключалась в reset головке и индексе git в предыдущем состоянии, используя:

git reset --keep

Вы также можете сделать то же самое вручную, открыв графический интерфейс git и выбрав каждый "Поэтапные изменения" и нажмите "Снять изменения". Когда все не установлено, вы должны теперь сжимать свою базу данных, проверять свою базу данных и совершать транзакции.

Я также пробовал следующие команды, но они не работали для меня, но они могут для вас в зависимости от конкретной проблемы:

git reset --mixed
git fsck --full
git gc --auto
git prune --expire now
git reflog --all

Наконец, чтобы избежать этой проблемы синхронизации, повреждающей ваш индекс git (который может произойти с DropBox, SpiderOak или любым другим облачным диском), вы можете сделать следующее:

  • Преобразуйте свою папку .git в один "пакет" git файл, используя: git bundle create my_repo.git --all, тогда он должен работать так же, как и раньше, но поскольку все находится в одном файл, вы не будете подвергать риску синхронизацию, повреждающую ваш репозиторий git.
  • Отключить мгновенную синхронизацию. SpiderOak позволяет вам настроить планирование для проверки изменений на "автоматический" (что означает, что это как можно скорее, отслеживание изменений файла благодаря уведомлениям ОС). Это плохо, потому что он начнет загружать изменения, как только вы делаете изменения, а затем загрузите изменения, чтобы они могли удалить последние изменения, которые вы только что делали. Решение этой проблемы заключается в том, чтобы установить задержку мониторинга изменений на 5 минут и более. Это также устраняет проблемы с приложениями для заметок с мгновенным сохранением (например, Notepad ++).

Ответ 7

Я столкнулся с той же проблемой, поэтому я заменил папку ".git" резервной копией, и она все еще не работала, потому что файл .gitconfig был поврежден. BSOD на моем ноутбуке испортил его. Я заменил его следующим кодом, и sourcetree восстановил все мои репозитории.

[user]
name = *your username*
email = *your email address*
[core]
autocrlf = true
excludesfile = C:\\Users\\*user name*\\Documents\\gitignore_global.txt

Я не знаю, поможет ли это кому-либо, но это просто другое решение, которое сработало для меня.

Ответ 8

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

Ответ 9

Я попытался удалить объектные файлы с 0 байтами и извлечь их снова с пульта, и это сработало:

find . -type f -size 0 -exec mv {} /tmp \;
git fetch

Он извлек недостающие объекты с пульта и позволил мне продолжить работу без повторной инициализации всего репо.

Ответ 10

Быстрый способ, если у вас есть изменения в вашем текущем проекте и вы не хотите его потерять, перенесите ваш текущий проект куда-нибудь, клонируйте проект из github в эту папку и внесите некоторые изменения, чтобы попытаться зафиксировать снова. Или просто удалите репо и клонируйте его снова, это сработало у меня.

Ответ 11

Я хотел добавить это в качестве комментария под Zoey Hewil, отличный ответ выше, но у меня в настоящее время нет достаточно представителей, чтобы сделать это, поэтому я должен добавить это здесь и отдать должное ее работе: P

Если вы используете Poshgit и чувствуете себя чрезвычайно ленивым, вы можете использовать следующее, чтобы автоматически извлечь ваш URL из вашей конфигурации git и упростить работу. Стандартные предостережения относятся к проверке этого на копии/резервное копирование вашего локального репо в случае, если он взорвется вам в лицо.

$config = get-content .git\config
$url = $config -match " url = (?<content>.*)"
$url = $url.trim().Substring(6)
$url

move-item -v .git .git_old;
git init;
git remote add origin "$url";
git fetch;
git reset origin/master --mixed

Ответ 12

Вы можете попробовать на клонированном репо на вашей новой машине, как в Git - как восстановить из пропавшего blob:

git reflog --all --expire=now
git gc --prune=<date> 

Попробуйте "now" для <date>, затем вернитесь во времени, 7 августа, чтобы удалить ссылки на те отсутствующие blobs.
Но это означало бы потерю работы, связанной с этими коммитами...

Для синхронизированной папки (Ubuntu One), только сохранить пакет, а не полное репо.
Пакет - это всего лишь один файл.

Ответ 13

Эта команда работала для меня:

$ git reset --mixed