【问题标题】:cloning a repo with nested submodules does not work使用嵌套子模块克隆 repo 不起作用
【发布时间】:2019-06-28 21:49:39
【问题描述】:

我有多个单独的 git 存储库,其中没有子模块。任务是组装这些存储库的分层树,并使用它在用户之间共享。这对于“subtree”或“subrepo”方案来说是微不足道的,但它似乎不适用于“submodules”。尝试子模块的原因是 nfs 系统上的 git 性能缓慢。在我的情况下,结帐需要 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 来做到这一点。

因此,所需的方案似乎不起作用。有办法解决吗?

【问题讨论】:

  • 由于管理子模块的痛苦,我们很久以前就放弃了子模块。在我看来,您可以通过发布包含一系列 git clone 命令的脚本来提供相同的功能,也许可以单独选择。
  • @paxdiablo 谢谢,它尝试过并拒绝了这个想法,因为它太不稳定了。它必须依赖分层的 .gitignores 并且需要大量的脚本。拥有庞大的客户群,它不会运作良好。所以,我希望子模块能让它更易于管理。

标签: git git-submodules


【解决方案1】:

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

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

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

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

【讨论】:

  • 这一切都发生在本地克隆上,不涉及可配置的服务器。但我会尝试配置。谢谢。
【解决方案2】:
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 时,它会尝试从其原始目录中克隆m1,而不是从msub/m1。仅仅是因为在顶级.gitmodules 中有指向原始m1 的路径。而原来的m1 没有子模块。

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

  • git add 在提交之前更改了 m1
  • cd m1 && git push origin master(好吧,push 到非裸仓库是行不通的,所以 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

【讨论】:

  • 谢谢。我得到了图片。看起来子模块流违反了 git 哲学。它不会克隆组装好的仓库,而是克隆各个子模块的原始仓库并在途中重建树。除非在原始子模块存储库中推送,否则在原始树的子模块中所做的任何提交都不会反映在其克隆中。无赖!
  • .gitmodules 包含原始 URL,而不是本地克隆的 URL。这样的本地克隆通常根本没有公共 URL,因此将更改推送到原始 URL 是发布更改的唯一方法。如果您想克隆包含所有供应商子存储库的整个存储库,请使用git subtree
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
  • 2022-07-08
  • 2014-10-01
  • 1970-01-01
相关资源
最近更新 更多