【问题标题】:git: reset submodule branch to remote taggit:将子模块分支重置为远程标签
【发布时间】:2020-10-05 12:49:45
【问题描述】:

我有一个带有标签的主模块,我在主模块下有一些子模块。 我想将主模块重置为特定标签(例如“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

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

问候

【问题讨论】:

    标签: git tags


    【解决方案1】:

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

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

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

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

    标签仅在主模块中...

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

    ...所以它是子模块的远程标签

    不,不是。没有“远程标签”之类的东西。标签只是提交哈希 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 的索引现在保存为路径名和哈希 ID 对,例如 path/to/submodulefeedc0ffee...,可能希望子模块提交到 git checkout(作为分离的 HEAD)。

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

    git submodule update checkout
    

    或:

    git submodule update --recursive checkout
    

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


    1--all 选项到git fetch 表示从所有远程获取。这在您使用它的上下文中有点意义,因为每个遥控器都可能有一些标签集,这将使您的 Git 将其标签的 all 复制到一个大规模的标签联合。如果存在冲突——如果远程 A 说标签 v1.2.3 应该表示 deadbeef 而远程 B 说标签 v1.2.3 应该表示 feedf00d,那么一般来说,无论您先选择哪个“获胜”。

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

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

    【讨论】:

    • 非常感谢您冗长而详细的回答。我在上面的问题中忘记了一个信息。我希望子模块也位于主分支上。它们应该在属于超级项目标签的提交的主分支上。
    • @crappidy:有多个存储库,所以你应该限定这个:which master?如果您希望子模块存储库将git fetch 运行到它自己的远程,然后使用其更新的origin/master,那么面向用户的Git 命令要做......好吧,不是完全 这个,是@ 987654353@。 --remote 等价于 git submodule foreachgit fetch,然后是 git checkout <hash>,其中 <hash> 来自指定的分支,但分支不一定是 master:它来自 @ 987654360@ 超级项目中的设置。
    • 查看the git submodule documentation 了解所有血腥细节,并注意在解码复杂子模块配置的每一层时往往需要重复阅读。
    【解决方案2】:
    git submodule update --init --recursive
    git submodule foreach git checkout -f -B master
    

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

    【讨论】:

      猜你喜欢
      • 2019-02-26
      • 2013-11-27
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      • 2015-10-01
      • 1970-01-01
      • 2023-03-04
      • 2018-12-22
      相关资源
      最近更新 更多