J'ai un référentiel Git qui contient plusieurs sous-modules. Comment lister les noms de tous les sous-modules après l'exécution de git submodule init
?
La commande git submodule foreach
peut faire écho aux noms du sous-module, mais cela ne fonctionne qu'une fois qu'ils ont été extraits, ce qui n'est pas arrivé après l'étape d'initialisation. Il y a d'autres étapes dans la chaîne qui doivent être franchies avant de pouvoir les extraire, et je ne veux pas avoir à fileter les noms des sous-modules dans le script.
Donc, y a-t-il une commande Git pour obtenir les noms de tous les sous-modules actuellement enregistrés, mais pas encore extraits?
Vous pouvez utiliser le même mécanisme que celui utilisé par git submodule init
, à savoir, regardez .gitmodules
. Ces fichiers énumèrent chaque chemin de sous-module et l'URL à laquelle il fait référence.
Par exemple, depuis la racine du référentiel, cat .gitmodules
imprimera le contenu à l'écran (en supposant que vous avez cat
).
Les fichiers .gitmodule ayant le format de configuration Git, vous pouvez utiliser git config pour les analyser:
git config --file .gitmodules --name-only --get-regexp path
Vous montrerait toutes les entrées de sous-module, et avec
git config --file .gitmodules --get-regexp path | awk '{ print $2 }'
vous n'obtiendrez que le chemin du sous-module lui-même.
Vous pouvez utiliser git submodule status
ou éventuellement git submodule status --recursive
si vous souhaitez afficher des sous-modules imbriqués.
À partir de la documentation GIT SCM:
Affiche le statut des sous-modules. Cela imprimera le SHA-1 du actuellement extrait commet pour chaque sous-module, avec le Le chemin du sous-module et la sortie de git décrivent le SHA-1. Chaque SHA-1 sera préfixé par - si le sous-module n'est pas initialisé, + si la validation du sous-module actuellement extrait ne correspond pas à SHA-1 trouvé dans l'index du référentiel contenant et U si le sous-module a des conflits de fusion.
Pour ne renvoyer que les noms des sous-modules enregistrés, vous pouvez utiliser cette commande:
grep path .gitmodules | sed 's/.*= //'
Pensez-y comme git submodule --list
qui n'existe pas.
La commande suivante listera les sous-modules:
git submodule--helper list
La sortie ressemble à ceci:
<mode> <sha1> <stage> <location>
Note: Nécessite Git 2.7.0 ou supérieur.
Je peux voir que la réponse a été sélectionnée, mais pour quiconque accède à cette page:
$ git submodule
listera tous les sous-modules du repo git spécifié.
À votre santé
J'utilise ceci:
git config --list|egrep ^submodule
J'ai remarqué que la commande fournie dans une réponse à cette question m'apportait l'info que je cherchais:
Aucun mappage de sous-module trouvé dans .gitmodule pour un chemin qui n'est pas un sous-module
git ls-files --stage | grep 160000
Vous pouvez utiliser:
git submodule | awk '{ print $2 }'
Si cela ne vous dérange pas d’opérer uniquement sur des sous-modules initialisés, vous pouvez utiliser git submodule foreach
pour éviter l’analyse de texte.
git submodule foreach --quiet 'echo $name'
J'utilise celui-ci:
git submodule status | cut -d' ' -f3-4
Sortie (chemin + version):
tools/deploy_utils (0.2.4)
Cela a fonctionné pour moi:
git ls-files --stage | grep ^160000
Basé sur cet article: http://www.speirs.org/blog/2009/5/11/understanding-git-submodules.html
Edit: il faut lire grep ^160000
git config
permet de spécifier un fichier de configuration.
Et .gitmodules
est un fichier de configuration.
Ainsi, avec l’aide de " utilisez l’espace comme délimiteur avec la commande de coupe ":
git config --file=.gitmodules --get-regexp ^^submodule.*\.path$ | cut -d " " -f 2
Cela ne listera que les chemins, un par sous-module déclaré.
Comme Tino souligne dans les commentaires :
- Cela échoue pour les sous-modules contenant spaces.
les chemins de sous-modules peuvent contenir newlines, comme dans
git submodule add https://github.com/hilbix/bashy.git "sub module" git mv 'sub module' $'sub\nmodule'
Comme alternative plus robuste, Tino propose:
git config -z --file .gitmodules --get-regexp '\.path$' | \ sed -nz 's/^[^\n]*\n//p' | \ tr '\0' '\n'
Pour les chemins contenant des nouvelles lignes (ils peuvent être créés avec
git mv
), laissez le| tr '\0' '\n'
et utilisez quelque chose comme... | while IFS='' read -d '' path; do ...
pour un traitement ultérieur avec bash.
Cela nécessite une bash moderne qui comprendread -d ''
(n'oubliez pas l'espace entre-d and ''
).
Juste les chemins de sous-modules s'il vous plaît, madame ...
git config --list | grep \^submodule | cut -f 2 -d .
Vendor/BaseModel Vendor/ObjectMatcher Vendor/OrderedDictionary Vendor/_ObjC Vendor/XCodeHelpers
????????
Pour lister tous les sous-modules par nom:
git submodule --quiet foreach --recursive 'echo $name'
Dans ma version de git
[1], chaque sous-module git a une name
et une path
. Ils ne doivent pas nécessairement être les mêmes [2]. Obtenir les deux de manière fiable, sans vérifier les sous-modules au préalable (git update --init
), est un peu délicat de la magie de Shell.
names
Je n'ai pas trouvé comment y parvenir en utilisant git config
ou toute autre commande git
. Nous sommes donc revenus à l'expression régulière sur .gitmodules
(super laid). Mais cela semble quelque peu sûr car git
limite l'espace de code possible autorisé pour le sous-module names
. De plus, puisque vous souhaitez probablement utiliser cette liste pour un traitement ultérieur du shell, la solution ci-dessous sépare les entrées avec NULL
- octets (\0
).
$ sed -nre \
's/^\[submodule \"(.*)\"]$/\1\x0/p' \
"$(git rev-parse --show-toplevel)/.gitmodules" \
| tr -d '\n' \
| xargs -0 -n1 printf "%b\0"
Et dans votre script:
#!/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"
)
Remarque : read -rd ''
nécessite bash
et ne fonctionnera pas avec sh
.
paths
Dans mon approche, j'essaie pas de traiter la sortie de git config --get-regexp
avec awk
, tr
, sed
, ... mais la passe à zéro octet séparé en retour vers git config --get
. Cela permet d'éviter les problèmes de nouvelles lignes, d'espaces et d'autres caractères spéciaux (par exemple, unicode) dans le sous-module paths
. De plus, puisque vous souhaitez probablement utiliser cette liste pour un traitement ultérieur du shell, la solution ci-dessous sépare les entrées avec NULL
- octets (\0
).
$ git config --null --file .gitmodules --name-only --get-regexp '\.path$' \
| xargs -0 -n1 git config --null --file .gitmodules --get
par exemple, dans un script bash
, vous pouvez alors:
#!/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
)
Remarque : read -rd ''
nécessite bash
et ne fonctionnera pas avec sh
.
git
version$ git --version
git version 2.22.0
name
et path
divergentsConfigurer le référentiel de test:
$ 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 = ./
Déplacez le sous-module pour que name
et path
divergent:
$ 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
Configurer le référentiel de test:
$ 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
S'il n'y a pas de .gitmodules, mais que la configuration de sous-modules existe dans .git/modules /
find .git/modules/ -name config -exec grep url {} \;
Voici un autre moyen d’analyser les noms de sous-modules git à partir de .gitmodules sans avoir recours à des paramètres IFS sed ou sophistiqués. :-)
#!/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-)