4

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

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

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

4

2 回答 2

6

概括

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

长格式和解释

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

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

从 Git 2.0 版本开始,您可以使用伪名称-来引用标准输入,因此:

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 ,子模块的名称是设置为P的条目。该子模块的 URL 为.submodule.name.pathsubmodule.name.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' \
    '$1 ~ /submodule\..*\.path/ && $2 == path { split($1, a, "."); print a[2] }'

(尽管当您将其放入可以读取树以查找 gitlink 的东西时,您可能需要 Python 或类似的东西)。

于 2016-12-19T07:12:42.423 回答
0

由于 git v2.x 您可以使用以下内容:

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

解释

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

注意

  • 子模块的远程名称应该是“origin”(由 git 设置为默认远程名称)
  • 子模块之前应该已经初始化(例如,通过在超级项目中执行git submodule update --init
于 2019-08-05T13:28:18.783 回答