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.

  • File from non-active change list is modified
  • Git: continuous integration without rebase chaos
  • Git pre-push hooks
  • The latest commit gone after hard reset
  • Git repository lost its remote branches?
  • Checking when a selection of files have changed
  • 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.

  • copy a git repository without revisions (without .git and .gitingore) from a remote server
  • What should go in a default git config file?
  • Grabbing git log from other folder
  • Parsing the output of “git submodule foreach 'git status'”
  • In Git, can I view all commits from a branch merge?
  • Does git pull always create a merge commit?
  • 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)

    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)

    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.

    Git Baby is a git and github fan, let's start git clone.