Git deposundaki alt modülleri listeleme


247

İçinde birkaç alt modül bulunan bir Git depom var. git submodule initÇalıştırıldıktan sonra tüm alt modüllerin adlarını nasıl listeleyebilirim ?

git submodule foreachKomut altmodülün isimlerini yankı olabilir, ama onlar init adımdan sonra olmadı ki teslim edildikten sonra sadece çalışır. Zincirde, kontrol edilmeden önce gerçekleşmesi gereken daha fazla adım var ve alt modüllerin adlarını komut dosyasına zorlamak istemiyorum.

Şu anda kayıtlı, ancak henüz teslim alınmamış alt modüllerin adlarını almak için bir Git komutu var mı?


4
Süper saçma değil, ama Sandeep'in cevabı , git submodulevarsayımsal bir git submodule listdavranış sergilemeyi beklediğim gibi davrandığını gösteriyor - hiçbir argüman olmadan ne olduğunu kontrol etmeyi hiç düşünmedim git submodule. (Başlangıçta yanlış 'Paylaş' bağlantısını aldığım için bu bağlantıyı test ettiğim için sevindim!)
adaçayı

4
Buraya geldim çünkü git submodule listyoktu ve git submodule helpyardımcı olmadı (ikincisine göre, çözüm, git submodulegeçerli kullanım değil).
user2394284

Cevapların çoğu (kabul edilenler de dahil olmak üzere) alt modülü listeler paths, namesözel karakterler içerdiklerinde kırmazlar. Hem adlar hem de yollar için güvenli olması gereken bir cevap vermeye çalıştım: stackoverflow.com/a/56912913/3215929
Ente

Yanıtlar:


175

git submodule initKendisinin kullandığı mekanizmayı kullanabilirsiniz , yani bakın .gitmodules. Bu dosyalar, her alt modül yolunu ve başvurduğu URL'yi numaralandırır.

Örneğin, havuz kökünden, cat .gitmodulesiçeriği ekrana yazdırır (sahip olduğunuzu varsayarak cat).

.Gitmodule dosyalarının Git yapılandırma biçimi olduğundan, bu dosyaları ayrıştırmak için git config komutunu kullanabilirsiniz:

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

Size tüm alt modül girişlerini gösterir ve

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

sadece alt modül yolunun kendisini alırsınız.


Ancak konsolda hiçbir şey yazdırmıyor.
IgorGanapolsky

2
@IgorGanapolsky - cat .gitmodulesdepo kökünde yaparsanız, konsolda yazdırabilirsiniz ...
sdaau

Alt awkmodül yolunda boşluk varsa bölüm başarısız olur.
maikel

@Ikke Ad, yol ve url dahil alt modüllerin bir listesini almak istiyorum. Aşağıdaki Git komutunu denedim, ancak hiçbir şey döndürmüyor: git config --file = .gitmodules --get-regexp. *? Alt modül (. *)] Yol = (. *) Url = (. *) I den git git config --file = .gitmodules --get-regexp. *? (alt modül). *? (yol). *? (url) de. Belki bir çözümünüz var. Şimdiden teşekkür ederim.
Odrai

8
UYARI: awkboşluklu alt modüller için başarısız! Komut okumalıdır git config -z --file .gitmodules --get-regexp '\.path$' | sed -nz 's/^[^\n]*\n//p' | tr '\0' '\n'(bir modern sedile ihtiyacınız var -z). Bu , içinde Newlines bulunan yollar için başarısız olur (ile oluşturulabilir git mv). Bunlara karşı güvende olmak istiyorsanız, bırakın | tr '\0' '\n've ... | while IFS='' read -d '' path; do ...bash ile daha fazla işlem yapmak için benzer bir şey kullanın . Bu, anlayan modern bir bash gerektirir read -d ''( -dve arasındaki boşluğu unutmayın '').
Tino

110

Yuvalanmış alt modülleri göstermek istiyorsanız git submodule statusveya isteğe bağlı olarak kullanabilirsiniz git submodule status --recursive.

Git belgelerinden:

Alt modüllerin durumunu gösterir. Bu, alt modül yolu ve SHA-1 için tarif edilen git çıkışı ile birlikte, her alt modül için halihazırda teslim alınmış taahhüdün SHA-1'ini yazdıracaktır. Her SHA-1, ön modül başlatılmamışsa, + şu anda teslim alınan alt modül taahhüdü, içeren deponun dizininde bulunan SHA-1 ile eşleşmezse ve alt modül birleştirme çakışmaları içeriyorsa U ile ön ek olarak gösterilir.


2
git submodule update --init --recursiveTüm alt modülü başlatmak için çalıştırın .
Jon Koops

2
@IgorGanapolsky Stefaan'ın yorumunda yeni okudu: alt modüller henüz başlatılmamışsa bu tür komutlar çalışmaz . Çıktı yok = alt modül yok (boş liste).
Tim

6
Bu kesinlikle bash'ın yardımı olmadan basit ve yerel tabanlı bir komut kullanmak için en iyi yanıt olarak işaretlenmelidir git. Ve bu çözüm, çalışan kopyanın herhangi bir noktasında iyi çalıştığı şekilde zariftir (ancak elbette alt modüller kendileri, sonuçta doğrudan kendileri için geçerlidir).
Tim

Sandeep Gill'in cevabının söylediği gibi git submodule, hiçbir argüman olmadan aynı değildir git submodule status, bu yüzden kendinizi 7 karakter yazarak kurtarabilirsiniz ;-)
Sam

@Sam Çalıştıklarından beri aynı değiller git submodule status --recursive, ama git submodule --recursivedeğiller. Bu 7 karakter size bir şey alıyor. Gerçi ihtiyaçlarınıza bağlıdır.
Kevin Rak

60

Yalnızca kayıtlı alt modüllerin adlarını döndürmek için şu komutu kullanabilirsiniz:

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

Bunu git submodule --listvar olmayan olarak düşünün .


3
Bunun yerine, perl -ne '/^\s*path =\s*(.*)/ and push(@submods, $1); END { print(join("\n", sort(@submods)));}' "$(git rev-parse --show-toplevel)/.gitmodules"bu cevaba (1) kıyasla, herhangi bir alt dizinden (alt modül içinde olmasa da) çalışan kullanımı; (2) alt modülleri ada göre sıralar; ve (3) .gitmodüllerde yorumlanmış satırları yoksayar.
Colin D Bennett

6
Ve önyükleme yapmak unutulmaz!
Dan

1
Bunun, pathalt modül adında ( git submodule add https://github.com/commercialhaskell/path.git) mevcut olabileceği için bunu yapmanın çok özensiz bir yolu olduğunu unutmayın . Ama muhtemelen bunu önceden biliyordun. Bir .gitconfigçalışma ağacındaki herhangi bir yerden erişmek istiyorsanız veya bunu bir --baredepoda çalıştırmanız gerekiyorsa, bunun gibi bir şey kullanabilirsiniz git cat-file -p HEAD:.gitmodules | .... "Aşamalı" dosyaya başvurmanız gerekiyorsa bunu yapabilirsiniz git cat-file -p :.gitmodules | ..., ancak bunun olması için bir git indexgerekir.
Tino

57

Aşağıdaki komut alt modülleri listeler:

git submodule--helper list

Çıktı şu şekildedir:

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

Not: Git 2.7.0 veya üstünü gerektirir.


1
Harika!. Bu komut nerede belgelenir. Git for Windwos üzerinde çalışıyor, ancak git
scm.com'da

1
git ls-files --stage | grep ^160000(Yanıt stackoverflow.com/a/29325219 adresinden) aynı sonucu veriyor gibi görünüyor, bu nedenle eski gits ile uyumlu olmanız gerekiyorsa belki de bu iyi bir alternatiftir.
Tino

--Çift tire submodule--helper
işaretine

25

kullanın:

$ git submodule

Belirtilen Git deposundaki tüm alt modülleri listeler.


3
Bu, bahsi geçen diğer iki cevabın etkili bir şekilde yinelenen bir cevabıdır ( atlandığı takdirde ima edildiğine git submodule [status]dikkat edin status, bu aynıdır).
Colin D Bennett

Her zaman çalışmaz. fatal: no submodule mapping found in .gitmodules for path 'bla-bla/foo-bar'. Öncelikle henüz değiştirilmemiş tüm iç depoları silmelisiniz.
1919

1
En iyi cevap (• ̀ ω • ́) ✧
Răzvan Flavius ​​Panda

--recursiveBayrağı kullanmak istiyorsanız, şu statuskomutu açıkça eklemeniz gerektiğini unutmayın : git submodule status --recursiveçalışır, ancak git submodule --recursiveyapmaz.
Sam

17

Bunu kullanıyorum:

git config --list|egrep ^submodule

1
@IgorGanapolsky Stefaan'ın yorumunda yeni okudu: Alt modüller henüz başlatılmadıysa bu çalışmaz . Çıktı yok = alt modül yok (boş liste).
Tim

İhtiyacım olan şey bu. Alt modüllerin alt klasörlerini ve uzaktan kumandalarının url'lerini gösterir.
thinsoldier

17

Bu sorunun cevabında verilen komutun aradığım bilgiyi verdiğini fark ettim:

Alt modül olmayan bir yol için .gitmodule içinde alt modül eşlemesi bulunamadı

git ls-files --stage | grep 160000

Bu cevap güzel ve temiz, mholm815'in .gitmodules ayrıştırma yanıtına kıyasla herhangi bir dezavantajı var mı?
Colin D Bennett

BTW, sadece alt modüllerin adlarını istiyorsanız, kullanıngit ls-files --stage | grep 160000 | perl -ne 'chomp;split;print "$_[3]\n"'
Colin D Bennett

İçinde hiçbir .gimodulesşey olmadığı için bu benim için çalıştı .git/config. (Nasıl olduğundan emin değilim, bu durumda veri havuzunu aldım. Bu bir hataydı, bu yüzden çözüm git rm
buydu

1
Çıplak depolarla çalışıyor. .Timmodules çözeltisinin aksine.
kupson

1
Bu en iyi cevap. Sadece küçük bir nit: grep "^160000 "biraz daha sağlam olurdu.
Lassi

12

Yalnızca başlatılmış alt modüllerde çalışmayı önemsemiyorsanız, git submodule foreachmetin ayrıştırmasını önlemek için kullanabilirsiniz .

git submodule foreach --quiet 'echo $name'

1
Bu yanıt, yalnızca başlatılan alt modüller için çalıştığı için benzersizdir. İhtiyacınız olan şeye bağlı olarak, bu istenen davranış olabilir (ancak beklenmedik ve istenmeyen de olabilir.)
Seth Johnson

9

Kullanabilirsiniz:

git submodule | awk '{ print $2 }'

1
Bu, stackoverflow.com/a/23490756/895245 ile aynı çıktıyı üretiyor gibi görünüyor, ancak daha kısa.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Downvoted. Bu komut tehlikelidir, çünkü geçerli bir alt modül adıtest (master) olan , adı verilen bir alt modül iE (boşluk ve ardından parantez içeren ad) başarısız olur . Komut da düzeltilemez, çünkü git ya yazdırır moduleya da module (branch). Ve bu komut porcellain olmadığı için daha da kötüsü, bu nedenle komutun çıkışı önceden haber verilmeksizin gelecekte değişebilir.
Tino

7

Bunu kullanıyorum:

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

Çıktı (yol + sürüm):

tools/deploy_utils (0.2.4)

Bu versiyonun dezavantajı yavaş olması. O kadar çok submodules projelerde bu iyi bir çözüm değil veya belki yakın benim makinede altmodülün başına bir saniye için, her alt modülün durum denetimi çeşit yapıyor gibi görünüyor o vb bir komut dosyası çalıştırmak olmalıdır eğer
Colin D Bennett

7

Tüm alt modülleri ada göre listelemek için:

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



5

Sadece alt modül yolları , hanımefendi lütfen ...

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

👍🏼


4
Bu muhtemelen soru için tamamen geçerli bir cevap olsa da, bazı uyarılar: Bu sadece adlarında nokta içermeyen alt modüller için çalışır. Nokta, modül adlarında tamamen geçerlidir. .urlAnahtarlarla sınırlı değildir , bu nedenle diğer girişler de görünebilir (genellikle hiçbiri yoktur, ancak bok olur). --localBurada kullanmalısınız , çünkü görmek --globalve --systemayarları istemezsiniz . Ve son not, gözden kaçırılabileceğinden, sadece zaten mevcut olan alt modüller için çalışır .git/config(sonradan olduğu gibi git submodule initsoruya bakın).
Tino

5

git configbir yapılandırma dosyası belirtmenize izin verir.
ve .gitmodules olduğu bir yapılandırma dosyası.

Yani, " boşluk komutunu kesme komutuyla sınırlayıcı olarak kullan " yardımıyla :

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

Bu, bildirilen alt modül başına bir tane olmak üzere yalnızca yolları listeler.

As Tino işaret yorumlarda :

  • Bu, boşluklu alt modüller için başarısız olur bulunan .
  • alt modül yolları , olduğu gibi yeni satırlar içerebilir

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

Daha sağlam bir alternatif olarak Tino şunları öneriyor:

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

İçlerinde yeni satırları olan yollar için (bunlar ile oluşturulabilir git mv), bırakın | tr '\0' '\n've ... | while IFS='' read -d '' path; do ...bash ile daha fazla işlem yapmak için benzer bir şey kullanın .
Bu, anlayan modern bir bash gerektirir read -d ''(arasındaki boşluğu unutma -d and '').


hmmm ... "daha iyi bir yol olmalı" benim acil düşüncelerim
arcseldon

sanırım ben bash profil vb bu komuta takma ad olabilir neyse.
arcseldon

Bu, içinde boşluk bulunan alt modüller için başarısız olur. Ayrıca yolların Newline ( git submodule add https://github.com/hilbix/bashy.git "sub module"; git mv 'sub module' $'sub\nmodule') içerebileceğini unutmayın . Benim yoruma bakın kabul cevap sizinkine çok benzer.
Tino

@Tino İyi puan. Daha fazla görünürlük için yorumunuzu cevaba ekledim.
VonC

3

Git [1] sürümümde, her Git alt modülünde a nameve a bulunur path. Mutlaka aynı olmaları gerekmez [2] . Her ikisini de güvenilir bir şekilde elde etmek, önce alt modülleri kontrol etmeden ( git update --init), zor bir sihirbazlık parçasıdır.

Alt modülün bir listesini alın names

Bunu git configveya başka bir gitkomutu kullanarak bunu başarmanın bir yolunu bulamadım . Bu nedenle regex'e geri döndük .gitmodules(süper çirkin). Ancak git, alt modül için izin verilen olası kod alanını sınırladığı için biraz güvenli görünüyor names. Buna ek olarak, muhtemelen bu listeyi daha fazla kabuk işleme için kullanmak istediğinizden, NULL-bytes ( \0) ile ayrı girişlerin altındaki çözüm .

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

Ve senaryonuzda:

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

Not : read -rd ''gerektirir bashve çalışmaz sh.

Alt modülün bir listesini alın paths

Benim yaklaşımda denemek değil çıktı işlemek için git config --get-regexpbirlikte awk, tr, sed, ... ama bunun yerine sıfır bayt geri ayrılmış geçmektedir git config --get. Bu, alt modüldeki yeni satırlar, boşluklar ve diğer özel karakterlerle (örn. Unicode) ilgili sorunları önlemek içindir paths. Buna ek olarak, muhtemelen bu listeyi daha fazla kabuk işleme için kullanmak istediğinizden, NULL-bytes ( \0) ile ayrı girişlerin altındaki çözüm .

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

Örneğin, bir Bash betiğinde şunları yapabilirsiniz:

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

Not : read -rd ''gerektirir bashve çalışmaz sh.


Dipnotlar

[1] Git sürümü

$ git --version
git version 2.22.0

[2] Ayırmalı namevepath

Test havuzunu ayarlayın:

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

Yapmak nameve ayrıştırmak için alt modülü taşıyın 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

Test yapmak

Test havuzunu ayarlayın:

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

Alt modülün listesini alın 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

Alt modülün listesini alın 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

0

Herhangi bir .gitmodulesdosya yoksa, ancak bir alt modül yapılandırması varsa .git/modules/:

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

0

Git veya küçük IFS ayarlarına gerek kalmadan Git alt modül adlarını .gitmodules'ten ayrıştırmanın başka bir yolu. :-)

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

Ayrıca, bu çözüm kaçan çift tırnak örneğini doğru bir şekilde ele alırken, yukarıdaki çözüm kaçan bir çıktı üretir. Bazı durumlarda doğru olmayabilir. ;-)
devC0de

"yukarıda" ve "aşağıda" oylamaya dayalı sıralama düzeninde çalışmaz.
Ente
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.