git: 将子模块分支重置为远程标记

git: reset submodule branch to remote tag

我有一个带标签的主模块,我在主模块下有一些子模块。 我想将主模块重置为特定标签(例如“v2.11.0”)并将子模块也重置为该标签。该标签仅在主模块中,因此它是子模块的远程标签。

git fetch --all --tags
git reset --hard tags/v2.11.0
git submodule foreach --recursive git checkout -B master
git submodule foreach --recursive git reset --hard tags/v2.11.0

将主模块重置为标签有效。但是将子模块重置为远程标签不适用于上面的代码。 你知道怎么回事吗?

问候

标签是提交的名称。因此,超级项目中的 tags/v2.11.0 标记是超级项目中特定提交的名称,即代表数字或哈希 ID。所以这个:

git fetch --all --tags
git reset --hard tags/v2.11.0

有点奇怪,1但不完全疯狂。

不过,每个子模块都是一个 单独的 Git 存储库 。那个单独的 Git 存储库可能有也可能没有标签 v2.11.0;如果它确实有这样的标签,该标签将代表存在于其他 Git 存储库中的一些 other 提交:

the tag is only in the main module ...

我推测这意味着每个子模块都没有这样的标签。

... so it is a remote tag for the submodules

不,不是。没有“远程标签”这样的东西。标签只是提交哈希 ID 的名称,在任何给定的存储库中,您要么有标签,要么没有。如果你没有标签,你就没有那个名字。其他一些存储库的标签是 那个存储库 .

中某个哈希 ID 的名称

Git 是关于提交的。每个提交都有一个唯一的哈希 ID。这就是您使用 Git 所做的很多事情:您可以 使用 分支名称,例如 masterdevelop 或其他名称,或标签名字像 v2.11.0,但你实际上是在告诉 Git 让我提交 b0ff0cab1e...。 (完整的哈希 ID 又长又难看,但你可以通过以下方式找到它:

git rev-parse tags/v2.11.0

例如。)

使用超级项目的正常方法是在超级项目提交中为每个子模块提供正确的哈希 ID。这是提交本身的一部分,作为一个 Git 调用 gitlink 的实体。检查超级项目提交结果将该 gitlink 放入超级项目 Git 的索引中。 Git 的索引现在作为 path-name-and-hash-ID 对,如 path/to/submodulefeedc0ffee...,人们可能希望子模块提交到 git checkout(作为分离头)。

如果你想让每个子模块在那个提交时成为一个分离的 HEAD,你现在 运行:

git submodule update checkout

或:

git submodule update --recursive checkout

使子模块本身递归地检查它自己的任何子模块。


1git fetch--all 选项意味着 从所有遥控器获取 。这在您使用它的上下文中有点意义,因为每个遥控器都可以有一些标签集,这将使您的 Git 复制 all 他们的标签,变成一个巨大的 tag-union。如果存在冲突——如果远程 A 说标签 v1.2.3 应该表示 deadbeef,而远程 B 说标签 v1.2.3 应该表示 feedf00d,则您先选择哪个“获胜” ",一般来说。

git reset --hard 很可能是错误的做法。如果您已经处于分离的 HEAD,这就像对给定标记执行 git checkout,副作用是丢弃所有尚未提交的工作。如果您在分支名称上,这会更改该分支名称中存储的哈希 ID,这可能是错误的。

总体而言,运行 git fetch --tags 可能更明智,没有 --all,从 current 远程获取,或者选择一个特定的遥控器来信任;或者如果只有一个遥控器,git fetch --tags 将使用那个遥控器,然后 --all 是不必要的。然后,完成后,使用 git checkout tags/v2.11.0git switch --detach tags/v2.11.0,如果有未提交的工作,它们会抱怨。

git submodule update --init --recursive
git submodule foreach git checkout -f -B master

这会将子模块设置为属于超级项目标签的提交。之后主分支将在此提交上检出。