Список подмодулей в репозитории Git
У меня есть Git-репозиторий, в котором есть несколько подмодулей. Как мне перечислить имена всех подмодулей после git submodule init
?
Команда git submodule foreach
может отображать имена подмодулей, но это работает только после того, как они извлечены, чего не произошло после шага инициализации. Есть еще несколько шагов в цепочке, которые необходимо выполнить, прежде чем их можно будет извлечь, и я не хочу привязывать имена субмодулей к сценарию.
Так есть ли команда Git, чтобы получить имена всех зарегистрированных в настоящее время, но еще не проверенных подмодулей?
Ответы
Ответ 1
Вы можете использовать тот же механизм, что и в git submodule init
, а именно, посмотреть на .gitmodules
. Эти файлы перечисляют каждый путь субмодуля и URL-адрес, на который он ссылается.
Например, из корневого хранилища cat.gitmodules
напечатает содержимое на экране (при условии, что у вас есть cat
).
Поскольку файлы .gitmodule имеют формат конфигурации Git, вы можете использовать git config для разбора этих файлов:
git config --file .gitmodules --name-only --get-regexp path
Покажет вам все записи субмодуля, и с
git config --file .gitmodules --get-regexp path | awk '{ print $2 }'
вы получите только сам путь субмодуля.
Ответ 2
Вы можете использовать git submodule status
или необязательно git submodule status --recursive
, если хотите показать вложенные подмодули.
В GIT документах SCM:
Показывать статус подмодулей. Это напечатает SHA-1 в настоящее время проверяется фиксация для каждого подмодуля, а также путь субмодуля и вывод GIT описывают SHA-1. каждый SHA-1 будет иметь префикс - если подмодуль не инициализирован, + если зафиксированный в настоящий момент подмодуль не соответствует SHA-1 найденный в индексе содержащего репозитория и U, если подмодуль имеет конфликты слияния.
Ответ 3
Чтобы вернуть только имена зарегистрированных подмодулей, вы можете использовать эту команду:
grep path .gitmodules | sed 's/.*= //'
Думайте об этом как о git submodule --list
который не существует.
Ответ 4
Следующая команда перечисляет подмодули:
git submodule--helper list
Результат выглядит примерно так:
<mode> <sha1> <stage> <location>
Примечание. Требуется git 2.7.0 или выше.
Ответ 5
Я вижу, что ответ был выбран, но для всех, кто достигает этой страницы:
$ git submodule
отобразит все подмодули в указанном репо git.
Приветствия
Ответ 6
Я использую это:
git config --list|egrep ^submodule
Ответ 7
Я заметил, что команда, предоставленная в ответе на этот вопрос, дала мне информацию, которую я искал:
Нет подмодульного отображения, найденного в .gitmodule для пути, который не является подмодулем
git ls-files --stage | grep 160000
Ответ 8
Вы можете использовать:
git submodule | awk '{ print $2 }'
Ответ 9
Если вы не против работы только с инициализированными подмодулями, вы можете использовать git submodule foreach
, чтобы избежать разбора текста.
git submodule foreach --quiet 'echo $name'
Ответ 10
Я использую этот:
git submodule status | cut -d' ' -f3-4
Выход (путь + версия):
tools/deploy_utils (0.2.4)
Ответ 11
Это сработало для меня:
git ls-files --stage | grep ^160000
На основании этой замечательной статьи: http://www.speirs.org/blog/2009/5/11/understanding-git-submodules.html
Редактировать: он должен читать grep ^160000
Ответ 12
Чтобы вывести список всех подмодулей по имени:
git submodule --quiet foreach --recursive 'echo $name'
Ответ 13
Просто пути подмодулей, пожалуйста, ma'am...
git config --list | grep \^submodule | cut -f 2 -d .
Vendor/BaseModel
Vendor/ObjectMatcher
Vendor/OrderedDictionary
Vendor/_ObjC
Vendor/XCodeHelpers
👍🏼
Ответ 14
git config
позволяет указать файл конфигурации.
И .gitmodules
- это файл конфигурации.
Итак, с помощью " использовать пробел в качестве разделителя с командой cut ":
git config --file=.gitmodules --get-regexp ^^submodule.*\.path$ | cut -d " " -f 2
Это будет перечислять только пути, по одному на объявленный подмодуль.
Как отмечает Тино в комментариях:
- Это не работает для подмодулей с пробелами в нем.
-
пути субмодулей могут содержать новые строки, как в
git submodule add https://github.com/hilbix/bashy.git "sub module"
git mv 'sub module' $'sub\nmodule'
В качестве более надежной альтернативы Тино предлагает:
git config -z --file .gitmodules --get-regexp '\.path$' | \
sed -nz 's/^[^\n]*\n//p' | \
tr '\0' '\n'
Для путей с символами новой строки в них (их можно создать с помощью git mv
), не указывайте | tr '\0' '\n'
| tr '\0' '\n'
и использовать что-то вроде ... | while IFS='' read -d '' path; do...
... | while IFS='' read -d '' path; do...
... | while IFS='' read -d '' path; do...
для дальнейшей обработки с помощью bash.
Для этого нужен современный bash, который понимает read -d ''
(не забывайте пробел между -d and ''
).
Ответ 15
В моей версии git
[1] каждый подмодуль git имеет name
и path
. Они не обязательно должны быть одинаковыми [2]. Получение обоих надежным способом без предварительной проверки субмодулей (git update --init
) - сложная git update --init
оболочки.
Получить список names
субмодулей
Я не нашел способа добиться этого, используя git config
или любую другую команду git
. Поэтому мы вернулись к регулярному выражению на .gitmodules
(супер уродливо). Но это кажется несколько безопасным, поскольку git
ограничивает возможное пространство кода, разрешенное для names
подмодулей. Кроме того, так как вы, вероятно, хотите использовать этот список для дальнейшей обработки оболочки, решение ниже разделяет записи с NULL
-bytes (\0
).
$ sed -nre \
's/^\[submodule \"(.*)\"]$/\1\x0/p' \
"$(git rev-parse --show-toplevel)/.gitmodules" \
| tr -d '\n' \
| xargs -0 -n1 printf "%b\0"
И в вашем сценарии:
#!/usr/bin/env bash
while IFS= read -rd '' submodule_name; do
echo submodule name: "${submodule_name}"
done < <(
sed -nre \
's/^\[submodule \"(.*)\"]$/\1\x0/p' \
"$(git rev-parse --show-toplevel)/.gitmodules" \
| tr -d '\n' \
| xargs -0 -n1 printf "%b\0"
)
Примечание: read -rd ''
требует bash
и не будет работать с sh
Получить список paths
субмодулям
В моем подходе я стараюсь не обрабатывать вывод из git config --get-regexp
с помощью awk
, tr
, sed
,... но вместо этого git config --get
нулевой байт, разделенный обратно, в git config --get
. Это сделано для того, чтобы избежать проблем с символами новой строки, пробелами и другими специальными символами (например, юникодом) в paths
подмодулей. Кроме того, так как вы, вероятно, хотите использовать этот список для дальнейшей обработки оболочки, решение ниже разделяет записи с NULL
-bytes (\0
).
$ git config --null --file .gitmodules --name-only --get-regexp '\.path$' \
| xargs -0 -n1 git config --null --file .gitmodules --get
например, в bash
скрипте вы можете:
#!/usr/bin/env bash
while IFS= read -rd '' submodule_path; do
echo submodule path: "${submodule_path}"
done < <(
git config --null --file .gitmodules --name-only --get-regexp '\.path$' \
| xargs -0 -n1 git config --null --file .gitmodules --get
)
Примечание: read -rd ''
требует bash
и не будет работать с sh
Сноски
[1] версия git
$ git --version
git version 2.22.0
[2] Подмодуль с разными name
и path
Настроить тестовый репозиторий:
$ git init test-name-path
$ cd test-name-path/
$ git checkout -b master
$ git commit --allow-empty -m 'test'
$ git submodule add ./ submodule-name
Cloning into '/tmp/test-name-path/submodule-name'...
done.
$ ls
submodule-name
$ cat .gitmodules
[submodule "submodule-name"]
path = submodule-name
url = ./
Переместите подмодуль, чтобы name
и path
расходились:
$ git mv submodule-name/ submodule-path
$ ls
submodule-path
$ cat .gitmodules
[submodule "submodule-name"]
path = submodule-path
url = ./
$ git config --file .gitmodules --get-regexp '\.path$'
submodule.submodule-name.path submodule-path
тестирование
Настроить тестовый репозиторий:
$ git init test
$ cd test/
$ git checkout -b master
$ git commit --allow-empty -m 'test'
$
$ git submodule add ./ simplename
Cloning into '/tmp/test/simplename'...
done.
$
$ git submodule add ./ 'name with spaces'
Cloning into '/tmp/test/name with spaces'...
done.
$
$ git submodule add ./ 'future-name-with-newlines'
Cloning into '/tmp/test/future-name-with-newlines'...
done.
$ git mv future-name-with-newlines/ 'name
> with
> newlines'
$
$ git submodule add ./ 'name-with-unicode-💩'
Cloning into '/tmp/test/name-with-unicode-💩'...
done.
$
$ git submodule add ./ sub/folder/submodule
Cloning into '/tmp/test/sub/folder/submodule'...
done.
$
$ git submodule add ./ name.with.dots
Cloning into '/tmp/test/name.with.dots'...
done.
$
$ git submodule add ./ 'name"with"double"quotes'
Cloning into '/tmp/test/name"with"double"quotes'...
done.
$
$ git submodule add ./ "name'with'single'quotes"
Cloning into '/tmp/test/name'with'single'quotes''...
done.
$ git submodule add ./ 'name]with[brackets'
Cloning into '/tmp/test/name]with[brackets'...
done.
$ git submodule add ./ 'name-with-.path'
Cloning into '/tmp/test/name-with-.path'...
done.
.gitmodules
:
[submodule "simplename"]
path = simplename
url = ./
[submodule "name with spaces"]
path = name with spaces
url = ./
[submodule "future-name-with-newlines"]
path = name\nwith\nnewlines
url = ./
[submodule "name-with-unicode-💩"]
path = name-with-unicode-💩
url = ./
[submodule "sub/folder/submodule"]
path = sub/folder/submodule
url = ./
[submodule "name.with.dots"]
path = name.with.dots
url = ./
[submodule "name\"with\"double\"quotes"]
path = name\"with\"double\"quotes
url = ./
[submodule "name'with'single'quotes"]
path = name'with'single'quotes
url = ./
[submodule "name]with[brackets"]
path = name]with[brackets
url = ./
[submodule "name-with-.path"]
path = name-with-.path
url = ./
Получить список names
субмодулей
$ sed -nre \
's/^\[submodule \"(.*)\"]$/\1\x0/p' \
"$(git rev-parse --show-toplevel)/.gitmodules" \
| tr -d '\n' \
| xargs -0 -n1 printf "%b\0" \
| xargs -0 -n1 echo submodule name:
submodule name: simplename
submodule name: name with spaces
submodule name: future-name-with-newlines
submodule name: name-with-unicode-💩
submodule name: sub/folder/submodule
submodule name: name.with.dots
submodule name: name"with"double"quotes
submodule name: name'with'single'quotes
submodule name: name]with[brackets
submodule name: name-with-.path
Получить список paths
субмодулей
$ git config --null --file .gitmodules --name-only --get-regexp '\.path$' \
| xargs -0 -n1 git config --null --file .gitmodules --get \
| xargs -0 -n1 echo submodule path:
submodule path: simplename
submodule path: name with spaces
submodule path: name
with
newlines
submodule path: name-with-unicode-💩
submodule path: sub/folder/submodule
submodule path: name.with.dots
submodule path: name"with"double"quotes
submodule path: name'with'single'quotes
submodule path: name]with[brackets
submodule path: name-with-.path
Ответ 16
Если нет .gitmodules, но конфигурация подмодулей существует в .git/modules/
find .git/modules/ -name config -exec grep url {} \;
Ответ 17
Вот еще один способ разобрать имена подмодулей git из .gitmodules без необходимости использования sed или нестандартных настроек IFS. :-)
#!/bin/env bash
function stripStartAndEndQuotes {
temp="${1%\"}"
temp="${temp#\"}"
echo "$temp"
}
function getSubmoduleNames {
line=$1
len=${#line} # get line length
stripStartAndEndQuotes "${line::len-1}" # remove last character
}
while read line; do
getSubmoduleNames "$line"
done < <(cat .gitmodules | grep "\[submodule.*\]" | cut -d ' ' -f 2-)