web-dev-qa-db-fra.com

Lister les sous-modules dans un dépôt Git

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?

171
tpg2114

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.

113
Ikke

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.

66
Jon Koops

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.

57
mholm815

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.

41
A.T.

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é

17
Sandeep Gill

J'utilise ceci: 

git config --list|egrep ^submodule
15
Robert Sjödahl

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
15
Max Cantor

Vous pouvez utiliser:

git submodule | awk '{ print $2 }'
8
fabceolin

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'
8
benesch

J'utilise celui-ci:

git submodule status | cut -d' ' -f3-4 

Sortie (chemin + version):

tools/deploy_utils (0.2.4)
7
Skarab

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

6
LTK

git config permet de spécifier un fichier de configuration.
Et .gitmodulesest 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 comprend read -d '' (n'oubliez pas l'espace entre -d and '').

4
VonC

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

????????

4
Alex Gray

Pour lister tous les sous-modules par nom:

git submodule --quiet foreach --recursive 'echo $name'

3
bGorle

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.

Obtenir une liste du sous-module 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.

Obtenir une liste du sous-module 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.


Notes de bas de page

[1] git version

$ git --version
git version 2.22.0

[2] Sous-module avec name et path divergents

Configurer 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

Essai

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 = ./

Obtenir la liste du sous-module 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

Obtenir la liste du sous-module 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
1
Ente

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 {} \;
0
MrSwed

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-)
0
devC0de