Вопрос или проблема
В: В git есть ли способ использовать подмодули “здесь”, оригинальные удаленные репозитории которых были указаны относительно внутри репозитория, в который был добавлен подмодуль, так, чтобы это было безопасно в отношении клонирования с флагом –mirror?
Такая структура с вложенными подмодулями кажется безопасной для обычного
clone --recurse-submodules …
Но вызывает проблемы с
clone --recurse-submodules --mirror …
, за которым следуют последующие клонирования для расширения зеркала.
Поскольку безголовые репозитории с флагом –mirror не содержат каталоги .git/modules, которые являются по сути локальными копиями репозитория подмодуля (для работы в отключенном режиме(?)).
Я использую git версии 2.43.0. Я немного надеюсь, что ответ на мой вопрос таков: “обновитесь до более новой версии git”. Довольно очевидно, что подмодули git развиваются к зрелости, с такими функциями, как absorbgitdirs.
—+ Дерево с вложенными подмодулями
Допустим, я хочу создать дерево с вложенными подмодулями.
И я создаю его, используя подмодули “здесь” – т.е. с относительными URL, которые находятся внутри репозитория.
Я не буду показывать детали, как можно создать такое дерево вложенных подмодулей “здесь”. Но оно может возникнуть, как описано в мануале git submodule для подкоманды absorbgitdirs:
absorbgitdirs … Репозиторий, который был клонирован независимо и
позже добавлен как подмодуль, или старые настройки имеют подмодули git
каталог внутри подмодуля, вместо того чтобы быть встроенными в каталог git суперпроекта. Из
https://git-scm.com/docs/git-submodule
Но я покажу, как может выглядеть такое дерево
$> find lib | grep -v '.git/'
lib
lib/.git
lib/.gitmodules
lib/file.txt
lib/m1
lib/m1/.git
lib/m1/.gitmodules
lib/m1/file.txt
lib/m1/m1.1
lib/m1/m1.1/.git
lib/m1/m1.1/file.txt
OK
$> find lib -name '.gitmodules' | xargs head
==> lib/.gitmodules <==
[submodule "m1"]
path = m1
url = ./m1
==> lib/m1/.gitmodules <==
[submodule "m1.1"]
path = m1.1
url = ./m1.1
OK
Обычное клонирование работает нормально:
$> git clone --recurse-submodules lib lib.non-mirror
Клонирование в 'lib.non-mirror'...
готово.
Подмодуль 'm1' (/home/glew/hack/git-stuff/nested-submodules/test.outer/test.tree/lib/m1) зарегистрирован для пути 'm1'
Клонирование в '/cygdrive/c/Users/glew/Stuff/cygwin.my-stuff/home/glew/hack/git-stuff/nested-submodules/test.outer/test.tree/lib.non-mirror/m1'...
готово.
Подмодуль 'm1': проверка '4a83ba1cdfd73494cfa35754fa65de2a10135e8f'
Подмодуль 'm1.1' (/home/glew/hack/git-stuff/nested-submodules/test.outer/test.tree/lib/m1/m1.1) зарегистрирован для пути 'm1/m1.1'
Клонирование в '/cygdrive/c/Users/glew/Stuff/cygwin.my-stuff/home/glew/hack/git-stuff/nested-submodules/test.outer/test.tree/lib.non-mirror/m1/m1.1'...
готово.
Подмодуль 'm1/m1.1': проверка '166b8056d17912ef533ff25c20fb4ec8aa1dd199'
OK
$> find lib.non-mirror | grep -v '.git/'
lib.non-mirror
lib.non-mirror/.git
lib.non-mirror/.gitmodules
lib.non-mirror/file.txt
lib.non-mirror/m1
lib.non-mirror/m1/.git
lib.non-mirror/m1/.gitmodules
lib.non-mirror/m1/file.txt
lib.non-mirror/m1/m1.1
lib.non-mirror/m1/m1.1/.git
lib.non-mirror/m1/m1.1/file.txt
OK
$> find lib.non-mirror -name '.gitmodules' | xargs head
==> lib.non-mirror/.gitmodules <==
[submodule "m1"]
path = m1
url = ./m1
==> lib.non-mirror/m1/.gitmodules <==
[submodule "m1.1"]
path = m1.1
url = ./m1.1
OK
Но clone –mirror, а затем клонирование этого как не-зеркало
НЕ УСПЕВАЕТ – потому что промежуточная стадия, зеркало, является пустым репозиторием.
Он не содержит репозиторий подмодуля.
$> git clone --recurse-submodules --mirror lib.mirror lib.mirror.gen2
Клонирование в пустой репозиторий 'lib.mirror.gen2'...
готово.
OK
$> git clone --recurse-submodules lib.mirror lib.mirror.unmirror
Клонирование в 'lib.mirror.unmirror'...
готово.
Подмодуль 'm1' (…/lib.mirror/m1) зарегистрирован для пути 'm1'
фатальная ошибка: репозиторий '…/lib.mirror/m1' не существует
Не удалось клонировать 'm1' …
НЕ УСПЕШНО=1
$> find lib.mirror.unmirror | grep -v '.git/' ; find lib.mirror.unmirror -name '.gitmodules' | xargs head
lib.mirror.unmirror
lib.mirror.unmirror/.git
lib.mirror.unmirror/.gitmodules
lib.mirror.unmirror/file.txt
lib.mirror.unmirror/m1
[submodule "m1"]
path = m1
url = ./m1
OK
Для сравнения, непустой репозиторий содержит что-то, что очень похоже на репозитории подмодулей и подподмодулей – в каталоге .git/modules. Что, на мой взгляд, очень похоже на “локальную копию” удаленных репозиториев подмодулей, так что вы можете выполнять отключенные операции.
Но каталог .git/modules отсутствует в –mirror пустом репозитории,
он присутствует только в непустом репозитории:
$ bash 1293 $> ddir lib.non-mirror/
lib.non-mirror/
| .gitmodules
| file.txt
+--m1/
| .git
| .gitmodules
| file.txt
| +--m1.1/
| .git
| file.txt
+--.git/
HEAD
config
index
+--hooks/
+--info/
+--logs/
+--objects/
+--refs/
+--modules/
+--m1/
HEAD
config
index
+--hooks/
+--info/
+--logs/
+--objects/
+--refs/
+--modules/
+--m1.1/
HEAD
config
index
+--hooks/
+--info/
+--logs/
+--objects/
+--refs/
Я думаю, это имеет смысл с одной точки зрения. Вы не можете действительно выполнять отключенную работу, используя безголый репозиторий с флагом –mirror. Вы действительно не можете редактировать файлы, фиксировать их и извлекать в безголом репозитории с флагом –mirror.
Но… если –mirror’ный репозиторий локален или доступен, когда другие части сети, такие как удаленные репозитории для подмодулей, недоступны, то определенно имеет смысл возможность клонировать безголый –mirror’ный репозиторий, получить “локальные копии” репозиториев подмодулей, чтобы затем вы могли выполнять отключенную работу.
Таким образом, всё это приводит к вопросу:
В: Есть ли способ использовать подмодули “здесь”, оригинальные удаленные репозитории которых были указаны относительно внутри репозитория, в который был добавлен подмодуль, таким образом, чтобы это было безопасно в отношении клонирования с флагом –mirror?
—+ Почему это важно для меня?
Почему я должен об этом беспокоиться?
Кажется, это артефакт, наследие, как описано в мануале git submodule для подкоманды absorbgitdirs:
absorbgitdirs – Репозиторий, который был клонирован независимо и
позже добавлен как подмодуль, или старые настройки имеют подмодули git
каталог внутри подмодуля, вместо того чтобы быть встроенными в каталог git суперпроекта. Из
https://git-scm.com/docs/git-submodule
Почему бы просто не исправить все с помощью absorbgitdirs и не завершить это?
Но… я утверждаю, что такое вложение подмодулей действительно имеет ценность.
Без этих подмодулей “здесь”, встраиваемых или вложенных в их родитель, вы должны иметь каждый подмодуль, живущий “где-то там”. Где-то вне контекста библиотеки, внутри которой он логически вложен.
Но я не буду углубляться в это в дальнейшем.
Ответ или решение
К сожалению, использование "здесь" подмодулей, где оригинальные URL-адреса удалённых репозиториев указаны относительно в рамках самого репозитория, вызывает сложности при использовании команды git clone --mirror
. Ниже предложены решения и объяснения, чтобы помочь вам справиться с данной ситуацией.
Проблема
Как уже было сказано, git clone --mirror
создает "безголовый" (bare) репозиторий, который не содержит каталогов .git/modules
. Это приводит к тому, что при дальнейших клонированиях возникает ошибка из-за отсутствия подмодулей, поскольку команда clone --recurse-submodules
не может найти эти подмодули по относительным URL-адресам.
Решения
-
Использование
clone --recurse-submodules
вместоclone --mirror
:
Для того, чтобы избежать проблем с подмодулями, вы можете использовать обычный клон с поддержкой подмодулей:git clone --recurse-submodules <урл> <папка>
Это будет работать корректно, так как все вложенные подмодули будут клонированы правильно.
-
Преобразование подмодуля перед клонированием:
Если вам необходимо использоватьclone --mirror
, вы можете пересоздать конфигурацию подмодулей. Например, вы можете сделать следующие шаги:- Клонировать обычным способом (без
--mirror
):git clone --recurse-submodules <урл> <папка>
- Изменить подмодули на абсолютные URL-адреса:
Для этого вам нужно вручную отредактировать файл.gitmodules
и заменить относительные URL-адреса на абсолютные. После этого обновите конфигурацию подмодулей:git submodule sync git submodule update --init --recursive
- Теперь вы можете создать
--mirror
репозиторий.
- Клонировать обычным способом (без
-
Использование
absorbgitdirs
:
Если вы хотите сохранить структуру вложенных подмодулей, вы можете использовать командуabsorbgitdirs
для преобразования структуры подмодулей. Это поможет интегрировать подмодули в суперпроект, и, таким образом, ваши команды будут работать корректно после выполненияclone --mirror
.Пример:
git submodule absorbgitdirs
-
Обновление Git:
Если вы используете старую версию Git (например, 2.43.0), рассмотрите возможность обновления до более новой версии, так как в последних версиях были введены улучшения, касающиеся работы с подмодулями и их относительными URL-адресами.
Заключение
Кратко подытожим: проблемы с "здесь" подмодулями при использовании clone --mirror
связаны с отсутствием информации о вложенных подмодулях в безголовом репозитории. Для решения данной проблемы вы можете:
- Использовать обычный клон с подмодулями (без
--mirror
). - Изменить относительные URL на абсолютные.
- Применить команду
absorbgitdirs
. - Обновить Git до последней версии для доступа к новым функциям.
Надеюсь, эти советы помогут вам справиться с вашими проблемами с подмодулями!