Why doesn't `git checkout` automatically do `git submodule update --recursive`? [duplicate]
Asked Answered
L

3

59

Someone please help me understand submodules in git. I know they are getting a lot of bashing around the internet but since I assume the git developers are smart people there must a reason for the current behavior - and maybe a way to work around my problem.

So, I have a project and some submodules. The project have different branches, like:

  • MyApp_version2
  • MyApp_version3
  • MyApp_version4
  • MyApp_liteversion
  • MyApp_development

My submodules doesn't update that often (maybe once a week) so I'm fine with them not being attached to the head of the submodule repository automatically.

However, when I check out an old branch - because I need to fix a bug in an old version of the software - I also need to update the submodules.

Why do I need to do this?

I would expect git to work like svn. When I commit my work in my main repo I would expect git to think something along these lines: "OK, he wants to commit his work now. I can see the submodules are currently at revision abc so when he at some point in the future get's back to this commit he probably wants the submodules at the same revision again."

I can not see a single case where you would want the submodules to stay at the current revision while you go back 3 years in your main repository. However, there must be a reason for this implementation, right?

I would really like to hear if any of you know the thoughts behind this, but in any case I would really like a solution. Is there a way to tell git: "I want to commit this work with these submodules. If I at some point go back to this state I want the submodules to be checked out at the correct version as well."

Example for clarification

My main repository is an application which needs to use SSL, and I find a SSL library (libSSL) I add as a submodule.

On Oct. 31 2010 I create a commit in my main repository (2fd4e1) while the submodule points to libSSL version 3 (c67a2d).

Time passes, libSSl gets updated to version 34, I adapt my code, life it good.

On May 14 2013 I create a new commit (28fced) and submodule points to the most recent version of libSSL (849ee1).

However, if I check out 2fd4e1 my submodule will stay at 849ee1 even though the original commit was created with c67a2d. Git knows I made the original commit with c67a2d and I don't see how you could possibly want a another submodule than the one the original commit was created with.

Liles answered 11/3, 2014 at 14:3 Comment(5)
Perhaps you're only checking out different commits to review how certain things looked at different points - would you really want to wait for all the submodules to update every single time? Although, I would agree it might be nice to have an option to git checkout to make it also do the appropriate submodule things, I wouldn't want it enabled by default...Missie
You can create an alias for Git that will automatically update submodules. See https://mcmap.net/q/12715/-is-there-a-way-to-make-git-pull-automatically-update-submodulesVookles
I had trouble discovering how to do an submodule inclusive checkout. The title of this question solved my problem. I wonder why this is so obscure.Osteomyelitis
I believe all the submodule * commands should be replaced by other existing commands, e.g.: git submodule init foo should probably be analogous to git clone foo if foo is not an url. And if the user want to do anything more complex than clone or checkout he can just cd foo and call git normally. This would probably make all these obscure commands intuitive and easy to use.Skaggs
git checout is a local operation. In contrast, git submodule update (which is what --recurse-submodules implies) can involve fetch and even clone. So doing this by default would fundamentally change the character of checkout. I guess that is why the designers decided against it. You can change the default behavior with git config --global submodule.recurse true.Monied
K
57

It sounds like what you want to do can be achieved from git v2.13 on with the new --recurse-submodules option of git checkout. From the git-checkout manual page:

--[no-]recurse-submodules

Using --recurse-submodules will update the content of all initialized submodules according to the commit recorded in the superproject. If local modifications in a submodule would be overwritten the checkout will fail unless -f is used. If nothing (or --no-recurse-submodules) is used, the work trees of submodules will not be updated.

See also this relevant git mailing list message about that new option.

Kermit answered 13/6, 2017 at 19:27 Comment(2)
You can set this to be the default behavior as of 2.14.0 with git config --global submodule.recurse trueHypophosphite
^ @Hypophosphite that should be its own answer!Mansard
P
6

Simplify your shortcut/aliases by using :

alias checkitout='git checkout $1; git submodule update --recursive'
Prepossession answered 21/2, 2019 at 16:8 Comment(0)
G
-4

You basically want git to do all operations recursively and automatically for all submodules. Which is probably trivial in a centralized client-server model like svn.

But git is distributed. Your submodule may come from a totally different URL, with a totally different protocol. Most probably you don't event have push access to the submodule's origin repo, while you do for the main repo.

So there cannot be a recursive push.

Therefore the designers probably decided to avoid automatic recursion for submodules everywhere. Which is consistent, but a huge amount of pain.

So much so, that in a certain project we completely abandoned them and used subtree merges instead.

Gimmal answered 11/3, 2014 at 14:41 Comment(3)
Not at all! I added an example. This has nothing to do with pushing to a remote repository. The issue is: Let's say I develop Firefox. In firefox version 3 I use libSSL version 1 (as a submodule). Later, in firefox 24 I use libSSL version 4. If I checkout Firefox version 3 again, why does libSSL stay at version 4 when git knows it should be version 1. FIrefox version 3 doesn't know anything about libSSL version 4 since it was released years after the original commit was createdLiles
Again. No automatic recursion into submodules. Ever. For consistency. Probably. Maybe. Who knows.Gimmal
the question is about checkout, there's no reason you can't do recursvive checkout. Of course push would be impossible. Question is why you have to do "git checkout someoldrev && git submodule update" because there's almost never a reason to leave the prior submodule.Loggins

© 2022 - 2024 — McMap. All rights reserved.