Как исправить ошибку git fsk из-за старого недопустимого файла gitmodules? - PullRequest
0 голосов
/ 26 апреля 2019

На нашем централизованном git-сервере мы автоматически запускаем периодический git fsck.В одном из наших репозиториев происходит сбой со следующей ошибкой:

$ git fsck
Checking object directories: 100% (256/256), done.
error: bad config line 43 in blob .gitmodules
error in blob 31e0c6cb966c309c4e6018fe280bbb9c40ca2902: gitmodulesParse: could not parse gitmodules blob

Я отследил коммит, содержащий этот BLOB-объект:

obj_name=31e0c6cb966c309c4e6018fe280bbb9c40ca2902 ; git log --all "$@" --pretty=format:'%T %h %s' | while read tree commit subject ; do     if git ls-tree -r $tree | grep -q "$obj_name" ; then         echo $commit "$subject";     fi; done
5adc29a fix develop

И затем я выследил ветви и тегикоторые содержат этот коммит.

Я вижу недействительные gitmodules, и он действительно недействителен из-за плохого слияния.Я вижу, что в ветке есть еще один коммит, который исправляет неправильное слияние.Я также вижу, что на коммит с недопустимым файлом gitmodules ссылаются два тега.

Я попытался удалить теги и снова запустить fsck, но это не помогло.

Я хотел бы, чтобы наш автоматическийgit fsck, чтобы прекратить оповещение, и, кажется, лучший способ - исправить gitmodule в этом конкретном коммите.Мне нужно только исправить это на сервере, мне все равно, если клонам или вилкам не хватает исправления, поскольку ошибка произошла более года назад.

Могу ли я сделать это безопасно и как?

1 Ответ

1 голос
/ 26 апреля 2019

Короткий ответ - нет: ничто в коммите не может быть изменено. Есть одна вещь, которую вы можете сделать, но она немного жестока.

Что вы можете сделать

Лучшее, что вы можете сделать (помимо игнорирования жалобы), - это создать новый и улучшенный коммит: тот, который точно похож на оригинал, за исключением ошибки. Но это новый коммит с новым и другим хеш-идентификатором, а не коммит 5adc29a. Так что теперь вам нужно найти все коммиты, у которых 5adc29a есть их родитель (ы), и сделать копии тех коммитов , которые имеют новый коммит в качестве нового и улучшенного родителя (и любых оригинальных коммитов). кроме 5adc29a в качестве другого родителя (ей)).

Изменив и 5adc29a и его ближайших детей, теперь вы должны найти детей от детей 5adc29a. Им тоже нужно найти новых и улучшенных родителей. Тогда вам нужно найти их детей и так далее. Это изменение, по сути, распространяется по всей истории, вплоть до всех кончиков ветвей, которые происходят от плохого - теперь замененного - коммита. Затем каждая ветка - name указывает на обновленную ветку - tip .

Существует команда Git, которая делает все это: git filter-branch. По сути, то, что git filter-branch делает - или может делать - это циклически повторять каждый коммит в репозитории, применяя некоторые фильтры, а затем фиксируя результат. Если результат по битам идентичен оригиналу, результат равен оригиналу и ничего не меняется. Если же результат будет другим, то этот коммит теперь будет иметь новые и улучшенные заменители и , и каждый последующий дочерний коммит будет переименован соответствующим образом. Это, конечно, меняет дочерний элемент, так что копия дочернего элемента также является новым коммитом, пронизывающим всю остальную историю, вплоть до всех подсказок ветвей, которые произошли от оригинала - теперь заменены - коммит.

Следовательно, «все», что вам нужно сделать, - это запустить команду git filter-branch, которая заменяет неверный коммит новым и улучшенным. Запустите это для каждого коммита, ветки и имени тега в вашем репозитории, и это:

root--c1--c2--...--bad--c1001--c1002--c1003   <-- master
                             \
                              c1004--c1005   <-- develop

становится:

                    bad--c1001--c1002--c1003   [original master]
                   /   \
                  /     c1004--c1005   [original develop]
                 /
root--c1--c2--...--fixed--c1006--c1007--c1008   <-- master
                               \
                                c1009--c1010   <-- develop

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

Сборка заменителя

Вы можете сделать это с помощью фильтра ответвления фильтра. Это самый прямой путь, но также трудно понять, как правильно. Гораздо проще использовать git replace.

То, что делает git replace, - это коммиты на замену. Такие замены на самом деле не являются заменами , они просто дополнительные коммиты, которые вы говорите своему Git использовать вместо оригиналов (и они не помогут с эта жалоба git fsck, так как оригиналы все еще там). По сути, если фиксация 5adc29a плохая, вы можете сделать улучшенную фиксацию с тем же parent (s), что и 5adc29a, но с хорошим содержанием. Затем вы говорите своему Git: Когда бы вы ни посмотрели на 5adc29a, вместо этого посмотрите на этот другой коммит.

Несколько команд Git, включая git gc и git fsck, намеренно не не подчиняются заменам. Всем командам Git можно сказать не подчиняться, чтобы увидеть, что там на самом деле. Но большинство, включая git filter-branch, по умолчанию подчиняются заменам.

Что тон имеет в виду, что вы можете создать замену, убедиться, что все выглядит хорошо, а затем просто запустить git filter-branch с --all (и соответствующим --tag-name-filter, если необходимо), но без других фильтров, которые, по сути, цементируют замену вместо.Затем вы удаляете все имена refs/original/, которые git filter-branch использует в качестве ремней безопасности и подушек безопасности в случае, если фильтрация не работает, и теперь у вас есть хранилище, в котором плохие объекты больше не появляются (и git gc будетв конце концов удалите их по-настоящему).

Этот репозиторий больше не совместим с плохим, или, скорее, он полностью совместим с слишком , и его соответствие плохому вызовет неудачный коммитчтобы вернуться, вместе со всеми дочерними элементами, которые вы заменили с шагом ответвления фильтра.Вам решать, стоит ли боль такого флага дня выгоды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...