Так как мне это исправить?
Вручную удалите все файлы подмодулей из вашего рабочего дерева: например, rm -rf submodule
.
Почему git не удалил папку, когда я вернулся к коммиту, где он никогда не существовал.
Подмодули грязные.
Помните, подмодуль, в Git, действительно просто еще один Git репозиторий. Этот другой Git репозиторий полностью и полностью независим от вашего основного (суперпроектного) репозитория. Или, скорее, было бы - у вас просто было бы два отдельных клона, расположенных бок о бок, без какого-либо взаимодействия между ними - за исключением того факта, что вы вставили клон подмодуля в дерево работы для суперпроект . И в процессе:
В современном Git сам репозиторий «поглощается» в каталог репозитория суперпроекта (так что нет папки .git
sub- , но вместо этого .git
файл в копии рабочего дерева извлеченного коммита из подмодуля.
Суперпроект Git записывает материал о подмодуле в конфигурации суперпроекта (не только в файле .gitmodule
) и в некоторых коммитах. В частности, в коммитах, где предполагается, что субмодуль извлекается с определенным идентификатором ha sh, сам идентификатор ha sh сохраняется как запись gitlink в каждом коммите.
Суперпроект Git сохраняет cd
-подключение в подмодуле и выполняет git checkout <hash-id>
, который отсоединяет HEAD в подмодуле. (Точно , когда это делает, это другая проблема; это зависит от того, включена ли рекурсия субмодуля.)
В общем, тот факт, что подмодуль является ( в основном) независимое хранилище запрещает суперпроекту Git полностью удалить его. В этом конкретном случае он, вероятно, должен просто go вперед и удалить его как часть "обновления подмодуля до правильного коммита", потому что "правильный" коммит в рассматриваемом подмодуле равен "нет коммита" вообще - убрать субмодуль из рабочего дерева ". В старые времена, до того как Git впитал каталог .git
в суперпроект, это буквально уничтожило бы хранилище субмодулей, что было бы плохо. 1 В современном Git это не будет ( как только каталог подмодуля .git
поглощен как минимум), так что его можно заставить работать.
1 Во многих ситуациях это будет безвредно, но для необходимости повторно клон. Но предположим, что вы сделали коммит суперпроекта, (1) сделав коммит субмодуля для новой ветки, которую вы сделали в субмодуле; (2) выход из подмодуля обратно в суперпроект и обновление записи индекса gitlink для записи нового идентификатора ha sh в подмодуле; (3) сделать новый коммит. Теперь у вас есть подмодульный коммит, который никуда не выдвигается, но может и должен быть передан до того, как будет передан коммит суперпроекта.
Теперь, когда все это настроено, вы решаете взглянуть на историю c коммит. Вы git checkout <hash>
в суперпроекте, и у этой историей c commit нет извлеченного субмодуля. Вы установили submodule.recurse
на true
или использовали git checkout --recurse-submodules
, чтобы суперпроект приводил субмодуль к правильному (отсутствующему) коммиту, а удалял субмодуль .
. каталог .git
буквально живет в подмодуле - внутри рабочего дерева подмодуля - это полностью, безвозвратно уничтожает коммит, который вы сделали в подмодуле, в ветке, которую вы там сделали, которую вы еще не выдвинули , Так что не должно быть .
Теперь, когда сама директория .git
живет где-то еще, удаление субмодуля из рабочего дерева суперпроекта не вредит субмодулю хранилище . Так что теперь этот вид удаления будет безопасным. Восстановление суперпроекта до последнего коммита может просто восстановить рабочее дерево подмодуля, проверяя коммит, который защищен G C веткой репозитория подмодуля (еще не выдвинут).