Команда git plumbing для получения удаленного субмодуля

Я работаю с git plumbing и зеркальными (и, следовательно, голыми) репозиториями в файловой системе только для чтения.

Я могу видеть существование субмодулей с git ls-tree, Я могу вывести их имя / путь и SHA1, но не могу найти способ получить удаленный субмодуль.

Информация где-то там; если я клонирую репо, git submodule init преуспевает. (Создание клона слишком дорого для обычного использования, особенно для очень больших репозиториев.) Как я могу получить доступ к удаленному субмодулю напрямую?

1 ответ

Решение

Резюме

Начать с git config --blob HEAD:.gitmodules --list и идти оттуда. Для этого нужны версии Git>= 1.8.4. Обратите внимание, что HEAD может быть любая ревизия.

Длинная форма и объяснение

Комментарии превратились в ответ, большая часть ответа предоставлена ​​ФП.:-) Кроме того, у нас есть следующие самоссылочные определения: суперпроект - это Git-репозиторий, который имеет подмодули, а подмодуль (иногда также называемый подпроектом) - это Git-репозиторий, управляемый суперпроектом. Сам подмодуль обычно сохраняется извлеченным при определенной фиксации (то есть как "отсоединенный HEAD"), хотя в настоящее время существуют особые случаи, когда вы можете указать Git переключить подмодуль на именованную ветвь. Если подмодуль имеет дополнительные подмодули, "внешний" подмодуль является суперпроектом для "внутреннего" подмодуля, поэтому super/sub все относительно.

Подмодули - URL-адреса хранилища и пути их извлечения - предоставляются файлом с именем .gitmodules в корневом каталоге суперпроекта. Следовательно, в голом хранилище вы можете получить или извлечь .gitmodules файл. Этот файл отформатирован как файл конфигурации, поэтому его можно прочитать через git config --file,

Начиная с Git версии 2.0, вы можете использовать псевдоним - сослаться на stdin, так:

git show HEAD:.gitmodules | git config --file - --list

выгрузит содержимое в привычном формате. (Если ваш вариант Git старше этого, но у вас есть /dev/stdin, ты можешь читать /dev/stdin Вот.)

Оказывается, что есть еще более простой способ: git config может, начиная с Git версии 1.8.4, читать BLOB-объекты прямо из хранилища. Идентификатор BLOB-объекта является приемлемым для git rev-parse, который может обрабатывать не только имя ветви или идентификатор фиксации, но даже последующее имя пути. (Этот код специально предназначен для обработки подмодулей: см. https://github.com/git/git/commit/1bc888193e1044db317a45b9a4c8d2b87b998f40.)

подробности

Если задан путь подмодуля P, то имя подмодуля будет зависеть от того, какая запись имеет submodule.name.path установить на P. Тогда URL для этого подмодуля submodule.name.url,

Можно найти нужное имя, используя git config --get-regexp, Однако в лучшем случае это раздражает, так как мы должны затем заключать в кавычки компоненты пути, которые являются метасимволами регулярного выражения, с очевидным общим .:

$ git config --blob HEAD:.gitmodules \
    --get-regexp 'submodule\..*\.path' 'some/dir\.name/path'
submodule.foo.path some/dir.name/path

так что, вероятно, имеет больше смысла просто сбросить конфигурацию с --list и использовать что-то еще, чтобы извлечь интересные поля. Например:

git config --blob HEAD:.gitmodules --list | \
    awk -F= -vpath='some/dir.name/path' \
    '$1 ~ /submodule\..*\.path/ && $2 == path { split($1, a, "."); print a[2] }'

(хотя к тому времени, когда вы помещаете это во что-то, что может читать деревья в поисках gitlinks, вы, вероятно, захотите Python или что-то подобное).

Начиная с git v2.x вы можете использовать следующее:

git config --file .gitmodules --get-regexp 'submodule\.\S+\.path' | 
    awk '{print $2}' |
    xargs -i git -C {} remote get-url origin

Объяснение

  • 1-я и 2-я команды возвращают относительные пути всех подмодулей
  • 3-я команда выполняет git remote внутри каталогов подмодулей и получает URL-адрес их происхождения

NB

  • удаленные имена для подмодулей должны быть "origin" (установлены git как удаленное имя по умолчанию)
  • подмодули должны быть инициализированы раньше (например, путем выполнения git submodule update --init внутри суперпроекта)
Другие вопросы по тегам