git - fatal: ваша текущая ветка кажется сломанной (возможно, из-за прерванной тяги) - PullRequest
1 голос
/ 02 ноября 2019

Проблема:

  1. случайно сделал git --amend и протолкнул его на USB-ключ от первого компьютера
  2. , извлеченный из USB-ключа на второй компьютер
  3. второй компьютерный репозиторий теперь поврежден
  4. git pull на первый компьютер приводит к конфликту слияния;не понимает, будет ли это также поврежденным состоянием (если --amend поврежден)

Симптомы:

большинство команд:

fatal: your current branch appears to be broken

. git / refs / возглавляет / мастер:

$ cat .git/refs/heads/master

Содержимое файла .git / refs /heads / master:

'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

$ git status
new file: ...
new file: ... [for every file in the repository; expected since on a corrupted branch]

I'mне уверен, что я готов винить git --amend, так как он кажется несколько мягким;возможно что-то еще случилось.

Как исправить?:

Исправить это так же просто, как взять хеш из последней удачной фиксации .git / logs / refs /heads / master и вставить еевручную в .git / refs /глав / мастер? Как бы я это сделал, если

Если это так, должен ли я уничтожить оскорбительный коммит (чтобы он потом не испортил вещи, скажем, git-repack или что-то в этом роде)?

КогдаЯ попытался less .git/logs/refs/heads/master и взял [edit: опечатка] первый хэш из последней строки формы ...

...
[hash for HEAD~2] [hash for HEAD~1] [authorname] ...
[hash for HEAD~1] [hash for HEAD] [authorname] ...
^^^^^^^^^^^^^^^^^   (corrupted)
EOF

... и затем вставил в. git / refs /heads / master file, теперь я застрял с ...

$ git fsck
error: inflate: data stream error (unknown compression method)
error: unable to unpack header of .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
error: 8f1da374ffac3711f8cdde57379f90cb03bbb9ea: object corrupt or missing: .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
error: inflate: data stream error (unknown compression method)
error: unable to unpack header of .git/objects/ac/2fcd052804fb7adac465220da5bcb04d008fc7
error: ac2fcd052804fb7adac465220da5bcb04d008fc7: object corrupt or missing: .git/objects/ac/2fcd052804fb7adac465220da5bcb04d008fc7
Checking object directories: 100% (256/256), done.
Checking objects: 100% (1147/1147), done.
error: inflate: data stream error (unknown compression method)
error: unable to unpack 8f1da374ffac3711f8cdde57379f90cb03bbb9ea header
error: inflate: data stream error (unknown compression method)
error: unable to unpack 8f1da374ffac3711f8cdde57379f90cb03bbb9ea header
fatal: loose object 8f1da374ffac3711f8cdde57379f90cb03bbb9ea (stored in .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea) is corrupt

Я мог бы попытаться уничтожить незакрепленный объект, но я не уверен, что это, в свою очередь, указатель на(например, дерево) более поврежденных объектов, которые также должны быть уничтожены. Я, конечно, мог бы попытаться уничтожить этот объект, если бы знал комендант (или мог бы попытаться rm сохранить его в резервной копии);Должен ли я попробовать это?

Кроме того, как я могу восстановить USB-ключ и другие репо из этого беспорядка? Спасибо.

(потенциально полезные ссылки для новичков, которые вряд ли помогут людям, способным ответить на этот вопрос: https://aboullaite.me/deep-dive-into-git-git-refs/) (аналогичный вопрос роковым: ваша текущая ветка кажется сломанной - не указывает причину ошибки; эта причина может быть вызвана многими причинами)


edit:

Я сделал rm .git/objects/... для каждого объекта, указанного выше, и теперь яесть ...

$ git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (1147/1147), done.
error: refs/remotes/origin/HEAD: invalid sha1 pointer 0000000000000000000000000000000000000000
error: refs/remotes/origin/master: invalid sha1 pointer 0000000000000000000000000000000000000000
error: HEAD: invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
error: refs/heads/master: invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
error: bad ref for .git/logs/refs/remotes/origin/HEAD
error: bad ref for .git/logs/refs/remotes/origin/master
error: ac2fcd052804fb7adac465220da5bcb04d008fc7: invalid sha1 pointer in cache-tree
broken link from    tree b0d598ef5427d59ed31eb1b315c761fc89af40b7
              to    tree ac2fcd052804fb7adac465220da5bcb04d008fc7
dangling blob f4e39c36cc8df3f9f324c0ccca4ed6a7a3ffe6ac
dangling tree 068716abcf815b4eaf8f0fe74c3020bf6251bba0
dangling blob fb4cfe7c94e8b4d800fdb4935806577b2b99fd94
dangling blob 35cf2ca2ed03811c14f1598c50daacfab9032b8f
missing tree ac2fcd052804fb7adac465220da5bcb04d008fc7
dangling blob d056e38af637cf0de76dac5689a8c5e735d75793
dangling blob 3b3903cc7b4eb035e9c4508024acc3f81c015741
dangling blob b09c3cc95935a327ecf7fad8374f14c4e320f67e

Ответы [ 2 ]

2 голосов
/ 02 ноября 2019

Корень проблемы, скорее всего, заключается в том, что вы извлекли USB-ключ до или во время действия ОС по записи в USB-ключа. В результате осталось несколько поврежденных файлов.

Файлы, поврежденные из-за неправильного выключения компьютера по любой причине - одно из них - это извлечение USB-ключа, но также возможны сбои операционной системы, сбои питания, загорание компьютеров ии т. д., как правило, приводят к повреждению самых последних записанных файлов. Файлы, которые только что сидели тихо , как правило , остаются целыми. Здесь много предостережений, но этот общий принцип применим здесь.

  • Файлы, содержащие информацию о ветвях, могут быть повреждены, если вы обновляли ветки.

    Здесь,поврежденные файлы включены .git/refs/heads/master. Этот файл должен содержать 41 байт, которые состоят из 40-байтового текстового представления идентификатора хеша коммита, который должен рассматриваться как конец ветви master, за которым следует символ новой строки ASCII. Не существует определенного способа догадаться , в котором коммит является правильным tip-коммитом , поэтому Git хранит ответ на вопрос "каков хэш-идентификатор коммита tip из master* в некоторых файлах.

    некоторых случаях допустимый ответ может быть доступен в .git/packed-refs, но в целом, если существует .git/refs/heads/master, он должен содержать правильныйОтвет. Правильный ответ со временем изменяется, когда вы создаете новые коммиты, когда вы запускаете git reset, вы запускаете git branch -f и т. д.)

  • Поврежденные файлыможет включать .git/index, который содержит индекс Git или область подготовки . Оба термина означают одно и то же в Git, и есть третий, редко используемый термин, кэш для этого же файла. За исключением случаев, когда вы используете индекс для работы с конфликтующим объединением, материал в индексный файл в основном довольно легко переписать- вычислить с некоторыми усилиями: Git использует его для ускорения работы, т. е. в качестве кэша, следовательно,Третий редко используемый термин.

    Если (как в большинстве случаев) в кеше нет ничего, что не может быть пересчитано, вы можете просто удалить .git/index и затем запустить git reset дляпересчитать это. Это привело бы к тому, что все сообщения "новый файл ..." исчезли бы, и единственное, что было потеряно, это то, были ли у вас какие-то особые обновления.

    Слово в основном появляется здесь часто, потому чтоИндекс содержит хэш-идентификатор всех объектов BLOB-объектов («файлов»), которые вы намереваетесь добавить в свой следующий коммит. Если вы сделали что-то необычное, например, создали новую уникальную версию файла и поместили ее в индекс, а затем удалили ее повсюду, идентификатор хэша этой уникальной версии файла может быть непросто найти где-либо. Вы можете получить это при использовании git add -p или git reset -p для создания третьего варианта файла, который отличается как от принятой версии , так и от версии рабочего дерева. В этом случае удаление и повторное создание индекса (с помощью rm .git/index; git reset) позволит проще всего восстановить этот файл, если повторно выполнить операцию git add -p или git reset -p.

    В вашем случаеКажется возможным, что индекс был полностью удален, что привело к тому, что Git заявил, что каждый файл был новым. Это то же самое, что вы получаете, если вы запускаете rm .git/index, так что вы можете также запустить git reset. Тем не менее, здесь определенно происходит что-то еще из-за этого сообщения:

    error: ac2fcd052804fb7adac465220da5bcb04d008fc7: invalid sha1 pointer in cache-tree
    

    cache-tree здесь ссылается на содержимое индекса, используя старое имя cache . Но поскольку это «кеш», удаление и повторное создание индекса может обойти проблему, в зависимости от других факторов.

  • В поврежденные файлы могут входить некоторые файлы вашего рабочего дерева. Git не может помочь вам в этом: эти файлы управляет остальная часть вашего компьютера. Git записывает копий файлов в ваше рабочее дерево, когда вы git checkout записываете какой-то существующий коммит, чтобы они были в форме, которую вы можете видеть и с которой работать, но после этого все это ваше / ваше-компьютер для управления.

  • Возможно, поврежденные файлы содержат некоторые из внутренних объектов Git. В вашем случае это, очевидно, произошло:

    error: unable to unpack header of .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
    error: 8f1da374ffac3711f8cdde57379f90cb03bbb9ea: object corrupt or missing: .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
    

    Это означает, что объект 8f1da374ffac3711f8cdde57379f90cb03bbb9ea поврежден. Невозможно сказать, что это был за тип , тем более, какие данные были в нем и были ли они ценными, без дополнительной информации.

  • В число поврежденных файлов может входитьразличные reflogs, хранящиеся в .git/logs/. В этом случае вы получили:

    invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
    

    и:

    error: refs/heads/master: invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
    

    , используя этот же номер. Это идентификатор хэша поврежденного объекта, который мы видели всего минуту назад. Поскольку имена веток необходимы для указания на коммит объектов, теперь мы можем догадаться, что 8f1da374ffac3711f8cdde57379f90cb03bbb9ea был объектом коммита, прежде чем он был поврежден. Вероятно, это был недавно созданный коммит, например, сделанный git commit --amend.

Из всего этого мы можем сделать вывод - но это все еще предположение - что git commit --amend Сам коммит потерпел неудачу, и в качестве сломанного хеш-идентификатора в master должен был быть текст 8f1da374ffac3711f8cdde57379f90cb03bbb9ea. Вероятно, индекс был полностью поврежден или удален, но зачастую достаточно просто удалить его и перестроить его аспект кэша, чтобы вы могли удалить его снова (при необходимости), а затем пересобрать из текущего коммита, как только вы получите разумный «текущий коммит». ». Некоторые из ваших reflogs могут быть повреждены, но в любом случае все reflogs являются вспомогательными данными: в них нет ничего критичного для собственной работы Git, поэтому поврежденные могут быть усечены. Самая большая проблема - поврежденный файл .git/objects/.

Если вы хотите потерять этот коммит, может быть в порядке, просто удалив поврежденный объект и поместив действительный хэш-идентификатор в.git/refs/heads/master. Когда вы это сделали, ваш fsck все еще жаловался:

error: ac2fcd052804fb7adac465220da5bcb04d008fc7: invalid sha1 pointer in cache-tree
broken link from    tree b0d598ef5427d59ed31eb1b315c761fc89af40b7
              to    tree ac2fcd052804fb7adac465220da5bcb04d008fc7

Теперь эта первая строка по-прежнему ссылается на что-то прочитанное из .git/index. Функция удаления и сброса перестроит индекс / кэш из выбранного вами коммита, записав его хэш-идентификатор в .git/refs/heads/master. Если древовидный объект ac2fcd052804fb7adac465220da5bcb04d008fc7 не используется где-либо еще в хранилище, это может оставить вас с целым хранилищем.

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

  1. Удалить все коммиты и всех их потомков, если таковые имеются, которые ссылаются напрямуюили косвенно, к этому объекту дерева.

  2. Получить или восстановить отсутствующий объект. Если он находится в каком-то другом Git-репозитории - некотором клоне этого - это простой способ получить его. Запустите git cat-file -p ac2fcd052804fb7adac465220da5bcb04d008fc7 в хранилище, в котором оно есть. Результатом является текстовое представление дерева. Используйте git hash-object -t tree -w для создания объекта в хранилище USB-ключа, чтобы он существовал сейчас.

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

Вывод

как мне отремонтировать USB-ключ и другие репо из этого беспорядка?

ясный Можно использовать другой клон. Найдите неповрежденный клон того же хранилища. Сделайте клон этого клона, чтобы стать вашим новым результатом «отремонтированного клона». К этому новому клону добавьте новые объекты из поврежденного хранилища - новые теги, деревья, BLOB-объекты и коммиты - которые сами не повреждены. (Вы можете скопировать их напрямую, с помощью cp или использовать git cat-file -p <hash> | git hash-object -t <type> --stdin.) Таким образом, вы только читаете из поврежденный клон.

Когда выэто поврежденный объект, восстановите как можно больше полезных данных и двигайтесь дальше.

Результатом всегда будет хороший и действительный клон с максимально возможным количеством восстановленных данных и вы будете знаю точно, что вы выздоровели и что вы потеряли. Вы можете даже иметь коммиты, в которых некоторые файлы отсутствуют (потому что их внутренний объект BLOB-объекта был поврежден безвозвратно): вы можете сохранить заметку где-нибудь, возможно, используя git notes или, возможно, просто на бумаге, об этом и вернуться и восстановить то, что вы можетепозже, например.

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

0 голосов
/ 02 ноября 2019

[отвечая на собственный вопрос на данный момент, но я хотел бы принять ответ, который действительно работает]

  • компьютер 1:
    • запустить git fsck на первом репо с конфликтомон не был поврежден
    • скопировать папку репозитория в резервную копию на компьютере 1
    • зафиксировать что-либо на компьютере 1 (и / или, возможно, выполнить перезагрузку, если это только вы)
    • нажать наUSB-ключ (опция: заранее запустить git fsck на USB-ключе; я не знал, как запустить «голое» хранилище, поэтому я клонировал его во временное хранилище ...)
  • компьютер 2:
    • скопировать поврежденную папку репо на компьютере 2 в резервную копию
    • git clone с USB-ключа для восстановления репо

Это очевидноне отвечает, но пока работает («достаточно хорошо»), но правильный способ решения этой проблемы, вероятно, принесет пользу сообществу.

...