Search code examples
gitgit-submodules

`git submodule update --remote` vs `git pull --recurse-submodule` vs `git submodule foreach git pull origin main`


There are three commands that (as far as I know) can be used to update a git submodule to its latest version.

  • git submodule update --remote --recursive
  • git pull --recurse-submodule
  • git submodule foreach git pull origin main

What is the difference between the three commands? There are already some questions on StackOverflow regarding this, but most of them explain this using concepts I do not understand (rebase and branch HEADs). I'm hoping someone can explain this to me in a simple way. I'm using submodules in my project to link it to other projects, and I would like to know what the difference between the three commands is. All three work for me locally, and I would like to know which one is the most appropriate one for me to use.

I would also like to know what the two options on these commands do. --recurse-submodule is quite self-evident. git pull would only pull the main repo otherwise. But what does the --remote option on git submodule update do? What about the --recursive option? I'm assuming the --recursive option is to target submodules inside submodules, but I'm not able to figure out what --remote does.

I realize that git submodule update will initially clone the repos mentioned in .gitmodules, but I'm asking about what happens when a version of the repo already exists. Does it update that version to the latest commit or not?

What happens when I run this in a CI/CD tool like GitHub Actions? Only the .gitmodules file will be present, so will git submodule update update that to the latest commits or will it just clone the submodule repos, which is kind of pointless since the "local" cache will be cleared once the workflow finishes running.


Solution

  • git submodule update --remote --recursive

    This command updates all submodules (and their submodules because of --recursive) to use the latest commit on the default branch of their repository (e.g. main, master). You can change the branch per submodule in .gitmodules. To quote the official documentation:

    You can, however, set this to something different if you want. For example, if you want to have the DbConnector submodule track that repository’s “stable” branch, you can set it in either your .gitmodules file (so everyone else also tracks it), or just in your local .git/config file. Let’s set it in the .gitmodules file:

    $ git config -f .gitmodules submodule.DbConnector.branch stable

    If --remote wasn't used, it'd go for specific commits already recorded for each submodule by the main repository.

    git pull --recurse-submodule

    This works similarly to git submodule update --recursive, except it of course also pulls changes for the main repository.

    git submodule foreach git pull origin main

    This one updates each submodule (but not their submodules) to use latest commit on the main branch. It's not really safe to use as different submodules could use different branch names, e.g. master. I wouldn't recommend ever using it over git submodule update --remote.