Gitリポジトリのサブモジュールを一覧表示する


246

いくつかのサブモジュールが含まれているGitリポジトリがあります。git submodule init実行後にすべてのサブモジュールの名前を一覧表示するにはどうすればよいですか?

git submodule foreachコマンドは、サブモジュールの名前をエコー可能性が、彼らは初期化ステップの後に起きていないそのチェックアウトされた後ということにのみ機能します。チェックアウトする前に実行する必要のある手順がチェーンにあります。サブモジュールの名前をスクリプトに固定する必要はありません。

現在登録されているがまだチェックアウトされていないすべてのサブモジュールの名前を取得するGitコマンドはありますか?


4
それはそうではないという超愚かなことですが、サンディープの答えは、git submodule私が仮定git submodule listした動作を期待したとおりに動作することを示してますgit submodule。(最初に間違った「共有」リンクをつかんだので、そのリンクをテストしてよかった!)
セージ

4
私がここに来たのgit submodule listは、存在git submodule helpせず、役に立たなかったためです(後者によると、解決策git submoduleは有効な使用法ではありません)。
user2394284 2017

回答のほとんど(承認されたものを含む)はサブモジュールをリストしますが、特殊文字が含まれている場合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 2015

2
@IgorGanapolsky- cat .gitmodulesリポジトリのルートで行うと、コンソールで印刷できます...
sdaau

awkサブモジュールパスにスペースがある場合、パーツは失敗します。
マイケル2017

@Ikke名前、パス、URLを含むサブモジュールのリストを取得したいと思います。次のGitコマンドを試しましたが、何も返されません。git config --file = .gitmodules --get-regexp。*?submodule(。*)] path =(。*)url =(。*)I git config --file = .gitmodules --get-regexp。*?(submodule)。*?(path)。*?(url)も試しました。おそらくあなたは解決策を持っています。前もって感謝します。
Odrai 2017年

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 ...ください。これには、理解できる最新のbashが必要read -d ''です(-dとの間のスペースを忘れないでください'')。
ティノ

109

ネストされたサブモジュールを表示するgit submodule status場合git submodule status --recursive、またはオプションで使用できます。

Gitのドキュメントから:

サブモジュールのステータスを表示します。これにより、各サブモジュールの現在チェックアウトされているコミットのSHA-1が、SHA-1のサブモジュールパスとgit describeの出力とともに出力されます。各SHA-1には、サブモジュールが初期化されていない場合は+、現在チェックアウトされているサブモジュールコミットが含まれているリポジトリのインデックスにあるSHA-1と一致しない場合はプレフィックスが付けられ、サブモジュールにマージ競合がある場合はUが付けられます。


2
git submodule update --init --recursiveすべてのサブモジュールを初期化するために実行するだけです。
Jon Koops、2015

2
@IgorGanapolskyがStefaanのコメントを読んだところです。この種のコマンドは、サブモジュールがまだ初期化されていないと機能しません。出力なし=サブモジュールなし(空のリスト)。
Tim

6
これは、bashの助けを借りずに、シンプルでネイティブベースのコマンドを使用するためのベストアンサーとしてマークする必要がありますgit。そしてこのソリューションは、作業コピーのどの時点でも適切に実行されるという点で優れています(もちろん、サブモジュール自体はもちろん、その結果が直接自分に適用されます)。
Tim

Sandeep Gillの答えが言うように、git submodule引数なしはと同じなのでgit submodule status、7文字を入力する手間を省くことができます;-)
Sam

彼らは@Sam以来、全く同じではありませんgit submodule status --recursive動作しますが、git submodule --recursiveしません。これらの7つのキャラクターはあなたに何かを買います。それはあなたのニーズにもよるが。
Kevin Rak

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"この回答と比較してwhichを使用してください(1)(サブモジュール内ではありませんが)任意のサブディレクトリから機能します。(2)サブモジュールを名前でソートします。(3).gitmodulesのコメント行を無視します。
コリンDベネット

6
そして起動するのは印象的です!
Dan

1
これはpath、サブモジュール名(git submodule add https://github.com/commercialhaskell/path.git)に存在する可能性があるため、非常にずさんな方法です。しかし、おそらくあなたはすでにそのことをすでに知っていました。.gitconfigワークツリーのどこからでもアクセスしたい場合、またはこれを--bareリポジトリで実行する必要がある場合は、などを使用できますgit cat-file -p HEAD:.gitmodules | ...。「ステージングされた」ファイルを参照する必要がある場合は実行できますがgit cat-file -p :.gitmodules | ...、これにはgit indexが必要です。
ティノ

56

次のコマンドは、サブモジュールを一覧表示します。

git submodule--helper list

出力は次のようになります。

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

注:Git 2.7.0以降が必要です。


1
すごい!。このコマンドはどこに文書化されていますか。Windwos用のGitの上で動作しますが、上の任意のドキュメントを見つけることができませんgit-scm.com
DarVar

1
git ls-files --stage | grep ^160000(回答よりstackoverflow.com/a/29325219)は同じ結果を生成するようですので、古いgitとの互換性が必要な場合、これはおそらく良い代替品です。
ティノ

--ダブルダッシュに注意してsubmodule--helper
ください-it3xl

25

使用する:

$ git submodule

指定したGitリポジトリ内のすべてのサブモジュールが一覧表示されます。


3
これは事実上、言及されている他の2つの回答の重複した回答ですgit submodule [status]status省略された場合は暗黙に示されるため、これは同じです)。
コリンDベネット

常に機能するとは限りません。fatal: no submodule mapping found in .gitmodules for path 'bla-bla/foo-bar'。最初に、まだサブモジュール化されていないすべての内部リポジトリーを削除する必要があります。
it3xl

1
ベストアンサー(•̀ω•́)✧
RăzvanFlavius Panda

--recursiveフラグを使用したい場合、statusコマンドを明示的に追加する必要があることに注意してください:git submodule status --recursive機能しますが、git submodule --recursiveしません。
Sam

17

私はこれを使います:

git config --list|egrep ^submodule

1
@IgorGanapolskyがStefaanのコメントを読んだところ:サブモジュールがまだ初期化されていない場合、これは機能しません。出力なし=サブモジュールなし(空のリスト)。
Tim

これは私が必要としたものです。サブモジュールのサブフォルダーとそのリモートのURLが表示されます。
thinsoldier

17

この質問への回答で提供されたコマンドが、私が探していた情報を提供してくれていることに気づきました。

.gitmoduleで、サブモジュールではないパスのサブモジュールマッピングが見つかりません

git ls-files --stage | grep 160000

この回答は素晴らしく、きれいです。.gitmodulesを解析するmholm815の回答と比べて不利な点はありますか?
コリンDベネット

ところで、サブモジュールの名前だけが必要な場合は、git ls-files --stage | grep 160000 | perl -ne 'chomp;split;print "$_[3]\n"'
Colin D Bennett

私には.gimodules何もなかったので、これは私にとってはうまくいきました.git/config。(それがどのように発生するかはわかりませんが、この状態でリポジトリを取得しました。これはいくつかの誤りでしgit rmたので、解決策はでした。)
wenzeslaus

1
それは裸のリポジトリで動作しています。.gitmodulesソリューションとは異なり。
kupson 2016年

1
これが最良の答えです。ほんの小さなニット:grep "^160000 "もう少し堅牢です。
ラッシー2017年

12

初期化されたサブモジュールのみを操作してもかまわない場合は、git submodule foreachテキスト解析を回避するために使用できます。

git submodule foreach --quiet 'echo $name'

1
この回答は、初期化されたサブモジュールに対してのみ機能するという点で独特です。何が必要に応じて、これは望ましい動作であるかもしれない(それはまた、予期しない、望ましくないかもしれません。)
セス・ジョンソン

9

以下を使用できます。

git submodule | awk '{ print $2 }'

1
これは、stackoverflow.com / a / 23490756/895245と同じ出力を生成するようですが、より短いです。
Ciro Santilli郝海东冠状病六四事件法轮功

反対投票。このコマンドは、有効なサブモジュール名test (master)である(スペースと括弧が続く名前)というサブモジュールiEで失敗するため、危険です。gitはprints moduleまたはのいずれかであるため、コマンドも修正できませんmodule (branch)。また、このコマンドは磁器ではないため、さらに悪いことに、コマンドの出力は将来予告なしに変更される可能性があります。
ティノ

7

私はこれを使います:

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

出力(パス+バージョン):

tools/deploy_utils (0.2.4)

このバージョンの欠点は、遅いことです。各サブモジュールで何らかのステータスチェックを行っているようです。おそらく私のマシンのサブモジュールごとに1秒近くです。そのため、多くのサブモジュールを含むプロジェクトでは、これは適切な解決策ではありません。または、スクリプトなどから実行する必要がある場合は
コリンDベネット14

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(後などgit submodule init、質問を参照)。
ティノ

5

git config設定ファイルを指定できます。
そして、.gitmodules ある設定ファイル。

したがって、「スペースを区切りコマンドとして区切り文字として使用する」の助けを借りて:

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

宣言されたサブモジュールごとに1つ、パスのみがリストされます。

以下のようティノは指摘するコメントで

  • これは、スペースを含むサブモジュールでは失敗します
  • サブモジュールパスには、次のように改行が含まれる場合があります。

    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 ...
これには、理解する最新のbashが必要read -d ''です(間のスペースを忘れないでください-d and '')。


うーん...「もっと良い方法があるに違いない」が私の直接の考えです
arcseldon

とにかく、bashプロファイルなどでそのコマンドのエイリアスを作成できると思います。
arcseldon 2016年

これは、スペースを含むサブモジュールでは失敗します。また、パスには改行(git submodule add https://github.com/hilbix/bashy.git "sub module"; git mv 'sub module' $'sub\nmodule')が含まれる場合があることに注意してください。受け入れられた回答に対する私のコメントを参照してください。
ティノ

@ティノ良い点。より見やすくするために、回答にコメントを含めました。
VonC 2018

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-regexpawktrsed、...代わりにゼロバイトがバックに分け、それを渡しますgit config --get。これは、サブモジュール内の改行、スペース、その他の特殊文字(Unicodeなど)の問題を回避するため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バージョン

$ 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または空想の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 2007
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.