克隆带有嵌套子模块的 repo 不起作用

cloning a repo with nested submodules does not work

我有多个单独的 git 存储库,其中没有子模块。任务是 assemble 这些存储库的层次结构树,并用它在用户之间共享。这对于 'subtree' 或 'subrepo' 方案来说是微不足道的,但它似乎不适用于 'submodules'。尝试子模块的原因是 git 在 nfs 系统上的性能很慢。以我为例,结帐需要 2 个多小时

我正在尝试创建一个包含子模块的共享存储库。到目前为止,第一次克隆尝试失败了。这是测试用例:

 mkdir m1 ; cd m1 ; git init ; date > a.txt ; git add --all ; git commit -m added ; cd -
 mkdir m2 ; cd m2 ; git init ; date > b.txt ; git add --all ; git commit -m added ; cd -
 mkdir m3 ; cd m3 ; git init ; date > c.txt ; git add --all ; git commit -m added ; cd -
 mkdir msub; cd msub; git init; date > d.txt; git add --all; git commit -m added;
 git submodule add `realpath ../m1` m1
 cd m1
 git submodule add `realpath ../../m2` m2
 git submodule add `realpath ../../m3` m3
 git commit -m 'added submodules'
 cd ..
 git commit -m 'added a submodule'
 cd ..
 git clone --recursive msub msub1

因此,它创建了带有单个顶级子模块 (m1) 的 msub1。

在其他情况下,我在克隆第一个子模块后遇到与此类似的致命错误。

fatal: git upload-pack: not our ref 89434ad65c1e697bfa311cd0260dfe1997985e65
fatal: remote error: upload-pack: not our ref 89434ad65c1e697bfa311cd0260dfe1997985e65
Fetched in submodule path 'soc', but it did not contain 89434ad65c1e697bfa311cd0260dfe1997985e65. Direct fetching of that commit failed.

我尝试直接将子模块添加到 'm1',这似乎改善了这种情况,但我不能用真正的 repos 做到这一点。

所以,想要的方案好像不行。有办法解决吗?

"not our ref" 响应通常意味着您的服务器配置为限制通过 ID 直接获取对象,并且没有合适的引用允许获取该对象。

Git 提供了三个选项来控制您是否可以获取任意对象 ID:一个允许获取 Git 有权访问的任意对象,一个允许获取从引用,还有一个还允许从隐藏的引用中获取可访问的对象。大多数服务器提供商选择禁用其中一个或多个,这通常意味着您只能在 non-hidden 引用(即分支或标记)指向它时请求对象 ID。

"not our ref" 消息表示您正尝试通过用于子模块的对象 ID 获取对象,但由于上述原因服务器不允许这样做。如果您正在使用 Bitbucket Server 的引用缓存,这也可能意味着服务器缓存了过时的数据;在这种情况下,如果您需要某些东西正常工作,您应该禁用引用缓存。

您可以做几件事。如果您需要检查任意修订的能力,您可以创建一个指向它的分支。或者,如果你的子模块不需要特定的修订版,而只需要最新的分支,你可以设置 submodule.<name>.branch 选项(参见 man gitmodules)然后你将始终检查最新的分支.如果您使用的是 self-hosted 服务器,则可以将 uploadpack.allowAnySHA1InWant 设置为 true。最后,您可以手动获取子模块(可能使用 git submodule foreach),通常会有您想要的修订。

git submodule add `realpath ../m1` m1
cd m1
git submodule add `realpath ../../m2` m2
git submodule add `realpath ../../m3` m3

您在这里修改了 m1 的本地克隆副本,但没有将更改推回原始 m1

git commit -m 'added submodules'
cd ..
git commit -m 'added a submodule'

您忘记在子模块中添加更改。

cd ..
git clone --recursive msub msub1

gitmsub 克隆到 msub1 时,它会尝试从其原始目录而不是 msub/m1 克隆 m1。很简单,因为在top-level .gitmodules 中有通往原始m1 的路径。而原来的 m1 没有子模块。

要修复整个工作流程,您需要:

  • git add 在提交之前更改了 m1
  • cd m1 && git push origin master(好吧,push 到 non-bare 回购是行不通的,所以 cd 到原来的 pull 代替)。

所以整个固定脚本是:

#! /bin/sh
set -e

mkdir m1 ; cd m1 ; git init ; date > a.txt ; git add --all ; git commit -m added ; cd -
mkdir m2 ; cd m2 ; git init ; date > b.txt ; git add --all ; git commit -m added ; cd -
mkdir m3 ; cd m3 ; git init ; date > c.txt ; git add --all ; git commit -m added ; cd -
mkdir msub; cd msub; git init; date > d.txt; git add --all; git commit -m added;
git submodule add `realpath ../m1` m1
cd m1
git submodule add `realpath ../../m2` m2
git submodule add `realpath ../../m3` m3
git commit -m 'added submodules'
cd ../../m1
git pull ../msub/m1 master
cd ../msub
git add m1
git commit -m 'added a submodule'
cd ..
git clone --recursive msub msub1