繁体   English   中英

指定git子模块的分支?

[英]Specify branch for a git submodule?

我已经在我的git存储库中添加了一个git子模块,它工作正常。

在我的“父”存储库中,我创建了一个功能分支: myfeature ,需要对子模块进行一些更改。 但是我不想影响使用相同子模块的其他团队。 因此,我在子模块存储库submodule-feature上创建了相应的功能分支,并进行了一些更改。 然后,我已经从子模块目录添加/提交更改,然后在父存储库的根目录中添加了更改。

但是,当我在“父”存储库上切换回master时,子模块仍位于submodule-feature功能分支上。 那不是我所期望的。 因为现在当我在master上运行测试时,它们失败了,因为我在submodule-feature分支的submodule中引入了一些重大更改。

不可能将子模块的分支锁定到父存储库分支吗?

编辑:基于: 添加Git子模块时,如何指定分支/标签?

看起来我可以在.gitmodules为子模块存储库指定一个分支

[submodule "mysubmodule"]
    path = mysubmodule
    url = https://bla.git
    branch = submodule-feature

并在jenkins中添加以下其他git行为:

在此处输入图片说明

和:

在此处输入图片说明

myfeature分支上运行构建时,它将克隆/签出submodule-feature分支。

但是,在本地工作时,这当然需要一些手动步骤。 但是从CI方面来看,它非常容易实现。

简短的答案通常只是 “不”。 尽管詹金斯(Jenkins)有一个复选框,但在此处使用它可能不是一个好主意-是否使用,取决于谁控制名称到ID的映射。 其他CI系统可能具有也可能没有相似的复选框。 要了解我在这里得到的内容,请继续阅读。

子模块的理念是,超级项目由其子模块控制。 我认为,这部分内容对于任何人都不会感到惊讶或反对。 但关键在于上层项目控制每个子模块的方式 这部分确实让人感到惊讶,原因很简单。 一般来说,这是对Git存储库的基本误解。

人们认为,Git存储库中重要的是分支 ,或更确切地说,是masterdevelop等分支名称 那根本不是真的。 这些分支在大多数情况下实际上无关紧要 对于人类而言,这些分支名称具有巨大的,压倒一切的目的。 对于Git来说,它们提供的服务几乎都是平凡的,其他名称也可以很好地覆盖它,例如标签名称,远程跟踪名称或refs/stashHEAD@{17} 1个

在Git中, 提交 (而不是分支名称(也不是标签名称,也没有任何其他名称))是核心的基本内容。 承诺就是Git的存在理由 没有提交,Git将不起作用。 对于提交,Git很有用。 提交实际上是由其哈希ID标识的,其真实名称是那些丑陋的大字符串,如b5101f929789889c2e536d915698f58d5c5c6b7a 愚蠢的事物,例如易读的名称,例如masterdevelop ,对于弱者,生物……人类都是如此。

当然,我们作为弱者, 就像我们的名字一样。 因此,我们在存储库中使用它们。 但是,当我们拥有一个像超级项目一样的存储库来控制另一个存储库(例如子模块)时,在这种情况下, 就没有人参与了 因此,Git使用提交ID来控制在每个子模块中提取哪个提交哈希ID。

因此,这就是惊奇的源头-除非您了解了Git的来源,这一点也就不足为奇了。 当您让超级项目选择子模块提交时,超级项目通过哈希ID选择子模块提交。 任何分支名称都不相关。 哈希ID准确且始终正确。 分公司名称是草率的,他们移动 ,有目的的,从提交承诺,随着时间的推移。 一个提交哈希ID可以具有零个或多个直接指向它的分支名称,或者可以通过提交图到达它。 2

超级项目中进行的每个提交都记录了子模块预期已检出的确切子模块哈希ID。 因此,当您在超级项目中git checkout某些提交时,通常应该立即让每个子模块通过在超级项目中指定的哈希ID进行自己的单独git checkout 3

请记住,每个子模块都是其自己的Git存储库,因此它具有自己的HEAD ,索引和工作树。 辅助模块索引记录被检出到子模块的工作树中的文件和HEAD在每个子模块中分离的头的方式,记录当前签出的哈希ID提交。 选择此哈希ID的是超级项目的Git,方法是将其存储在超级项目中的提交中,而子模块的Git负责签出此特定的提交。 在此过程中,没有任何地方提到分支名称。 分支名称无关!


1名称的In-Git功能除了为弱者提供了拐杖外,还可以防止物体被垃圾收集 如果无法通过某些名称访问对象,则该对象很容易受到收集的影响。 由于大多数提交大多是链接在一起的,因此一个名称倾向于保护存储库中的大多数提交。 另见脚注2。

2有关可达性的更多信息,请参见“像(a)Git一样思考”

3默认情况下,这实际上不会自动发生。 您必须在配置中使用git checkout --recurse-submodules或设置submodule.recurse 根据您正在执行的操作(尤其是如果您尝试更新子模块),自动进行操作既方便又非常烦人。


那么,为什么可以首先设置分支名称?

如您所述, .gitmodules文件可以记录分支名称。 您也可以将其复制到.git/config (如果同时设置了.git/config设置, .gitmodules覆盖.gitmodules设置。)但是通常,子模块根本不在分支上; 如上所述,它已进入分离HEAD模式。 那么,什么好这个部门的名字吗?

第一个但有些不令人满意的答案是:一点都不好。 大多数操作只是不使用它。

第二个更令人满意的答案是: 一些特殊用途的操作确实使用它。 具体来说,如果您正在更新超级项目,并且想要进行一个新的超级项目提交来记录新的子模块哈希ID,则需要某种方式来挑选新的子模块提交哈希ID。 解决此问题的方法有多种,名称是为其中一种方式设计的。

例如,假设子模块是一个不受您控制的公共存储库(也许在GitHub上)。 您只需要使用它。 也许每年两次,或者一天可能有50000次,那么有人会更新GitHub存储库。 他们将新的提交提交给master或他们的develop或诸如此类,破坏了您使用的一堆东西,但这不是问题,因为您的超级项目不会 “让我获得他们最新的masterdevelop提交” ”,您的超级项目会说“让我提交a123456... ”,并且a123456...永远都是相同的提交,直到宇宙热死,或者我们停止使用Git,以先发生的为准。 但是,在破坏了您自己的一堆软件的同时,他们引入了您必须具备的一项很酷的新功能。

此时,您想要做的就是拥有Git,它也控制着您的子模块,告诉您的子模块Git: 去找我他们最新的masterdevelop或我以前记录的名字。 由于您确实记录了该名称,因此可以使用以下命令引导Git指示子模块执行该操作:

git submodule update --remote

(您可以在其中添加一些额外的标志,例如--checkout--rebase--merge ,但我不打算讨论这些详细信息,我现在假设您仅直接使用它们的最新标志) 。 您的Git拥有您的子模块Git运行git fetch ,然后根据您的子模块的分支名称副本将您的子模块存储库更新为最新提交。 (现在至少涉及三个Git,即您的超级项目,您的子模块和GitHub上的Git存储库。因此,这有点复杂。无论他们是谁,他们可能都有一个或多个Git存储库用于控制GitHub,但是至少您不必处理它。嗯,还没有。)

现在您的子模块已更新,您必须修复自己的代码,以使用新功能并处理它们对已使用的东西所做的所有重大更改。 因此,您需要做所有这些,在本地计算机上构建和测试软件,而且都不需要在这里使用CI,并且可以正常工作。 现在,您可以git add的更改,并git add子模块的名称。 现在,您的超级项目的索引和工作树都匹配了,您可以在超级项目中进行新的提交了。

请注意, git add submodule-path仅告诉您的Git在索引中记录子模块Git存储库中当前检出的提交的哈希ID 再说一次, 分支名称(如果有)是不相关的。 子模块存储库是在分支master还是develop ,或者具有分离的HEAD都无关紧要; 重要的是原始提交哈希ID

现在,您运行git commit进行新的提交。 索引中的哈希ID是您通过运行git add submodule-path记录的提交哈希ID,它控制哪个提交将被视为子模块的“正确”提交。 在这种情况下 ,您之前运行git submodule update --remote的事实选择了该提交ID。 但是唯一重要的是索引中的哈希ID,该ID进入新提交。

现在,您可以git push在超级项目Git存储库中所做的提交git push提交到其他系统,例如CI系统。 它可以git checkout此提交,并且此提交记录正确的子模块哈希ID。

如何将其与CI系统结合使用,以便CI系统选择哈希ID?

显然,这要困难得多,取决于您的CI系统是否将其作为功能提供,这可能会更难。

现在,您已经知道这是如何构造的,您已经拥有了所需的工具。 您必须具有CI系统更新(或获取)超级项目的克隆。 该超级项目的.gitmodules文件中还包含CI系统必须克隆的所有子模块的URL和路径。 它可能包含也可能不包含这些子模块的某些分支名称。

CI系统现在必须指示某些Git(超级项目Git或子模块Git),以使子模块Git git checkout一些已经记录为正确提交的提交以外的提交,以便超级项目不再使用CI提交系统已签出。 换句话说,您将不再构建提交给CI系统的内容 您正在使用CI系统从身体部位中构建新的科学怪人的怪物:提交时的主体,但未直接指定的其他提交中提取的肢体相反,您允许其他人指定哪个提交去了。 您给CI系统起了一个名字,并告诉它询问他们(无论他们是谁)该名称到达的哈希ID。

您的CI系统现在可以尝试构建和使用此科学怪人的怪物。 如果一切运作良好,CI系统将需要作出新的承诺,这是很多喜欢你的承诺,除了它记录了他们身上得到了-whoever他们,再一次,有问题的辅助模块中的散列ID。 除非您的CI系统也是您的主要存储库的真实来源,否则您的CI系统现在可能还需要将此提交推送到某个地方的权限。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM