Git 리포지토리에 하위 모듈 나열


247

여러 하위 모듈이있는 Git 저장소가 있습니다. git submodule init실행 된 후 모든 하위 모듈의 이름을 어떻게 나열 합니까?

git submodule foreach명령은 서브 모듈의 이름을 에코 할 수 있지만,이 초기화 단계 이후에 무슨 일이 있었되지 않은 체크 아웃 한 후에는 것을에만 작동합니다. 체인에 체크 아웃하기 전에 더 많은 단계가 필요하며 하위 모듈의 이름을 스크립트에 하드 와이어 링하지 않아도됩니다.

그렇다면 현재 등록되었지만 아직 체크 아웃되지 않은 서브 모듈의 이름을 가져 오는 Git 명령이 있습니까?


4
그렇지 않습니다,하지만 슈퍼 바보 하기 Sandeep의 응답 쇼 것으로 git submodule동작합니다 나는 가상의 예상대로 git submodule list행동 - 나는 단지와 무슨 일 확인 생각해 본 적이 없는 인수 git submodule. (처음에 잘못된 '공유'링크를 잡았 기 때문에 나는 그 링크를 테스트했습니다.)
sage

4
나는 git submodule list존재 git submodule help하지 않았고 도움 이되지 않았기 때문에 여기에 왔습니다 (후자에 따르면 해결책 git submodule은 유효하지 않습니다).
user2394284

목록 서브 모듈 (수락 포함)에 대한 답변의 대부분 paths, 아니 names그들이 특수 문자를 포함하고 휴식. 안전한 이름과 경로에 대한 답을 주려고했습니다 : stackoverflow.com/a/56912913/3215929
Ente

답변:


175

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 }'

서브 모듈 경로 자체 만 가져옵니다.


그러나 콘솔에서 아무것도 인쇄하지 않습니다.
IgorGanapolsky

2
@IgorGanapolsky- cat .gitmodules저장소 루트에서 작업하는 경우 콘솔에서 인쇄 할 수 있습니다 .
sdaau

awk당신이 서브 모듈 경로에 공백이있는 경우 일부는 실패합니다.
maikel

@Ikke 이름, 경로 및 URL을 포함한 하위 모듈 목록을 검색하고 싶습니다. 다음 Git 명령을 시도했지만 아무것도 반환하지 않습니다. git config --file = .gitmodules --get-regexp. *? submodule (. *)] path = (. *) url = (. *) I git config --file = .gitmodules --get-regexp. *? (submodule). *? (path). *? (url) 시도했습니다. 아마도 당신은 해결책이 있습니다. 미리 감사드립니다.
Odrai

8
경고 : awk공백이있는 하위 모듈에는 실패합니다! 이 명령은이어야합니다 git config -z --file .gitmodules --get-regexp '\.path$' | sed -nz 's/^[^\n]*\n//p' | tr '\0' '\n'(로 현대 sed가 필요합니다 -z). 개행 문자가있는 경로에서는 실패 합니다 (으로 만들 수 있음 git mv). 이것들로부터 안전하고 싶다면, bash를 | tr '\0' '\n'사용 ... | while IFS='' read -d '' path; do ...하여 추가 처리를 위해 같은 것을 사용하십시오 . 이것은 이해하는 현대적인 배쉬가 필요합니다 read -d ''( -d와 사이의 공백을 잊지 마십시오 '').
티노

110

중첩 된 하위 모듈을 표시하려는 경우 git submodule status또는 선택적으로 사용할 수 있습니다 git submodule status --recursive.

Git 문서에서 :

서브 모듈의 상태를 표시하십시오. 그러면 서브 모듈 경로 및 SHA-1에 대한 git describe 출력과 함께 각 서브 모듈에 대해 현재 체크 아웃 된 커밋의 SHA-1이 인쇄됩니다. 서브 모듈이 초기화되지 않은 경우, 각 체크 아웃 된 서브 모듈 커밋이 포함 저장소의 인덱스에서 찾은 SHA-1과 일치하지 않으면 +, 서브 모듈에 병합 충돌이있는 경우 U가 각 SHA-1 앞에 붙습니다.


2
git submodule update --init --recursive모든 서브 모듈을 초기화하기 위해 실행하십시오 .
Jon Koops 2012

2
@IgorGanapolsky는 Stefaan의 의견을 읽었습니다 . 서브 모듈이 아직 초기화되지 않은 경우 이러한 종류의 명령이 작동 하지 않습니다 . 출력 없음 = 하위 모듈 없음 (빈 목록).
Tim

6
이것은 bash의 도움없이 간단하고 기본 기반 명령 을 사용하는 가장 좋은 대답 으로 표시되어야합니다 git. 그리고이 솔루션은 작업 복사본의 어느 시점에서나 잘 작동하는 방식으로 우아합니다 (그러나 서브 모듈 자체는 물론 결과가 직접 적용됩니다).
Tim

하기 Sandeep 길의대로 대답은 말한다, git submodule인수와 동일합니다 git submodule status당신이 7 자 ;-) 입력 자신을 절약 할 수 있도록,

@Sam 그들은 git submodule status --recursive작동 이후 완전히 동일 git submodule --recursive하지 않지만 그렇지 않습니다. 그 7 명의 캐릭터는 당신에게 무언가를 사요. 그것은 당신의 필요에 달려 있습니다.
케빈 락

60

등록 된 서브 모듈의 이름 만 반환하려면 다음 명령을 사용하십시오.

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

git submodule --list존재하지 않는 것으로 생각하십시오 .


3
대신 perl -ne '/^\s*path =\s*(.*)/ and push(@submods, $1); END { print(join("\n", sort(@submods)));}' "$(git rev-parse --show-toplevel)/.gitmodules"이 답변과 비교하여 사용 (1) 모든 하위 디렉토리 (하위 모듈 내부는 아니지만)에서 작동합니다. (2) 서브 모듈을 이름별로 정렬합니다. 그리고 (3) .gitmodules에서 주석 처리 된 행을 무시합니다.
Colin D Bennett

6
그리고 부팅하는 것이 기억에 남습니다!
Dan

1
path하위 모듈 이름 ( git submodule add https://github.com/commercialhaskell/path.git) 에있을 수있는 매우 부주의 한 방법입니다 . 그러나 당신은 아마 이미 그것을 알고있었습니다. 작업 트리의 .gitconfig어느 곳에서나 액세스 하거나 --bare리포지토리 에서이를 실행해야하는 경우와 같은 것을 사용할 수 있습니다 git cat-file -p HEAD:.gitmodules | .... "staged"파일을 참조해야하는 경우에는 할 수 git cat-file -p :.gitmodules | ...있지만 git index가 있어야합니다.
티노

57

다음 명령은 서브 모듈을 나열합니다 :

git submodule--helper list

출력은 다음과 같습니다.

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

참고 : Git 2.7.0 이상이 필요합니다.


1
큰!. 이 명령은 어디에 기록되어 있습니까? Git for Windwos에서 작동하지만 git-scm.com에서
DarVar

1
git ls-files --stage | grep ^160000(Answer stackoverflow.com/a/29325219에서 ) 동일한 결과를 생성하는 것으로 보이므로 구형 gits와 호환되어야하는 경우 이는 좋은 대체품입니다.
티노

에주의하십시오 --더블 대시submodule--helper
it3xl

25

사용하다:

$ git submodule

지정된 Git 저장소의 모든 하위 모듈을 나열합니다.


3
이것은 실제로 언급 한 두 가지 다른 답변의 중복 답변입니다 git submodule [status]( status생략하면 암시되므로 동일합니다).
Colin D Bennett

항상 작동하지는 않습니다. fatal: no submodule mapping found in .gitmodules for path 'bla-bla/foo-bar'. 먼저 하위 모듈이 아닌 모든 내부 리포지토리를 삭제해야합니다.
it3xl

1
최고의 답변 (• ̀ ω • ́) ✧
Răzvan Flavius ​​Panda

--recursive플래그 를 사용하려면 다음 status명령 을 명시 적으로 추가해야합니다 . git submodule status --recursive작동하지만 작동 git submodule --recursive하지 않습니다.

17

나는 이것을 사용한다 :

git config --list|egrep ^submodule

1
@IgorGanapolsky는 Stefaan의 의견을 읽었습니다 . 서브 모듈이 아직 초기화되지 않은 경우 작동하지 않습니다 . 출력 없음 = 하위 모듈 없음 (빈 목록).
Tim

이것은 내가 필요한 것입니다. 하위 모듈의 하위 폴더와 해당 리모컨의 URL을 보여줍니다.
thinsoldier

17

이 질문에 대한 답변으로 제공된 명령이 내가 찾고있는 정보를 제공한다는 것을 알았습니다.

.gitmodule에서 하위 모듈이 아닌 경로에 대한 하위 모듈 매핑이 없습니다.

git ls-files --stage | grep 160000

이 대답은 훌륭하고 깨끗합니다 .mholm815의 대답 구문 분석 .gitmodules 와 비교할 때 단점이 있습니까?
Colin D Bennett

BTW, 당신은 단지 서브 모듈, 사용의 이름을 원하는 경우git ls-files --stage | grep 160000 | perl -ne 'chomp;split;print "$_[3]\n"'
콜린 D 베넷

에 내가 .gimodules없거나 아무것도 없기 때문에 이것은 나를 위해 일했습니다 .git/config. (어떻게 발생하는지 잘 모르겠습니다.이 상태의 저장소를 찾았습니다. 실수 였으므로 해결책이있었습니다 git rm.)
wenzeslaus

1
맨손으로 repos를 사용하고 있습니다. .gitmodules 솔루션과 달리
kupson

1
이것이 가장 좋은 대답입니다. 단지 작은 니트 : grep "^160000 "약간 더 견고합니다.
Lassi

12

초기화 된 서브 모듈에서만 작동하는 것을 신경 쓰지 않으면 git submodule foreach텍스트 구문 분석을 피할 수 있습니다 .

git submodule foreach --quiet 'echo $name'

1
이 답변은 초기화 된 하위 모듈에만 작동한다는 점에서 독특합니다. 필요한 것에 따라, 이것은 바람직한 행동 일 수도 있지만 예상치 못한 결과 일 수도 있습니다.
Seth Johnson

9

당신이 사용할 수있는:

git submodule | awk '{ print $2 }'

1
이것은 stackoverflow.com/a/23490756/895245 와 동일한 출력을 생성하는 것으로 보이지만 더 짧습니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

공감. 이 명령은 유효한 하위 모듈 이름test (master)(이름 뒤에 공백이 있고 괄호가있는) 하위 모듈 iE에 대해 실패하므로 위험합니다 . 또한이 명령은 고정 때문에 자식 중 하나를 인쇄 할 수없는 나 . 그리고이 명령은 포르 셀린이 아니기 때문에 더 나쁩니다. 따라서 명령의 출력은 사전 통지없이 변경 될 수 있습니다. modulemodule (branch)
티노

7

나는 이것을 사용한다 :

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

출력 (경로 + 버전) :

tools/deploy_utils (0.2.4)

이 버전의 단점은 속도가 느리다는 것입니다. 각 하위 모듈에서 일종의 상태 검사를 수행하는 것 같습니다. 내 컴퓨터의 하위 모듈 당 1 초에 가깝기 때문에 많은 하위 모듈이있는 프로젝트에서는 이것이 좋은 해결책이 아니거나 스크립트 등에서 실행 해야하는 경우입니다.
Colin D Bennett

7

이름으로 모든 하위 모듈을 나열하려면

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



5

그냥 서브 모듈 경로 , 부인을 기쁘게 ...

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

👍🏼


4
이것은 아마도 질문에 대한 완전한 대답 일지 모르지만 여기에 몇 가지주의 사항이 있습니다. 이름에 점이 포함되지 않은 하위 모듈에만 적용됩니다. 점은 모듈 이름에서 완전히 유효합니다. .url키로 제한되지 않으므로 다른 항목도 나타날 수 있습니다 (보통 아무것도 없지만 똥이 발생합니다). 당신은 사용해야 --local당신이보고 싶어하지 않기 때문에, 여기 --global--system설정. 마지막으로, 간과 될 수 있기 때문에 이미 존재하는 하위 모듈에서만 작동합니다 .git/config(after처럼 git submodule init질문 참조).
티노

5

git config구성 파일을 지정할 수 있습니다.
그리고 .gitmodules 이다 설정 파일은.

따라서 " cut 명령을 사용하여 공간을 구분 기호로 사용 "을 사용하십시오 .

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

선언 된 서브 모듈 당 하나의 경로 만 나열됩니다.

Tino 가 주석에서 지적한 것처럼 :

  • 공백이 있는 하위 모듈의 경우 실패 합니다.
  • 하위 모듈 경로에는 다음 과 같이 줄 바꿈 이 포함될 수 있습니다 .

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

보다 강력한 대안으로 Tino는 다음을 제안합니다.

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

개행 문자가있는 경로의 경우 (으로 만들 수 있음 git mv)을 남겨두고 bash를 사용한 추가 처리와 | tr '\0' '\n'같은 것을 사용하십시오 ... | while IFS='' read -d '' path; do ....
이것은 이해하는 현대적인 배쉬가 필요합니다 read -d ''(사이의 공백을 잊지 마십시오 -d and '').


흠 ... "더 좋은 방법이 있어야한다"내 즉각적인 생각입니다
arcseldon

어쨌든 bash 프로필 등에서 해당 명령의 별칭을 지정할 수 있습니다.
arcseldon

공백이있는 하위 모듈의 경우 실패합니다. 또한 경로에는 줄 바꿈 ( git submodule add https://github.com/hilbix/bashy.git "sub module"; git mv 'sub module' $'sub\nmodule') 이 포함될 수 있습니다 . 귀하의 답변 과 매우 유사한 수락 된 답변에 대한 내 의견을 참조 하십시오.
티노

@ 티노 좋은 포인트. 더 많은 가시성을 제공하기 위해 귀하의 의견을 답변에 포함 시켰습니다.
VonC

3

내 버전의 Git [1] 에서는 모든 Git 하위 모듈에 a name및 a가 path있습니다. 그것들이 반드시 동일 할 필요는 없다 [2] . 하위 모듈을 먼저 확인하지 않고 안정적인 방식으로 두 가지를 모두 얻는 것은 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-regexpawk, tr, sed, ... 대신이 0 바이트가 다시 분리 통과 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 --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

0

거기에 어떤없는 경우 .gitmodules파일하지만, 서브 모듈 구성에 존재 .git/modules/:

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

0

다음은 sed 또는 fancy IFS 설정없이 .gitmodules에서 Git 서브 모듈 이름을 구문 분석하는 다른 방법입니다. :-)

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

또한이 솔루션은 이스케이프 된 큰 따옴표 예제를 올바르게 처리하는 반면 위의 솔루션은 이스케이프 된 출력을 생성합니다. 어떤 경우에는 올바르지 않을 수 있습니다. ;-)
devC0de

"위"및 "아래"는 투표 기반 정렬 순서에서 실제로 작동하지 않습니다.
Ente
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.