如何确保 Git 子模块正在检出特定的标签?

4

这是我的情况:

我们正在尝试将一个项目转换为使用子模块。由于之前在测试时,子模块只是引用了develop分支。现在我想将所有模块从develop分支转换为指向master分支上的特定发布标签。其中一个模块还需要更改远程URL,因此我按照这些说明修改了.gitmodule文件并更新了远程url和分支;我甚至在根目录中执行了说需要git submodule update --init --recursive --remote的命令。然后,我按照这些说明进入每个子模块,检出各自的发行标签。

这似乎很好用,但是当我运行git status时,它抱怨有一个游离的头(我想这是预期的,因为我在分支上检出了标签而不是实际的分支本身)。然而,我随后git add了所有子模块,并提交到了本地仓库,但我还没有推送,因为我不确定子模块是否指向所需的标签。

那么,我怎么能验证当同事克隆此项目时,它将拉取子模块到我希望设置的发布标签所指的状态?我试图查看.gitmodule文件,希望看到“tag”值,但没有。我还检查了各个.git/module/sub_module_path/config文件,在这里也没有看到任何内容。

我怎样才能确保子模块将在所需的标签处被克隆?

1个回答

12

子模块从来没有指向标签(这在一般情况下是不可能的,正如你所发现的:检出标签名只会导致一个脱离HEAD状态)。请注意,标签名只是特定提交的人类可读名称。每次使用标签时,您都可以将其解析为正确的提交哈希 ID,然后直接使用哈希 ID。

就Git而言,子模块的目的是处于分离HEAD模式。 超级项目Git说要使用哪个提交。 超级项目提交 - 即当前在超级项目中实际检出的提交 - 列出了每个子模块的原始提交哈希 ID。 然后超级项目 Git 会执行以下操作:

git -C path/to/submodule checkout <hash>

使用超级项目提供的哈希值。因此,这与标签“同样好”:我们只是在超级项目中存储了哈希ID,而不是在子模块中存储它在标签名称中。

这意味着我们可以使用一个我们无法控制的子模块。我们无法在该子模块中创建新的标签名称,但我们可以git checkout任何我们喜欢的提交,然后在超级项目中创建一个新的提交,其中说检出哈希中的提交path/to/submodule。然后我们就完成了。

唯一剩下的问题,真正的问题是:

  • 好吧,我们有一个超级项目,还有一些提交a123456,当检出该提交并运行git submodule update --init时,将检出该标签。

  • 但现在我们将在超级项目中进行一些新的和改进的提交。

  • 在至少其中一次新的改进提交中 - 比如下一个版本发布 - 我们希望特定的子模块sub/mod位于v3.1415926(它是提交feedc0ffee),而不是旧的糟糕的v1.4142136(提交badcab1e)。那么我们如何确保这些新的提交在超级项目中使用哈希ID feedc0ffee

答案是:只需在子项目中检出所需的提交,例如:

git -C sub/mod checkout v3.1415926

然后在超级项目中运行git add

git add sub/mod

那么这到底是什么?

git submodule update --init --recursive --remote
这里的--remote参数的意思是:我已经在某个地方存储了一些名称。对于每个子模块,执行git -C path/to/submodule fetch(这是--remote的第一部分),然后用存储的name使用git -C path/to/submodule checkoutname来检出名称。 这是--remote的第二部分。递归地执行此操作,即如果子模块本身是更多子模块的超级项目,则也要对这些子模块执行此操作。 这是--recursive部分。

这是一个相当强大的功能,由多个部分组成:

  • name存储在哪里?您如何知道每个子模块使用的名称?
  • 谁控制name解析为哈希ID?我们在子模块中运行git fetch,因此是子模块的远程!
  • 我们将获得什么哈希ID?这取决于该子模块中git fetch更新的任何名称(如果有)。

所有这些问题都有答案,但只有“名称存储在哪里”的问题应该(或者可以)在此处回答。该名称来自于:

  • 如果在超级项目的.git/config中设置了它,则为超级项目的.git/config;或者
  • 如果在超级项目的.gitmodules中设置了它,则为超级项目的.gitmodules;或者
  • master

除了硬编码的master之外,这些都有进一步的控制选项:您可以使用git configgit submodule更新.git/config和/或.gitmodules

这一切都相当复杂,而且还非常微妙,因为很容易让某人在自己的.git/config中设置它并忘记更新.gitmodules。例如,如果你不是这个人,那么你将得到错误的名称!出于这个原因,我通常建议手动完成所有操作,如果您是选择哪个子模块放在哪个提交上的人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接