git clone –mirror и не включенные подмодули “здесь”

Вопрос или проблема

В: В 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-адресам.

Решения

  1. Использование clone --recurse-submodules вместо clone --mirror:
    Для того, чтобы избежать проблем с подмодулями, вы можете использовать обычный клон с поддержкой подмодулей:

    git clone --recurse-submodules <урл> <папка>

    Это будет работать корректно, так как все вложенные подмодули будут клонированы правильно.

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

    • Клонировать обычным способом (без --mirror):
      git clone --recurse-submodules <урл> <папка>
    • Изменить подмодули на абсолютные URL-адреса:
      Для этого вам нужно вручную отредактировать файл .gitmodules и заменить относительные URL-адреса на абсолютные. После этого обновите конфигурацию подмодулей:

      git submodule sync
      git submodule update --init --recursive
    • Теперь вы можете создать --mirror репозиторий.
  3. Использование absorbgitdirs:
    Если вы хотите сохранить структуру вложенных подмодулей, вы можете использовать команду absorbgitdirs для преобразования структуры подмодулей. Это поможет интегрировать подмодули в суперпроект, и, таким образом, ваши команды будут работать корректно после выполнения clone --mirror.

    Пример:

    git submodule absorbgitdirs
  4. Обновление Git:
    Если вы используете старую версию Git (например, 2.43.0), рассмотрите возможность обновления до более новой версии, так как в последних версиях были введены улучшения, касающиеся работы с подмодулями и их относительными URL-адресами.

Заключение

Кратко подытожим: проблемы с "здесь" подмодулями при использовании clone --mirror связаны с отсутствием информации о вложенных подмодулях в безголовом репозитории. Для решения данной проблемы вы можете:

  • Использовать обычный клон с подмодулями (без --mirror).
  • Изменить относительные URL на абсолютные.
  • Применить команду absorbgitdirs.
  • Обновить Git до последней версии для доступа к новым функциям.

Надеюсь, эти советы помогут вам справиться с вашими проблемами с подмодулями!

Оцените материал
Добавить комментарий

Капча загружается...