【问题标题】:How do I get `git clone --recursive` to recreate submodules' remotes and branches?如何让 `git clone --recursive` 重新创建子模块的遥控器和分支?
【发布时间】:2012-05-26 19:44:01
【问题描述】:

我有一个包含几个子模块的项目。其中许多是从 GitHub fork 克隆的,我为我的自定义模块添加了一个分支。典型的设置是这样的:

在本地文件夹中:MyProject1/Frameworks/SomeAmazingRepo/

$ git branch -vva
*my-fork                       123456 [my-fork/my-fork] Latest commit msg from fork
master                         abcdef [origin/master] Latest commit msg from original repo
remotes/my-fork/my-fork        123456 [my-fork/my-fork] Latest commit msg from fork
remotes/my-fork/master         abcdef [origin/master] Latest commit msg from original repo
remotes/origin/HEAD            -> origin/master
remotes/origin/master          abcdef [origin/master] Latest commit msg from original repo

$ git remote -v
my-fork                        git@github.com:MyUser/SomeAmazingRepo.git (fetch)
my-fork                        git@github.com:MyUser/SomeAmazingRepo.git (push)
origin                         git://github.com/OriginalOwner/SomeAmazingRepo.git (fetch)
origin                         git://github.com/OriginalOwner/SomeAmazingRepo.git (push)

git clone --recursive 我的项目开始了一个新的衍生项目,当它开始递归时,它吐出一个错误,声称它找不到这些存储库的存储提交。经检查,似乎尚未添加遥控器,并且分支在 master 中保留(空)...

在本地文件夹中:MyProject2/Frameworks/SomeAmazingRepo/

$ git branch -vva
*master                        abcdef [origin/master] Latest commit msg from original repo
remotes/origin/HEAD            -> origin/master
remotes/origin/master          abcdef [origin/master] Latest commit msg from original repo

$ git remote -v
origin                         git://github.com/OriginalOwner/SomeAmazingRepo.git (fetch)
origin                         git://github.com/OriginalOwner/SomeAmazingRepo.git (push)

唯一的补救办法是手动将遥控器添加到所有存储库(非常乏味)。

在上面有两个跟踪分支但只有一个远程(origin => my github fork)的情况下存在类似的问题。在这种情况下,它会找到提交并将其签出,但无法重新创建跟踪分支,留下一个“悬空”提交......非常可怕,因为它没有警告你!

如何克隆我的项目,以便它可靠地重新创建子模块的远程和分支?

【问题讨论】:

  • 你不能先确保所有 trackinf 分支都到位,首先是你的父 repo,然后通过 git submodule foreach,对于每个子模块,使用单行 like this one
  • “trackinf 分支”是什么意思?此外,我不一定希望所有遥控器都作为分支检出。问题是git clone --recursive 根本没有重新创建子模块的(非原始)遥控器。我觉得我在这里遗漏了一些细微差别,但我不能完全指出它......
  • 对不起,这是一个错字:“跟踪分支”(stackoverflow.com/questions/4693588/…)。显然不是你所缺少的。
  • 实际上,我在最后简要提到的第二种情况是,源代码库中的子模块只有一个远程主模块(可以很好地克隆),但已签出跟踪分支。在这种情况下,git clone--recursive 将 HEAD 设置为分支的提交(它成功找到,因为它是 remote=origin 的一部分)但未能重新创建分支本身,这意味着它是悬空的。也许这是一个不同的问题,但我想我的问题只是“git clone --recursive 坏了还是只是我?!?”或“为什么使用子模块进行克隆如此不可靠,我该如何解决?”
  • 好的,关于“不可靠性”,我想我有一个很好的解释。请参阅下面我答案的最后一部分。

标签: git git-submodules git-clone cloning git-remote


【解决方案1】:

git clone --recursive 等价于git submodule update --init --recursive

git submodule update 只会签出记录的 SHA1(记录在父仓库中):

更新已注册的子模块,即克隆缺少的子模块并检查包含存储库的索引中指定的提交。
这将使子模块 HEAD 分离

2012:因此在子模块中找不到活动分支是常态。
git submodule foreach 'git checkout master' 至少可以设置主分支(如果您确定所有记录的 SHA1 都应该是每个子模块的“主”分支的一部分。


2013-2014:您可以配置您的 .gitmodules 文件,以便在您的子模块中指定要结帐的分支
见“How do I update my git submodules from specific branches?

cd /path/to/your/parent/repo
git config -f .gitmodules submodule.<path>.branch <branch>

您在子模块中本地添加的任何远程,例如my-fork,根本不会记录在父存储库中。
因此,当您再次克隆该父 repo 时,它将初始化和更新 .gitmodules 文件中记录的子模块(您可以 change that address,但只有 一个 与每个子模块相关联)。
如果您有其他远程地址要关联到每个子模块,则需要一个脚本来自动化该过程。

如“True nature of submodule”中所述,子模块主要用于记录/访问历史中的固定点。
您可以直接在子模块中进行开发,但您需要去那里创建正确的分支和/或添加正确的遥控器。

它吐出一个错误,声称找不到这些存储库的存储提交。

每次在子模块中提交时,您需要:

  • 将其推送到关联的远程(即记录在父仓库的.gitmodules 中的远程)
  • 返回父 repo 并提交父 repo。

但是:

如果您已推送到“my-fork”,而该子模块的关联远程仓库不是my-fork”...那么下一个克隆将无法签出子模块提交。


2014 年 8 月更新 (Git 2.1)

commit 9393ae7Matthew Chen (charlesmchen)

子模块:文档“sync --recursive

git submodule sync”命令支持--recursive 标志,但文档没有提到这一点。
该标志很有用,例如在子模块的子模块中更改远程时。


更新 Git 2.23(2019 年第三季度)

您还可以考虑git clone --recurse-submodule --remote-submodules:它将使用已在其跟踪分支而不是其 gitlink 父 repo SHA1 签出的子模块进行克隆。

【讨论】:

  • 对。我想我开始明白了。出现问题是因为我最初从 RepoA 添加了我的子模块,然后将其分叉到 Github RepoB,然后 将其添加为子模块中的新远程,而 ParentRepo 对此一无所知。相反,我应该更新 ParentRepo's(?) .gitmodulesremote/origin 设置为 RepoB 并运行 git submodule sync (link #3) 以使一切井井有条?
  • 对于场景 #2,我只需要确保我的子模块位于 branch=master 并运行git submodule foreach... 手动去检查所有内容。 ParentRepo 无法确定其子模块所在的分支似乎有点漏洞。理想情况下,人们会想要一个完全克隆 repo、子模块和所有状态的命令。在第一个场景中,我可以看到基本原理 - 我已经在子模块中设置了我没有告诉父级的功能 - 但就分支而言,所有信息都包含在子模块的源代码库中......功能请求?
  • 谢谢你的好答案。我希望这可以避免其他人头疼。
  • @HariKaramSingh 我很高兴你成功了。我确认您的git submodule sync 使用情况。至于分支,不要忘记它们可以随时重命名/删除。提交 SHA1 很重要。带有子模块的“配置”构建是提交的集合,而不是像“svn 外部”那样,“某些分支的最新版本”:git 子模块和 svn 外部根本不同(并且不兼容):stackoverflow.com/questions/3131912/…跨度>
猜你喜欢
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 2012-01-06
  • 2016-11-08
  • 2019-09-02
  • 1970-01-01
相关资源
最近更新 更多