it-swarm.com.de

Listen Sie Submodule in einem Git-Repository auf

Ich habe ein Git-Repository, das mehrere Submodule enthält. Wie liste ich die Namen aller Submodule auf, nachdem git submodule init ausgeführt wurde?

Der Befehl git submodule foreach könnte die Namen des Submoduls wiedergeben, dies funktioniert jedoch nur, wenn sie ausgecheckt wurden. Dies ist nach dem Init-Schritt nicht der Fall. Es gibt weitere Schritte in der Kette, die ausgeführt werden müssen, bevor sie ausgecheckt werden können, und ich möchte nicht, dass die Namen der Submodule fest mit dem Skript verbunden werden müssen. 

Gibt es also einen Git-Befehl, um die Namen aller aktuell registrierten, aber noch nicht ausgecheckten Submodule abzurufen?

171
tpg2114

Sie könnten den gleichen Mechanismus verwenden wie git submodule init selbst, nämlich .gitmodules. Diese Dateien listet jeden Submodulpfad und die URL auf, auf die er verweist.

Zum Beispiel wird cat .gitmodules vom Stamm des Repository auf den Bildschirm gedruckt (vorausgesetzt, Sie haben cat).

Da .gitmodule-Dateien das Git-Konfigurationsformat haben, können Sie git config zum Analysieren dieser Dateien verwenden:

git config --file .gitmodules --name-only --get-regexp path

Zeigt dir alle Submodul-Einträge an und mit

git config --file .gitmodules --get-regexp path | awk '{ print $2 }'

sie würden nur den Submodulpfad selbst erhalten.

113
Ikke

Sie können git submodule status oder optional git submodule status --recursive verwenden, wenn Sie verschachtelte Submodule anzeigen möchten.

Aus den GIT SCM-Dokumenten:

Zeigt den Status der Submodule an. Dadurch wird der SHA-1 von .__ gedruckt. derzeit ausgechecktes Commit für jedes Submodul zusammen mit der Submodulpfad und die Ausgabe von git beschreiben den SHA-1. Jeder SHA-1 wird das Präfix vorangestellt - wenn das Submodul nicht initialisiert ist, + wenn das momentan ausgecheckte Submodul-Commit nicht mit dem SHA-1 übereinstimmt im Index des enthaltenden Repository gefunden und U, wenn das Submodul hat Mischkonflikte.

66
Jon Koops

Um nur die Namen der registrierten Submodule zurückzugeben, können Sie diesen Befehl verwenden:

grep path .gitmodules | sed 's/.*= //'

Betrachten Sie es als git submodule --list, der nicht existiert.

57
mholm815

Der folgende Befehl listet die Submodule auf:

git submodule--helper list

Die Ausgabe sieht ungefähr so ​​aus:

<mode> <sha1> <stage> <location>

Hinweis: Benötigt git 2.7.0 oder höher.

41
A.T.

Ich kann sehen, dass die Antwort ausgewählt wurde, aber für alle anderen, die diese Seite erreichen:

$ git submodule

listet alle Submodule im angegebenen Git-Repo auf.

Prost

17
Sandeep Gill

Ich benutze das: 

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

Ich habe festgestellt, dass der Befehl, der in einer Antwort auf diese Frage bereitgestellt wurde, mir die Informationen gab, nach denen ich gesucht hatte:

Keine Submodulzuordnung in .gitmodule für einen Pfad gefunden, der kein Submodul ist

git ls-files --stage | grep 160000
15
Max Cantor

Sie können verwenden:

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

Wenn Sie nichts dagegen haben, nur mit initialisierten Submodulen zu arbeiten, können Sie git submodule foreach verwenden, um das Parsen von Text zu vermeiden.

git submodule foreach --quiet 'echo $name'
8
benesch

Ich benutze dieses:

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

Ausgabe (Pfad + Version):

tools/deploy_utils (0.2.4)
7
Skarab

Das hat für mich funktioniert:

git ls-files --stage | grep ^160000

Basierend auf diesem großartigen Artikel: http://www.speirs.org/blog/2009/5/11/understanding-git-submodules.html

Edit: Es muss grep ^160000 gelesen werden

6
LTK

git config ermöglicht die Angabe einer Konfigurationsdatei.
Und .gitmodulesist eine Konfigurationsdatei.

Also mit Hilfe von " Leerzeichen als Trennzeichen mit dem Befehl" Ausschneiden " " verwenden:

git config --file=.gitmodules --get-regexp ^^submodule.*\.path$ | cut -d " " -f 2

Es werden nur die Pfade aufgelistet, einer pro deklariertem Submodul.

Als Tino weist in den Kommentaren darauf hin:

  • Dies schlägt für Submodule mit spaces fehl. 
  • submodulpfade können newlines enthalten, wie in

    git submodule add https://github.com/hilbix/bashy.git "sub module"
      git mv 'sub module' $'sub\nmodule'
    

Als robustere Alternative schlägt Tino vor: 

git config -z --file .gitmodules --get-regexp '\.path$' | \
  sed -nz 's/^[^\n]*\n//p' | \
  tr '\0' '\n' 

Für Pfade mit Zeilenumbrüchen (sie können mit git mv erstellt werden) lassen Sie den | tr '\0' '\n' weg und verwenden etwas wie ... | while IFS='' read -d '' path; do ... für die weitere Verarbeitung mit bash.
Dies erfordert eine moderne Bash, die read -d '' versteht (den Abstand zwischen -d and '' nicht vergessen).

4
VonC

Nur die Submodulpfade bitte, gnädige Frau ...

git config --list | grep \^submodule | cut -f 2 -d .
Vendor/BaseModel
Vendor/ObjectMatcher
Vendor/OrderedDictionary
Vendor/_ObjC
Vendor/XCodeHelpers

????????

4
Alex Gray

Um alle Submodule nach Namen aufzulisten:

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

3
bGorle

In meiner Version von git [1]Jedes Git-Submodul hat ein name und ein path. Sie müssen nicht unbedingt gleich sein [2]. Beides zuverlässig zu erhalten, ohne zuerst die Submodule (git update --init) auszuchecken, ist ein kniffliges Stück Shell-Zauberei.

Liste der Submodule abrufen names

Ich habe keine Möglichkeit gefunden, dies mit git config oder einem anderen git Befehl zu erreichen. Deshalb sind wir zurück, um .gitmodules (super hässlich) zu regexen. Es scheint jedoch einigermaßen sicher zu sein, da git den für das Submodul names zulässigen Codebereich begrenzt. Da Sie diese Liste wahrscheinlich für die weitere Shell-Verarbeitung verwenden möchten, werden in der folgenden Lösung die Einträge mit NULL-Bytes (\0) getrennt.

$ sed -nre \
  's/^\[submodule \"(.*)\"]$/\1\x0/p' \
  "$(git rev-parse --show-toplevel)/.gitmodules" \
| tr -d '\n' \
| xargs -0 -n1 printf "%b\0"

Und in deinem Drehbuch:

#!/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"
)

Hinweis : read -rd '' erfordert bash und funktioniert nicht mit sh

Liste der Submodule abrufen paths

In meinem Ansatz versuche ich nicht die Ausgabe von git config --get-regexp mit awk, tr, sed zu verarbeiten, ... aber stattdessen Null zu übergeben Byte zurück zu git config --get getrennt. Dies dient dazu, Probleme mit Zeilenumbrüchen, Leerzeichen und anderen Sonderzeichen (z. B. Unicode) im Untermodul paths zu vermeiden. Da Sie diese Liste wahrscheinlich für die weitere Shell-Verarbeitung verwenden möchten, werden in der folgenden Lösung die Einträge mit NULL-Bytes (\0) getrennt.

$ git config --null --file .gitmodules --name-only --get-regexp '\.path$' \
| xargs -0 -n1 git config --null --file .gitmodules --get

zum Beispiel in einem bash Skript könnten Sie dann:

#!/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
)

Hinweis : read -rd '' erfordert bash und funktioniert nicht mit sh


Fußnoten

[1] git Version

$ git --version
git version 2.22.0

[2] Submodul mit divergierenden name und path

Richten Sie das Test-Repository ein:

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

Bewegen Sie das Submodul, damit name und path auseinander gehen:

$ 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

Testen

Richten Sie das Test-Repository ein:

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

Liste der Submodule abrufen 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

Liste der Submodule abrufen 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

Wenn keine .gitmodules vorhanden sind, aber Submodule config in .git/modules/vorhanden sind

find .git/modules/ -name config -exec grep url {} \;
0
MrSwed

Hier ist eine andere Möglichkeit, Git-Submodulnamen aus .gitmodules zu analysieren, ohne dass sed- oder ausgefallene IFS-Einstellungen erforderlich sind. :-)

#!/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