git 获取远程子模块的管道命令

git plumbing command to get submodule remote

我正在只读文件系统中使用 git 管道和镜像(因此是裸露的)存储库。

我可以看到带有 git ls-tree 的子模块的存在。我可以推断出它们的 name/path 和 SHA1,但我找不到远程获取子模块的方法。

信息就在某处;如果我克隆回购协议,git submodule init 成功。 (制作克隆对于正常使用来说太昂贵了,特别是对于非常大的存储库。)我怎样才能直接访问子模块远程?

总结

git config --blob HEAD:.gitmodules --list 开始,然后从那里开始。这需要 Git 版本 >= 1.8.4。请注意 HEAD 可以是任何版本。

长格式和解释

评论变成了答案,大部分答案由 OP 提供。 :-) 此外,我们还有以下自引用定义:superproject 是一个包含子模块的 Git 存储库,而 submodule(有时也称为 子项目 )是由超级项目控制的 Git 存储库。子模块本身通常在特定提交时保持检出(即,作为 "detached HEAD"),尽管现在有特殊情况,您可以指示 Git 将子模块切换到命名分支。如果一个子模块有更多的子模块,"outer" 子模块是 "inner" 子模块的超级项目,所以 super/sub 都是相对的。

子模块——存储库 URLs 及其检出路径——由超级项目根目录中名为 .gitmodules 的文件提供。因此,在裸存储库中,您将获取或提取 .gitmodules 文件。此文件格式为配置文件,因此可通过 git config --file.

读取

从Git 2.0版开始,可以使用伪名-来引用stdin,所以:

git show HEAD:.gitmodules | git config --file - --list

将以熟悉的格式转储内容。 (如果您的 Git 变体早于此,但您有 /dev/stdin,您可以在此处阅读 /dev/stdin。)

事实证明,还有一种更简单的方法:git config 可以,因为 Git 版本 1.8.4,直接从存储库中读取一个 blob。 blob 标识符是 git rev-parse 可接受的任何内容,它不仅可以处理分支名称或提交 ID,甚至可以处理后续路径名。 (此代码专门用于子模块处理:参见 commit 1bc888193e1044db317a45b9a4c8d2b87b998f40。)

详情

给定子模块路径 P,子模块的名称是具有 submodule.<em>name</em>.path 的条目 设置为 P。该子模块的 URL 是 submodule.<em>name</em>.url.

可以使用 git config --get-regexp 搜索所需的名称。然而,这充其量也很烦人,因为我们必须引用作为正则表达式元字符的路径名组件,最常见的是 .:

$ git config --blob HEAD:.gitmodules \
    --get-regexp 'submodule\..*\.path' 'some/dir\.name/path'
submodule.foo.path some/dir.name/path

所以使用 --list 转储配置并使用其他东西提取有趣的字段可能更有意义。例如:

git config --blob HEAD:.gitmodules --list | \
    awk -F= -vpath='some/dir.name/path' \
    ' ~ /submodule\..*\.path/ &&  == path { split(, a, "."); print a[2] }'

(虽然当你把它放入可以读取树的东西中寻找 gitlinks 时,你可能想要 Python 或类似的东西)。

因为 git v2.x 您可以使用以下内容:

git config --file .gitmodules --get-regexp 'submodule\.\S+\.path' | 
    awk '{print }' |
    xargs -i git -C {} remote get-url origin

说明

  • 第一个和第二个命令return所有子模块的相对路径
  • 第三条命令在子模块的目录中执行 git remote 并获取 url 它们的来源

注意

  • 子模块的远程名称应为 "origin"(由 git 设置为默认远程名称)
  • 子模块之前应该已经初始化(例如,通过在超级项目中执行 git submodule update --init