What is the difference between “git submodule foreach git pull origin master” and “git pull origin master –recurse-submodules”
I have a dotfiles repository where all my vim plugins are stored as submodules so they are easy to update when they have changes. I thought these two commands did the same thing, but I noticed this must not be the case.
I knew I had updates to pull down in several submodules so I ran
git pull origin master --recurse-submodules from the root of the parent repository. It appeared to iterate over each submodule, but only fetch updates from their origin repositories.
When I ran
git submodule foreach git pull origin master then it actually ran
git pull origin master within each repository, doing both the fetch and the merge.
What is the point of using
--recurse-submodules? I’m a little confused about what it’s actually trying to do and Google was a bit cryptic with what I found. I thought maybe you smart folks would have a simpler explanation.
2 Solutions collect form web for “What is the difference between “git submodule foreach git pull origin master” and “git pull origin master –recurse-submodules””
That option is mainly for fetching all the submodule commits, not just pulling one specific branch like master, for reasons detailed in the two following commits:
(note there is a bug fixed in Git 2.11, see at the end of this answer)
git pull, this option has been introduced in (commit 7dce19d, Nov. 2010, git 1.7.4-rc0):
pull: Add the
Until now you had to call “
git submodule update” (without
-N|--no-fetchoption) or something like “
git submodule foreach git fetch” to fetch new commits in populated submodules from their remote.
This could lead to “
(commits not present)” messages in the output of
git diff --submodule” (which is used by “
git gui” and “
fetching or pulling new commits in the superproject and is an obstacle for
implementing recursive checkout of submodules.
git submodule update” cannot fetch changes when disconnected, so it was very easy to forget to fetch the submodule changes before disconnecting only to discover later that they are needed.
This patch adds the “
--recurse-submodules” option to recursively fetch
each populated submodule from the url configured in the
submodule at the end of each “
git fetch” or during “
git pull” in the
superproject. The submodule paths are taken from the index.
Commit 88a2197 (March 2011, git 1.7.5-rc1) explains a bit more:
pull: recurse into submodules when necessary
To be able to access all commits of populated submodules referenced by the
superproject, it is sufficient to only then let “
git fetch” recurse into a
submodule when the new commits fetched in the superproject record new
commits for it.
- Having these commits present is extremely useful when using the “
--submodule” option to “
git diff“ (which is what “
git gui” and
gitk” do since 1.6.6), as all submodule commits needed for creating a
descriptive output can be accessed.
- Also merging submodule commits (added in 1.7.3) depends on the submodule commits in question being present to work.
- Last but not least this enables disconnected operation when using
submodules, as all commits necessary for a successful “
git submodule update -N” will have been fetched automatically.
So we choose this mode as the default for fetch and pull.
git pull origin master --recurse-submodules git submodule foreach git pull origin master
The first one should pull, not just fetch, and be equivalent to the second one. Maybe this is a parameter order issue:
git pull --recurse-submodules origin master
However, it is not the recommended way to update submodule for a given branch: see the following section.
Note that the right way to actually pull from master would be to register the master branch to the submodule, making that submodule tracking master:
git config -f .gitmodules submodule.<path>.branch <branch>
Then a simple
git submodule update --remote --recursive would be enough.
And the branch to fetch/pull is recorded in the parent repo (in the
.gitmodules file), so you don’t even have to remember which branch you want your submodule to update against.
Update Git 2.11 (Q4 2011)
Having a submodule whose “
.git” repository is somehow corrupt
caused a few commands that recurse into submodules loop forever.
See commit 10f5c52 (01 Sep 2016) by Junio C Hamano (
(Merged by Junio C Hamano —
gitster — in commit 293c232, 12 Sep 2016)
What is the point of using
--recurse-submodules will do submodules within a submodule (it’s actually recursive).
git submodule foreach git pull origin master will not, it will only do the immediate submodules.