为什么`git checkout`不会自动执行`git submodule update --recursive`?

Mar*_*kus 34 git git-submodules

有人请帮我理解git中的子模块.我知道他们在互联网上受到了很多抨击但是因为我认为git开发人员是聪明人,所以当前行为必须有理由 - 也许是一种解决我的问题的方法.

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

  • MyApp_version2
  • MyApp_version3
  • MyApp_version4
  • MyApp_liteversion
  • MyApp_development

我的子模块经常不会更新(可能每周一次)所以我很好,他们没有自动附加到子模块库的头部.

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

为什么我需要这样做?

我希望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,即使原始提交是使用c67a2d创建的,我的子模块也将保持在849ee1.Git知道我使用c67a2d进行了原始提交,但我没有看到你怎么可能想要另一个子模块而不是创建原始提交的子模块.

小智 26

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

- [无糖]递归-子模块

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

另请参阅有关该新选项的相关git邮件列表消息.

  • 您可以将此设置为2.14.0的默认行为,使用`git config --global submodule.recurse true` (13认同)
  • ^ @codehearts 这应该是它自己的答案! (2认同)

小智 6

通过使用简化您的快捷方式/别名:

alias checkitout='git checkout $1; git submodule update --recursive'
Run Code Online (Sandbox Code Playgroud)


SzG*_*SzG -4

您基本上希望 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 的任何信息,因为它是在原始提交创建多年后发布 (7认同)
  • 问题是关于结帐的,没有理由不能进行递归结帐。当然,推动是不可能的。问题是为什么你必须执行“git checkout someoldrev && git submodule update”,因为几乎没有理由离开先前的子模块。 (2认同)