【问题标题】:Why doesn't `git checkout` automatically do `git submodule update --recursive`? [duplicate]为什么`git checkout`不会自动执行`git submodule update --recursive`? [复制]
【发布时间】:2014-03-11 14:03:38
【问题描述】:

请有人帮我理解 git 中的子模块。我知道他们在互联网上受到了很多抨击,但既然我认为 git 开发人员是聪明人,那么当前的行为肯定是有原因的——也许是解决我的问题的方法。

所以,我有一个项目和一些子模块。该项目有不同的分支,例如:

  • MyApp_version2
  • MyApp_version3
  • MyApp_version4
  • MyApp_liteversion
  • MyApp_development

我的子模块不会经常更新(可能一周一次),所以我对它们很好 not being attached to the head of the submodule repository automatically

但是,当我签出旧分支时 - 因为我需要修复旧版本软件中的错误 - 我还需要更新子模块。

为什么我需要这样做?

我希望 git 能像 svn 一样工作。当我在我的主仓库中提交我的工作时,我希望 git 会按照这些思路思考:“好的,他现在想提交他的工作。我可以看到子模块目前处于修订版 abc 所以当他在未来的某个时候回到这个提交,他可能想要再次使用相同版本的子模块。”

我看不到任何情况下您希望子模块保持当前版本,而您在主存储库中返回 3 年。不过,这种实现肯定是有原因的吧?

我真的很想听听你们中是否有人知道这背后的想法,但无论如何我真的很想要一个解决方案。有没有办法告诉 git:“我想用这些子模块提交这项工作。如果我在某个时候回到这个状态,我希望子模块也能以正确的版本签出。”

说明示例

我的主存储库是一个需要使用 SSL 的应用程序,我找到了一个 SSL 库 (libSSL) 作为子模块添加。

2010 年 10 月 31 日,我在主存储库 (2fd4e1) 中创建了一个提交,而子模块指向 libSSL 版本 3 (c67a2d)。

时间过去了,libSSl 更新到版本 34,我调整了我的代码,过得很好。

2013 年 5 月 14 日,我创建了一个新提交 (28fced),子模块指向最新版本的 libSSL (849ee1)。

但是,如果我签出 2fd4e1,我的子模块将保持在 849ee1,即使原始提交是使用 c67a2d 创建的。 Git 知道我使用 c67a2d 进行了原始提交,但我看不出你怎么可能想要另一个子模块而不是创建原始提交的那个子模块。

【问题讨论】:

  • 也许您只是检查不同的提交以查看某些事物在不同点上的表现 - 您真的要等待所有子模块每次都更新吗?虽然,我同意给git checkout 提供一个选项以使其也执行适当的子模块操作可能会很好,但我不希望它默认启用...
  • 您可以为 Git 创建一个别名,它会自动更新子模块。见stackoverflow.com/a/4611550/994153
  • 我在发现如何进行包含子模块的结帐时遇到了麻烦。这个问题的标题解决了我的问题。我想知道为什么它如此晦涩。
  • 我相信所有子模块 * 命令都应该被其他现有命令替换,例如:如果 foo 不是 url,git submodule init foo 应该类似于git clone foo。如果用户想做比克隆或结帐更复杂的事情,他可以cd foo 并正常调用 git。这可能会使所有这些晦涩的命令变得直观且易于使用。

标签: git git-submodules


【解决方案1】:

听起来你想做的事情可以从 git v2.13 开始使用git checkout 的新--recurse-submodules 选项来实现。来自git-checkout 手册页:

--[no-]递归子模块

使用 --recurse-submodules 会根据超级项目中记录的提交更新所有初始化子模块的内容。如果子模块中的本地修改将被覆盖,则检出将失败,除非使用 -f。如果不使用(或 --no-recurse-submodules),则不会更新子模块的工作树。

另请参阅relevant git mailing list message about that new option

【讨论】:

  • 您可以使用git config --global submodule.recurse true将其设置为2.14.0的默认行为
  • ^ @codehearts 这应该是它自己的答案!
【解决方案2】:

使用 :

简化您的快捷方式/别名
alias checkitout='git checkout $1; git submodule update --recursive'

【讨论】:

    【解决方案3】:

    您基本上希望 git 对所有子模块递归地自动执行所有操作。这在像 svn 这样的集中式客户端-服务器模型中可能是微不足道的。

    但是 git 是分布式的。您的子模块可能来自完全不同的 URL,具有完全不同的协议。很可能您没有 push 访问子模块的 origin 存储库,而您却可以访问主存储库。

    所以不能递归推送。

    因此,设计者可能决定避免对所有子模块进行自动递归。这是一致的,但是非常痛苦。

    以至于在某个项目中我们完全放弃了它们并使用了子树合并。

    【讨论】:

    • 一点也不!我添加了一个例子。这与推送到远程存储库无关。问题是:假设我开发 Firefox。在 Firefox 版本 3 中,我使用 libSSL 版本 1(作为子模块)。后来,在 Firefox 24 中,我使用了 libSSL 版本 4。如果我再次签出 Firefox 版本 3,为什么当 git 知道它应该是版本 1 时,libSSL 仍停留在版本 4。FIrefox 版本 3 对 libSSL 版本 4 一无所知,因为它是在创建原始提交数年后发布
    • 再次。没有自动递归到子模块。曾经。为了一致性。大概。也许。谁知道呢。
    • 问题是关于结帐,没有理由不能进行递归结帐。当然推是不可能的。问题是为什么你必须做“git checkout someoldrev && git submodule update”,因为几乎没有理由离开之前的子模块。
    猜你喜欢
    • 2018-01-31
    • 2014-03-18
    • 2021-01-06
    • 2023-02-26
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    相关资源
    最近更新 更多