git submodule update可以获取子模块中的标签吗?

22

我有一个使用子模块的git仓库,我想要将其指向一个带注释的标签,但是当我执行 git submodule update 时,新标签并没有被获取。我可以切换到子模块并在那里执行 git fetch --tags 命令来获取新标签,但我真的想从外部完成所有这些操作,因为它是脚本化的。

我在git文档中找不到任何建议让 git submodule update 包括标签的方法(我的git版本为1.7.3.5)。

显然还有另一种可能性——将子模块指向标签所指向的提交而不是标签本身,但这似乎不太简洁。

有没有办法让 git submodule update 包括标签?

4个回答

23
晚来的回答,但我惊讶地发现没有人提到 git submodule foreach。这基本上是我解决你遇到的确切问题的方法:
git submodule foreach --recursive 'git fetch --tags'
git submodule update --recursive

--recursive标志用于递归进入子模块。


13

git submodule是一个shell脚本实现的,因此很容易看到它在做什么——如果你使用的是打包版本,则可能位于/usr/lib/git-core/git-submodule。基本上,如果主项目树中存储的对象名称(SHA1sum)与子模块中检出的版本不匹配,它会在子模块中运行git-fetch,如Koraktor指出的

git fetch的文档 (kernel.org正在关闭时使用man git-fetch)指出它应该获取指向已下载对象的每个标记,并且已下载的对象将包括获取的每个分支的所有祖先提交。这意味着对git submodule update执行后,您没有获取到所有相关的标签,这让我感到惊讶。

如果你真正想要的是尝试设置新的子模块版本并提交结果,那么我认为git submodule update不是你想要的工具——它只是确保子模块处于正确的版本,以基于当前主项目提交。相反,你应该做这样的事情:

( cd my-submodule && \
      git fetch && \
      git fetch --tags && \
      git checkout my-tag )
git add my-submodule
git commit -m 'Update the submodule to the "my-tag" version' my-submodule

(我添加了额外的 git fetch --tags以防万一你的标签没有指向一个已经下载的提交。)

显然还有另一种可能性 - 将子模块指向标签所指向的提交而不是标签本身,但这似乎不够简洁。

嗯,主项目树中存储的唯一内容是提交对象的哈希值,因此即使存在一个命令说“将我的子模块设置为该子模块中的标签 my-tag”,它最终也会存储与该标签相对应的哈希值...


感谢您的所有帮助 - 看起来我的问题是我想要的提交不在任何分支的历史记录中。 您认为为什么 git submodule update 只执行 git fetch 而不是 git fetch --tags 有一个很好的理由吗? 在那里添加 git fetch --tags 将解决未来遇到此问题的任何人的问题。 当 kernel.org 恢复正常后,我会找到报告此问题的地方。 - Duncan Parkes
2
@DuncanParkes 从Git 1.9/2.0(2014年第一季度)开始,git fetch --tags就足够了(不需要添加git fetch):https://dev59.com/13M_5IYBdhLWcg3w2W9g#20608181 - VonC

5

git submodule update如果你的子模块是最新的,将不会获取任何内容。因此这可能是一个误解。

git submodule update将把存储库中子模块的工作目录内容更新到定义的状态(即检出在存储库中已定义的子模块提交)。

更好的方法是进入子模块所在的目录(它本身就是一个 Git 存储库)并简单地运行git fetch --tags,然后运行git checkout some-tag。之后,子模块已经更新到some-tag,你可以为提交进行暂存。


你说得对,我确实有这种误解,但这不是我的主要问题。我的主要问题是,当我将子模块设置为指向标签提交时,当我切换到其他地方并执行git submodule update时,它会抱怨找不到提交。我已经决定将其指向标签提交的父级。 - Duncan Parkes

0

你可以编写脚本,这样你就可以执行 (cd path-to-submod && git fetch)

将命令放在括号中会将环境放在子shell中,这意味着你不必回到之前的目录。

希望这能帮到你。


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