Liệt kê các mô hình con trong kho Git


246

Tôi có một kho lưu trữ Git có một số mô hình con trong đó. Làm thế nào để tôi liệt kê tên của tất cả các mô hình con sau khi git submodule initđã được chạy?

Các git submodule foreachlệnh có thể vang tên của các submodule, nhưng điều đó chỉ có tác dụng một khi họ đã được kiểm tra ra mà đã không xảy ra sau khi bước init. Có nhiều bước hơn trong chuỗi cần phải xảy ra trước khi chúng có thể được kiểm tra và tôi không muốn phải đặt tên của các mô hình con cứng vào tập lệnh.

Vì vậy, có một lệnh Git để có được tên của tất cả các đăng ký hiện đang đăng ký, nhưng chưa kiểm tra các mô hình con?


4
Thật ngớ ngẩn khi điều đó không xảy ra, nhưng câu trả lời của Sandeep cho thấy git submodulehành vi như tôi mong đợi là một giả thuyết git submodule listđể hành xử - tôi chỉ không bao giờ nghĩ sẽ kiểm tra những gì xảy ra mà không có tranh luận git submodule. (Vui mừng vì tôi đã kiểm tra liên kết đó, vì ban đầu tôi đã lấy liên kết 'Chia sẻ' sai!)
hiền nhân

4
Tôi đến đây vì git submodule listkhông tồn tại và git submodule helpkhông giúp đỡ (theo giải pháp sau, giải pháp này, git submodulekhông phải là cách sử dụng hợp lệ).
dùng2394284

Hầu hết các câu trả lời (bao gồm câu trả lời được chấp nhận) liệt kê mô hình con paths, không namesvà ngắt khi chúng chứa các ký tự đặc biệt. Tôi đã cố gắng đưa ra câu trả lời cho cả tên và đường dẫn nên an toàn: stackoverflow.com/a/56912913/3215929
Ente

Câu trả lời:


175

Bạn có thể sử dụng cơ chế tương tự như git submodule initsử dụng chính nó, cụ thể là, nhìn vào .gitmodules. Tệp này liệt kê từng đường dẫn mô hình con và URL mà nó đề cập đến.

Ví dụ: từ thư mục gốc của kho lưu trữ, cat .gitmodulessẽ in nội dung ra màn hình (giả sử bạn có cat).

Vì các tệp .gitmodule có định dạng cấu hình Git, bạn có thể sử dụng cấu hình git để phân tích các tệp đó:

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

Sẽ hiển thị cho bạn tất cả các mục con, và với

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

bạn sẽ chỉ nhận được đường dẫn mô hình chính nó.


Nhưng nó không in bất cứ thứ gì trên bàn điều khiển.
IgorGanapolsky

2
@IgorGanapolsky - bạn có thể in trên bảng điều khiển, nếu bạn làm cat .gitmodulestrong kho lưu trữ gốc ...
sdaau

Phần awkthất bại nếu bạn có khoảng trắng trong đường dẫn mô hình con.
maikel

@Ikke Tôi muốn lấy danh sách các mô hình con bao gồm tên, đường dẫn và url. Tôi đã thử lệnh Git sau, nhưng nó không trả về bất cứ thứ gì: git config --file = .gitmodules --get-regapi. *? Subodule (. *)] Path = (. *) Url = (. *) I đã thử git config --file = .gitmodules --get-regapi. *? (mô đun con). *? (đường dẫn). *? (url) là tốt. Có lẽ bạn có một giải pháp. Cảm ơn bạn trước.
Odrai

8
CẢNH BÁO: awkthất bại cho các mô hình con với không gian! Lệnh nên đọc git config -z --file .gitmodules --get-regexp '\.path$' | sed -nz 's/^[^\n]*\n//p' | tr '\0' '\n'(bạn cần một hiện đại sedvới -z). Điều này không thành công cho các đường dẫn có Newlines trong chúng (chúng có thể được tạo bằng git mv). Nếu bạn muốn an toàn trước những điều này, hãy bỏ qua | tr '\0' '\n'và sử dụng một cái gì đó như ... | while IFS='' read -d '' path; do ...để xử lý thêm với bash. Điều này cần một bash hiện đại để hiểu read -d ''(đừng quên khoảng trống giữa -d'').
Tino

109

Bạn có thể sử dụng git submodule statushoặc tùy chọn git submodule status --recursivenếu bạn muốn hiển thị các mô hình con lồng nhau.

Từ tài liệu Git:

Hiển thị trạng thái của các mô hình con. Điều này sẽ in SHA-1 của cam kết hiện đang được kiểm tra cho mỗi mô hình con, cùng với đường dẫn mô hình con và đầu ra của mô tả git cho SHA-1. Mỗi SHA-1 sẽ được thêm tiền tố - nếu mô hình con không được khởi tạo, + nếu cam kết mô hình con hiện đang kiểm tra không khớp với SHA-1 được tìm thấy trong chỉ mục của kho chứa và U nếu mô hình con có xung đột hợp nhất.


2
Chỉ cần chạy git submodule update --init --recursiveđể khởi tạo tất cả các mô hình con.
Jon Koops 11/2/2015

2
@IgorGanapolsky chỉ cần đọc tại bình luận của Stefaan: loại lệnh này không hoạt động nếu các mô hình con chưa được khởi tạo . Không có đầu ra = không có mô hình con (danh sách trống).
Tim

6
Điều này chắc chắn nên được đánh dấu là câu trả lời tốt nhất cho việc sử dụng một lệnh đơn giản và gitdựa trên nguồn gốc mà không cần bất kỳ sự trợ giúp nào từ bash. Và giải pháp này là thanh lịch theo cách nó chạy tốt ở bất kỳ điểm nào của bản sao làm việc (tất nhiên là chính các mô hình con, mà kết quả áp dụng trực tiếp cho chính chúng).
Tim

Như câu trả lời của Sandeep Gill nói, git submodulekhông có đối số nào giống như git submodule statusvậy, vì vậy bạn có thể tự lưu 7 ký tự ;-)
Sam

@Sam Họ không hoàn toàn giống nhau kể từ khi git submodule status --recursivelàm việc, nhưng git submodule --recursivekhông. 7 nhân vật đó mua cho bạn một cái gì đó. Nó phụ thuộc vào nhu cầu của bạn mặc dù.
Kevin Rak

60

Để chỉ trả lại tên của các mô hình con đã đăng ký, bạn có thể sử dụng lệnh này:

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

Hãy nghĩ về nó như git submodule --listkhông tồn tại.


3
Thay vào đó, sử dụng perl -ne '/^\s*path =\s*(.*)/ and push(@submods, $1); END { print(join("\n", sort(@submods)));}' "$(git rev-parse --show-toplevel)/.gitmodules"cái mà so với câu trả lời này (1) hoạt động từ bất kỳ thư mục con nào (mặc dù không nằm trong một mô hình con); (2) sắp xếp các mô hình con theo tên; và (3) bỏ qua các dòng nhận xét trong .gitmodules.
Colin D Bennett

6
Và thật đáng nhớ khi khởi động!
Dan

1
Lưu ý rằng đây là cách làm rất cẩu thả, như pathcó thể có trong tên mô hình con ( git submodule add https://github.com/commercialhaskell/path.git). Nhưng có lẽ bạn đã biết điều đó trước đây. Nếu bạn muốn truy cập .gitconfigtừ bất cứ nơi nào trong một bàn làm việc hoặc cần chạy nó trong --barekho lưu trữ, bạn có thể sử dụng một cái gì đó như git cat-file -p HEAD:.gitmodules | .... Nếu bạn cần tham khảo tệp "dàn dựng", bạn có thể làm git cat-file -p :.gitmodules | ..., tuy nhiên điều này cần có một git indexđể có mặt.
Tino

56

Lệnh sau sẽ liệt kê các mô hình con:

git submodule--helper list

Đầu ra là một cái gì đó như thế này:

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

Lưu ý: Nó yêu cầu Git 2.7.0 trở lên.


1
Tuyệt quá!. Lệnh này được ghi lại ở đâu. Hoạt động trên Git cho Windwos nhưng không thể tìm thấy bất kỳ tài liệu nào trên git-scm.com
DarVar

1
git ls-files --stage | grep ^160000(từ Trả lời stackoverflow.com/a/29325219 ) dường như tạo ra kết quả tương tự, vì vậy có lẽ đây là một sự thay thế tốt nếu bạn cần tương thích với các gits cũ.
Tino

Hãy chú ý đến --dấu gạch ngang kép trongsubmodule--helper
it3xl

25

Sử dụng:

$ git submodule

Nó sẽ liệt kê tất cả các mô hình con trong kho Git được chỉ định.


3
Đây thực sự là một câu trả lời trùng lặp của hai câu trả lời khác được đề cập git submodule [status](lưu ý statusđược ngụ ý nếu bỏ qua, vì vậy đây là như nhau).
Colin D Bennett

Không phải lúc nào cũng làm việc. fatal: no submodule mapping found in .gitmodules for path 'bla-bla/foo-bar'. Trước tiên, bạn phải xóa tất cả các kho lưu trữ bên trong chưa được đăng ký.
it3xl

1
Câu trả lời hay nhất (• ω • ́) ✧
Răzvan Flavius ​​Panda

Lưu ý rằng nếu bạn muốn sử dụng --recursivecờ, bạn phải thêm rõ ràng statuslệnh: git submodule status --recursivehoạt động, nhưng git submodule --recursivekhông.
Sam

17

Tôi sử dụng cái này:

git config --list|egrep ^submodule

1
@IgorGanapolsky chỉ cần đọc tại bình luận của Stefaan: Điều này không hoạt động nếu các mô hình con chưa được khởi tạo . Không có đầu ra = không có mô hình con (danh sách trống).
Tim

Đây là exaclty những gì tôi cần. Nó cho thấy các thư mục con của các mô hình con và các url của điều khiển từ xa của chúng.
thinsoldier

17

Tôi nhận thấy rằng lệnh được cung cấp trong câu trả lời cho câu hỏi này đã cho tôi thông tin mà tôi đang tìm kiếm:

Không tìm thấy ánh xạ mô hình con trong .gitmodule cho một đường dẫn không phải là mô hình con

git ls-files --stage | grep 160000

Câu trả lời này rất hay và sạch sẽ, có bất kỳ nhược điểm nào so với phân tích cú pháp câu trả lời của mholm815 không?
Colin D Bennett

BTW, nếu bạn chỉ muốn tên của các mô hình con, hãy sử dụnggit ls-files --stage | grep 160000 | perl -ne 'chomp;split;print "$_[3]\n"'
Colin D Bennett

Điều này làm việc cho tôi vì tôi không có .gimoduleshoặc có bất cứ điều gì trong .git/config. (Tôi không chắc nó xảy ra như thế nào. Tôi đã có kho lưu trữ ở trạng thái này. Đó là một số sai lầm, vì vậy giải pháp là git rm.)
wenzeslaus

1
Nó hoạt động với repos trần. Không giống như dung dịch .gitmodules.
kupson

1
Đây là câu trả lời tốt nhất. Chỉ cần một nit nhỏ: grep "^160000 "sẽ mạnh mẽ hơn một chút.
Lassi

12

Nếu bạn không nhớ chỉ hoạt động trên các mô hình con khởi tạo, bạn có thể sử dụng git submodule foreachđể tránh phân tích cú pháp văn bản.

git submodule foreach --quiet 'echo $name'

1
Câu trả lời này là duy nhất ở chỗ nó chỉ hoạt động cho các mô hình con đã được khởi tạo. Tùy thuộc vào những gì bạn cần, đây có thể là hành vi mong muốn (nhưng cũng có thể là bất ngờ và không mong muốn.)
Seth Johnson

9

Bạn có thể dùng:

git submodule | awk '{ print $2 }'

1
Điều này dường như tạo ra cùng một đầu ra như stackoverflow.com/a/23490756/895245 nhưng ngắn hơn.
Ciro Santilli 郝海东 冠状 病 事件

Bị hạ bệ. Lệnh này rất nguy hiểm, vì nó không thành công cho một mô hình con iE được đặt tên test (master)(tên có khoảng trắng theo sau dấu ngoặc đơn), đây là tên mô hình con hợp lệ . Lệnh cũng không thể được sửa, bởi vì git hoặc in modulehoặc module (branch). Và thậm chí còn tệ hơn, vì lệnh này không phải là porcellain, vì vậy đầu ra của lệnh có thể thay đổi trong tương lai mà không cần thông báo trước.
Tino

7

Tôi sử dụng cái này:

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

Đầu ra (đường dẫn + phiên bản):

tools/deploy_utils (0.2.4)

Nhược điểm tôi thấy của phiên bản này là nó chậm. Nó dường như đang thực hiện một số loại kiểm tra trạng thái trên mỗi mô hình con, có thể gần một giây trên mỗi mô hình con trên máy của tôi, vì vậy đối với các dự án có nhiều mô hình con thì đây không phải là một giải pháp tốt, hoặc nếu nó nên được chạy từ một kịch bản, v.v.
Colin D Bennett

7

Để liệt kê tất cả các mô hình con theo tên:

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



5

Xin vui lòng chỉ các đường dẫn mô hình con , thưa bà ...

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

👍🏼


4
Mặc dù đây có lẽ là một câu trả lời hoàn toàn hợp lệ cho câu hỏi, đây là một số lưu ý: Điều này chỉ hoạt động đối với các mô hình con không chứa dấu chấm trong tên của chúng. Một dấu chấm là hoàn toàn hợp lệ trong tên mô-đun. Nó không giới hạn .urlcác khóa, vì vậy các mục khác cũng có thể hiển thị (thường không có, nhưng shit xảy ra). Bạn nên sử dụng --localở đây, vì bạn không muốn xem --global--systemcài đặt. Và cuối cùng cần lưu ý, bởi vì nó có thể bị bỏ qua, nó chỉ hoạt động cho các mô hình con, đã có mặt .git/config(như sau git submodule init, xem câu hỏi).
Tino

5

git configcho phép chỉ định một tập tin cấu hình.
.gitmodules một tập tin cấu hình.

Vì vậy, với sự trợ giúp của " sử dụng không gian như một dấu phân cách với lệnh cắt ":

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

Điều đó sẽ chỉ liệt kê các đường dẫn, mỗi đường dẫn được khai báo.

Như Tino chỉ ra trong các ý kiến :

  • Điều này thất bại cho các mô hình con với không gian trong đó.
  • đường dẫn mô hình con có thể chứa dòng mới , như trong

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

Như một sự thay thế mạnh mẽ hơn, Tino đề xuất:

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

Đối với các đường dẫn có dòng mới trong chúng (chúng có thể được tạo bằng git mv), hãy bỏ qua | tr '\0' '\n'và sử dụng một cái gì đó như ... | while IFS='' read -d '' path; do ...để xử lý thêm với bash.
Điều này cần một bash hiện đại để hiểu read -d ''(đừng quên khoảng trống giữa -d and '').


hmmm ... "phải có một cách tốt hơn" là những suy nghĩ ngay lập tức của tôi
arcseldon

đoán tôi có thể bí danh lệnh đó trong hồ sơ bash, vv cảm ơn dù sao đi nữa.
arcseldon

Điều này thất bại cho các mô hình con với không gian trong đó. Cũng lưu ý rằng các đường dẫn có thể chứa Newlines ( git submodule add https://github.com/hilbix/bashy.git "sub module"; git mv 'sub module' $'sub\nmodule'). Xem bình luận của tôi cho câu trả lời được chấp nhận rất giống với câu trả lời của bạn.
Tino

@Tino Điểm tốt. Tôi đã bao gồm nhận xét của bạn trong câu trả lời để dễ nhìn hơn.
VonC

3

Trong phiên bản Git của tôi [1] , mọi mô hình con Git đều có a namevà a path. Họ không nhất thiết phải giống nhau [2] . Nhận cả hai theo một cách đáng tin cậy, mà không cần kiểm tra các mô hình con đầu tiên ( git update --init), là một mẹo nhỏ của thuật sĩ vỏ.

Lấy một danh sách các mô hình con names

Tôi đã không tìm ra cách để đạt được điều này bằng cách sử dụng git confighoặc bất kỳ gitlệnh nào khác . Vì vậy, chúng tôi trở lại regex trên .gitmodules(siêu xấu xí). Nhưng nó có vẻ an toàn vì gitgiới hạn không gian mã có thể được phép cho mô hình con names. Ngoài ra, vì bạn có thể muốn sử dụng danh sách này để xử lý shell hơn nữa, giải pháp bên dưới các mục riêng biệt với 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"

Và trong kịch bản của bạn:

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

Lưu ý : read -rd ''yêu cầu bashvà sẽ không làm việc với sh.

Lấy một danh sách các mô hình con paths

Trong cách tiếp cận của tôi, tôi cố gắng không để xử lý đầu ra từ git config --get-regexpvới awk, tr, sed, ... nhưng thay vì vượt qua nó một byte không tách ra trở lại git config --get. Điều này là để tránh các vấn đề với dòng mới, dấu cách và các ký tự đặc biệt khác (ví dụ Unicode) trong mô hình con paths. Ngoài ra, vì bạn có thể muốn sử dụng danh sách này để xử lý shell hơn nữa, giải pháp bên dưới các mục riêng biệt với NULL-bytes ( \0).

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

Ví dụ: trong tập lệnh Bash, bạn có thể:

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

Lưu ý : read -rd ''yêu cầu bashvà sẽ không làm việc với sh.


Chú thích

[1] Phiên bản Git

$ git --version
git version 2.22.0

[2] Submodule với phân kỳ namepath

Thiết lập kho kiểm tra:

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

Di chuyển mô hình con để thực hiện namepathphân kỳ:

$ 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

Kiểm tra

Thiết lập kho kiểm tra:

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

Nhận danh sách các mô hình con 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

Nhận danh sách các mô hình con 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

Nếu không có .gitmodulestệp nào , nhưng cấu hình mô đun con tồn tại trong .git/modules/:

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

0

Dưới đây là một cách khác để phân tích tên mô đun con Git từ .gitmodules mà không cần cài đặt IFS sed hoặc ưa thích. :-)

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

Thêm vào đó, giải pháp này dường như xử lý ví dụ dấu ngoặc kép được thoát một cách chính xác trong khi giải pháp trên tạo ra một đầu ra thoát. Mà có thể không đúng trong một số trường hợp. ;-)
devC0de

"Trên" và "dưới" không thực sự hoạt động theo thứ tự sắp xếp dựa trên biểu quyết.
Ente
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.