What is the difference between “git submodule foreach git pull origin master” and “git pull origin master --recurse-submodules”

匿名 (未验证) 提交于 2019-12-03 03:10:03

问题:

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.

回答1:

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)

For git pull, this option has been introduced in (commit 7dce19d, Nov. 2010, git 1.7.4-rc0):

fetch/pull: Add the --recurse-submodules option

Until now you had to call "git submodule update" (without -N|--no-fetch option) 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 "gitk") after fetching or pulling new commits in the superproject and is an obstacle for implementing recursive checkout of submodules.
Also "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 .git/config of 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:

fetch/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 (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 293c232, 12 Sep 2016)



回答2:

What is the point of using --recurse-submodules?

--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.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!