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-regexp에 awk, 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.