Merge branch 'jl/fetch-submodule-recursive'
authorJunio C Hamano <gitster@pobox.com>
Thu, 16 Dec 2010 20:57:15 +0000 (12:57 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 16 Dec 2010 20:57:15 +0000 (12:57 -0800)
* jl/fetch-submodule-recursive:
fetch_populated_submodules(): document dynamic allocation
Submodules: Add the "fetchRecurseSubmodules" config option
Add the 'fetch.recurseSubmodules' config setting
fetch/pull: Add the --recurse-submodules option

Conflicts:
builtin/fetch.c

1  2 
Documentation/config.txt
Documentation/fetch-options.txt
builtin/fetch.c
git-pull.sh
diff --combined Documentation/config.txt
index 488a27cd03b99362c5abbba8884c46e1704055ec,bb17432ea748332678fb62fbee0ac36c27aaef7e..bf9479e4eb49c971b9502d072dd9be18c838ab21
@@@ -374,15 -374,6 +374,15 @@@ core.warnAmbiguousRefs:
        If true, git will warn you if the ref name you passed it is ambiguous
        and might match multiple refs in the .git/refs/ tree. True by default.
  
 +core.abbrevguard::
 +      Even though git makes sure that it uses enough hexdigits to show
 +      an abbreviated object name unambiguously, as more objects are
 +      added to the repository over time, a short name that used to be
 +      unique will stop being unique.  Git uses this many extra hexdigits
 +      that are more than necessary to make the object name currently
 +      unique, in the hope that its output will stay unique a bit longer.
 +      Defaults to 0.
 +
  core.compression::
        An integer -1..9, indicating a default compression level.
        -1 is the zlib default. 0 means no compression,
@@@ -459,21 -450,6 +459,21 @@@ core.excludesfile:
        to the value of `$HOME` and "{tilde}user/" to the specified user's
        home directory.  See linkgit:gitignore[5].
  
 +core.askpass::
 +      Some commands (e.g. svn and http interfaces) that interactively
 +      ask for a password can be told to use an external program given
 +      via the value of this variable. Can be overridden by the 'GIT_ASKPASS'
 +      environment variable. If not set, fall back to the value of the
 +      'SSH_ASKPASS' environment variable or, failing that, a simple password
 +      prompt. The external program shall be given a suitable prompt as
 +      command line argument and write the password on its STDOUT.
 +
 +core.attributesfile::
 +      In addition to '.gitattributes' (per-directory) and
 +      '.git/info/attributes', git looks into this file for attributes
 +      (see linkgit:gitattributes[5]). Path expansions are made the same
 +      way as for `core.excludesfile`.
 +
  core.editor::
        Commands such as `commit` and `tag` that lets you edit
        messages by launching an editor uses the value of this
@@@ -522,9 -498,6 +522,9 @@@ core.whitespace:
    part of the line terminator, i.e. with it, `trailing-space`
    does not trigger if the character before such a carriage-return
    is not a whitespace (not enabled by default).
 +* `tabwidth=<n>` tells how many character positions a tab occupies; this
 +  is relevant for `indent-with-non-tab` and when git fixes `tab-in-indent`
 +  errors. The default tab width is 8. Allowed values are 1 to 63.
  
  core.fsyncobjectfiles::
        This boolean will enable 'fsync()' when writing object files.
@@@ -566,13 -539,9 +566,13 @@@ core.sparseCheckout:
        linkgit:git-read-tree[1] for more information.
  
  add.ignore-errors::
 +add.ignoreErrors::
        Tells 'git add' to continue adding files when some files cannot be
        added due to indexing errors. Equivalent to the '--ignore-errors'
 -      option of linkgit:git-add[1].
 +      option of linkgit:git-add[1].  Older versions of git accept only
 +      `add.ignore-errors`, which does not follow the usual naming
 +      convention for configuration variables.  Newer versions of git
 +      honor `add.ignoreErrors` as well.
  
  alias.*::
        Command aliases for the linkgit:git[1] command wrapper - e.g.
@@@ -617,9 -586,8 +617,9 @@@ branch.autosetupmerge:
        this behavior can be chosen per-branch using the `--track`
        and `--no-track` options. The valid settings are: `false` -- no
        automatic setup is done; `true` -- automatic setup is done when the
 -      starting point is a remote branch; `always` -- automatic setup is
 -      done when the starting point is either a local branch or remote
 +      starting point is a remote-tracking branch; `always` --
 +      automatic setup is done when the starting point is either a
 +      local branch or remote-tracking
        branch. This option defaults to true.
  
  branch.autosetuprebase::
        When `local`, rebase is set to true for tracked branches of
        other local branches.
        When `remote`, rebase is set to true for tracked branches of
 -      remote branches.
 +      remote-tracking branches.
        When `always`, rebase will be set to true for all tracking
        branches.
        See "branch.autosetupmerge" for details on how to set up a
@@@ -697,7 -665,7 +697,7 @@@ color.branch:
  color.branch.<slot>::
        Use customized color for branch coloration. `<slot>` is one of
        `current` (the current branch), `local` (a local branch),
 -      `remote` (a tracking branch in refs/remotes/), `plain` (other
 +      `remote` (a remote-tracking branch in refs/remotes/), `plain` (other
        refs).
  +
  The value for these configuration variables is a list of colors (at most
@@@ -725,7 -693,7 +725,7 @@@ color.diff.<slot>:
  color.decorate.<slot>::
        Use customized color for 'git log --decorate' output.  `<slot>` is one
        of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local
 -      branches, remote tracking branches, tags, stash and HEAD, respectively.
 +      branches, remote-tracking branches, tags, stash and HEAD, respectively.
  
  color.grep::
        When set to `always`, always highlight matches.  When `false` (or
@@@ -790,8 -758,7 +790,8 @@@ color.status.<slot>:
        one of `header` (the header text of the status message),
        `added` or `updated` (files which are added but not committed),
        `changed` (files which are changed but not added in the index),
 -      `untracked` (files which are not tracked by git), or
 +      `untracked` (files which are not tracked by git),
 +      `branch` (the current branch), or
        `nobranch` (the color the 'no branch' warning is shown in, defaulting
        to red). The values of these variables may be specified as in
        color.branch.<slot>.
@@@ -837,6 -804,8 +837,6 @@@ diff.mnemonicprefix:
        standard "a/" and "b/" depending on what is being compared.  When
        this configuration is in effect, reverse diff output also swaps
        the order of the prefixes:
 -diff.noprefix::
 -      If set, 'git diff' does not show any source or destination prefix.
  `git diff`;;
        compares the (i)ndex and the (w)ork tree;
  `git diff HEAD`;;
  `git diff --no-index a b`;;
        compares two non-git things (1) and (2).
  
 +diff.noprefix::
 +      If set, 'git diff' does not show any source or destination prefix.
 +
  diff.renameLimit::
        The number of files to consider when performing the copy/rename
        detection; equivalent to the 'git diff' option '-l'.
@@@ -863,8 -829,7 +863,8 @@@ diff.renames:
  diff.ignoreSubmodules::
        Sets the default value of --ignore-submodules. Note that this
        affects only 'git diff' Porcelain, and not lower level 'diff'
 -      commands such as 'git diff-files'.
 +      commands such as 'git diff-files'. 'git checkout' also honors
 +      this setting when reporting uncommitted changes.
  
  diff.suppressBlankEmpty::
        A boolean to inhibit the standard behavior of printing a space
@@@ -897,6 -862,11 +897,11 @@@ diff.wordRegex:
        sequences that match the regular expression are "words", all other
        characters are *ignorable* whitespace.
  
+ fetch.recurseSubmodules::
+       A boolean value which changes the behavior for fetch and pull, the
+       default is to not recursively fetch populated sumodules unless
+       configured otherwise.
  fetch.unpackLimit::
        If the number of objects fetched over the git native
        transfer is below this
@@@ -1120,7 -1090,7 +1125,7 @@@ gui.newbranchtemplate:
        linkgit:git-gui[1].
  
  gui.pruneduringfetch::
 -      "true" if linkgit:git-gui[1] should prune tracking branches when
 +      "true" if linkgit:git-gui[1] should prune remote-tracking branches when
        performing a fetch. The default value is "false".
  
  gui.trustmtime::
@@@ -1340,11 -1310,10 +1345,11 @@@ interactive.singlekey:
        ignored if portable keystroke input is not available.
  
  log.date::
 -      Set default date-time mode for the log command. Setting log.date
 -      value is similar to using 'git log'\'s --date option. The value is one of the
 -      following alternatives: {relative,local,default,iso,rfc,short}.
 -      See linkgit:git-log[1].
 +      Set the default date-time mode for the 'log' command.
 +      Setting a value for log.date is similar to using 'git log''s
 +      `\--date` option.  Possible values are `relative`, `local`,
 +      `default`, `iso`, `rfc`, and `short`; see linkgit:git-log[1]
 +      for details.
  
  log.decorate::
        Print out the ref names of any commits that are shown by the log
@@@ -1490,10 -1459,6 +1495,10 @@@ pack.compression:
        not set,  defaults to -1, the zlib default, which is "a default
        compromise between speed and compression (currently equivalent
        to level 6)."
 ++
 +Note that changing the compression level will not automatically recompress
 +all existing objects. You can force recompression by passing the -F option
 +to linkgit:git-repack[1].
  
  pack.deltaCacheSize::
        The maximum memory in bytes used for caching deltas in
@@@ -1549,13 -1514,11 +1554,13 @@@ pack.packSizeLimit:
        supported.
  
  pager.<cmd>::
 -      Allows turning on or off pagination of the output of a
 -      particular git subcommand when writing to a tty.  If
 -      `\--paginate` or `\--no-pager` is specified on the command line,
 -      it takes precedence over this option.  To disable pagination for
 -      all commands, set `core.pager` or `GIT_PAGER` to `cat`.
 +      If the value is boolean, turns on or off pagination of the
 +      output of a particular git subcommand when writing to a tty.
 +      Otherwise, turns on pagination for the subcommand using the
 +      pager specified by the value of `pager.<cmd>`.  If `\--paginate`
 +      or `\--no-pager` is specified on the command line, it takes
 +      precedence over this option.  To disable pagination for all
 +      commands, set `core.pager` or `GIT_PAGER` to `cat`.
  
  pretty.<name>::
        Alias for a --pretty= format string, as specified in
@@@ -1580,20 -1543,17 +1585,20 @@@ push.default:
        no refspec is implied by any of the options given on the command
        line. Possible values are:
  +
 -* `nothing` do not push anything.
 -* `matching` push all matching branches.
 +* `nothing` do not push anything.
 +* `matching` push all matching branches.
    All branches having the same name in both ends are considered to be
    matching. This is the default.
 -* `tracking` push the current branch to its upstream branch.
 -* `current` push the current branch to a branch of the same name.
 +* `tracking` push the current branch to its upstream branch.
 +* `current` push the current branch to a branch of the same name.
  
  rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
        rebase. False by default.
  
 +rebase.autosquash::
 +      If set to true enable '--autosquash' option by default.
 +
  receive.autogc::
        By default, git-receive-pack will run "git-gc --auto" after
        receiving data from git-push and updating refs.  You can stop
@@@ -1688,9 -1648,7 +1693,9 @@@ remote.<name>.tagopt:
        Setting this value to \--no-tags disables automatic tag following when
        fetching from remote <name>. Setting it to \--tags will fetch every
        tag from remote <name>, even if they are not reachable from remote
 -      branch heads.
 +      branch heads. Passing these flags directly to linkgit:git-fetch[1] can
 +      override this setting. See options \--tags and \--no-tags of
 +      linkgit:git-fetch[1].
  
  remote.<name>.vcs::
        Setting this to a value <vcs> will cause git to interact with
@@@ -1757,7 -1715,6 +1762,7 @@@ sendemail.to:
  sendemail.smtpdomain::
  sendemail.smtpserver::
  sendemail.smtpserverport::
 +sendemail.smtpserveroption::
  sendemail.smtpuser::
  sendemail.thread::
  sendemail.validate::
@@@ -1786,9 -1743,9 +1791,9 @@@ status.showUntrackedFiles:
        the untracked files. Possible values are:
  +
  --
 -      - 'no'     - Show no untracked files
 -      - 'normal' - Shows untracked files and directories
 -      - 'all'    - Shows also individual files in untracked directories.
 +* `no` - Show no untracked files.
 +* `normal` - Show untracked files and directories.
 +* `all` - Show also individual files in untracked directories.
  --
  +
  If this variable is not specified, it defaults to 'normal'.
@@@ -1811,6 -1768,13 +1816,13 @@@ submodule.<name>.update:
        URL and other values found in the `.gitmodules` file.  See
        linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
  
+ submodule.<name>.fetchRecurseSubmodules::
+       This option can be used to enable/disable recursive fetching of this
+       submodule. It can be overriden by using the --[no-]recurse-submodules
+       command line option to "git fetch" and "git pull".
+       This setting will override that from in the linkgit:gitmodules[5]
+       file.
  submodule.<name>.ignore::
        Defines under what circumstances "git status" and the diff family show
        a submodule as modified. When set to "all", it will never be considered
index 678675ccdf06dbe0e97d80bb3fbc8985155d2fc0,99e72d912488a73fffc816b2a006c453ab8b0e02..695696da1b6e78639014388e1d4ac8bf09a0e12d
@@@ -36,7 -36,7 +36,7 @@@ ifndef::git-pull[
  
  -p::
  --prune::
 -      After fetching, remove any remote tracking branches which
 +      After fetching, remove any remote-tracking branches which
        no longer exist on the remote.
  endif::git-pull[]
  
@@@ -49,11 -49,8 +49,11 @@@ ifndef::git-pull[
  endif::git-pull[]
        By default, tags that point at objects that are downloaded
        from the remote repository are fetched and stored locally.
 -      This option disables this automatic tag following.
 +      This option disables this automatic tag following. The default
 +      behavior for a remote may be specified with the remote.<name>.tagopt
 +      setting. See linkgit:git-config[1].
  
 +ifndef::git-pull[]
  -t::
  --tags::
        Most of the tags are fetched automatically as branch
        objects reachable from the branch heads that are being
        tracked will not be fetched by this mechanism.  This
        flag lets all tags and their associated objects be
 -      downloaded.
 +      downloaded. The default behavior for a remote may be
 +      specified with the remote.<name>.tagopt setting. See
 +      linkgit:git-config[1].
 +endif::git-pull[]
+ --[no-]recurse-submodules::
+       This option controls if new commits of all populated submodules should
+       be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
+ ifndef::git-pull[]
+ --submodule-prefix=<path>::
+       Prepend <path> to paths printed in informative messages
+       such as "Fetching submodule foo".  This option is used
+       internally when recursing over submodules.
+ endif::git-pull[]
  
  -u::
  --update-head-ok::
diff --combined builtin/fetch.c
index 6bcce55c0cdb6686e0585bf11107559ba61a5700,75032a507675914badcdce614ddd03dac4731ff8..357f3cdbbfd601e2ce3f1261a4d6b30c1257cda4
  #include "parse-options.h"
  #include "sigchain.h"
  #include "transport.h"
+ #include "submodule.h"
  
  static const char * const builtin_fetch_usage[] = {
        "git fetch [<options>] [<repository> [<refspec>...]]",
        "git fetch [<options>] <group>",
 -      "git fetch --multiple [<options>] [<repository> | <group>]...",
 +      "git fetch --multiple [<options>] [(<repository> | <group>)...]",
        "git fetch --all [<options>]",
        NULL
  };
@@@ -27,13 -28,20 +28,20 @@@ enum 
        TAGS_SET = 2
  };
  
+ enum {
+       RECURSE_SUBMODULES_OFF = 0,
+       RECURSE_SUBMODULES_DEFAULT = 1,
+       RECURSE_SUBMODULES_ON = 2
+ };
  static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
- static int progress;
+ static int progress, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
  static int tags = TAGS_DEFAULT;
  static const char *depth;
  static const char *upload_pack;
  static struct strbuf default_rla = STRBUF_INIT;
  static struct transport *transport;
+ static const char *submodule_prefix = "";
  
  static struct option builtin_fetch_options[] = {
        OPT__VERBOSITY(&verbosity),
@@@ -43,7 -51,8 +51,7 @@@
                    "append to .git/FETCH_HEAD instead of overwriting"),
        OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
                   "path to upload pack on remote end"),
 -      OPT_BOOLEAN('f', "force", &force,
 -                  "force overwrite of local branch"),
 +      OPT__FORCE(&force, "force overwrite of local branch"),
        OPT_BOOLEAN('m', "multiple", &multiple,
                    "fetch from multiple remotes"),
        OPT_SET_INT('t', "tags", &tags,
        OPT_SET_INT('n', NULL, &tags,
                    "do not fetch all tags (--no-tags)", TAGS_UNSET),
        OPT_BOOLEAN('p', "prune", &prune,
 -                  "prune tracking branches no longer on remote"),
 +                  "prune remote-tracking branches no longer on remote"),
+       OPT_SET_INT(0, "recurse-submodules", &recurse_submodules,
+                   "control recursive fetching of submodules",
+                   RECURSE_SUBMODULES_ON),
        OPT_BOOLEAN(0, "dry-run", &dry_run,
                    "dry run"),
        OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
@@@ -60,6 -72,8 +71,8 @@@
        OPT_BOOLEAN(0, "progress", &progress, "force progress reporting"),
        OPT_STRING(0, "depth", &depth, "DEPTH",
                   "deepen history of shallow clone"),
+       { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "DIR",
+                  "prepend this to submodule path output", PARSE_OPT_HIDDEN },
        OPT_END()
  };
  
@@@ -97,7 -111,7 +110,7 @@@ static void add_merge_config(struct re
                        continue;
  
                /*
 -               * Not fetched to a tracking branch?  We need to fetch
 +               * Not fetched to a remote-tracking branch?  We need to fetch
                 * it anyway to allow this branch's "branch.$name.merge"
                 * to be honored by 'git pull', but we do not have to
                 * fail if branch.$name.merge is misconfigured to point
@@@ -145,10 -159,7 +158,10 @@@ static struct ref *get_ref_map(struct t
                struct remote *remote = transport->remote;
                struct branch *branch = branch_get(NULL);
                int has_merge = branch_has_merge_config(branch);
 -              if (remote && (remote->fetch_refspec_nr || has_merge)) {
 +              if (remote &&
 +                  (remote->fetch_refspec_nr ||
 +                   /* Note: has_merge implies non-NULL branch->remote_name */
 +                   (has_merge && !strcmp(branch->remote_name, remote->name)))) {
                        for (i = 0; i < remote->fetch_refspec_nr; i++) {
                                get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0);
                                if (remote->fetch[i].dst &&
                         * if the remote we're fetching from is the same
                         * as given in branch.<name>.remote, we add the
                         * ref given in branch.<name>.merge, too.
 +                       *
 +                       * Note: has_merge implies non-NULL branch->remote_name
                         */
                        if (has_merge &&
                            !strcmp(branch->remote_name, remote->name))
@@@ -358,7 -367,7 +371,7 @@@ static int store_updated_refs(const cha
                        what = rm->name + 10;
                }
                else if (!prefixcmp(rm->name, "refs/remotes/")) {
 -                      kind = "remote branch";
 +                      kind = "remote-tracking branch";
                        what = rm->name + 13;
                }
                else {
@@@ -663,12 -672,10 +676,12 @@@ static int do_fetch(struct transport *t
  
        for_each_ref(add_existing, &existing_refs);
  
 -      if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET)
 -              tags = TAGS_SET;
 -      if (transport->remote->fetch_tags == -1)
 -              tags = TAGS_UNSET;
 +      if (tags == TAGS_DEFAULT) {
 +              if (transport->remote->fetch_tags == 2)
 +                      tags = TAGS_SET;
 +              if (transport->remote->fetch_tags == -1)
 +                      tags = TAGS_UNSET;
 +      }
  
        if (!transport->get_refs_list || !transport->fetch)
                die("Don't know how to fetch from %s", transport->url);
@@@ -783,28 -790,36 +796,36 @@@ static int add_remote_or_group(const ch
        return 1;
  }
  
- static int fetch_multiple(struct string_list *list)
+ static void add_options_to_argv(int *argc, const char **argv)
  {
-       int i, result = 0;
-       const char *argv[11] = { "fetch", "--append" };
-       int argc = 2;
        if (dry_run)
-               argv[argc++] = "--dry-run";
+               argv[(*argc)++] = "--dry-run";
        if (prune)
-               argv[argc++] = "--prune";
+               argv[(*argc)++] = "--prune";
        if (update_head_ok)
-               argv[argc++] = "--update-head-ok";
+               argv[(*argc)++] = "--update-head-ok";
        if (force)
-               argv[argc++] = "--force";
+               argv[(*argc)++] = "--force";
        if (keep)
-               argv[argc++] = "--keep";
+               argv[(*argc)++] = "--keep";
+       if (recurse_submodules == RECURSE_SUBMODULES_ON)
+               argv[(*argc)++] = "--recurse-submodules";
        if (verbosity >= 2)
-               argv[argc++] = "-v";
+               argv[(*argc)++] = "-v";
        if (verbosity >= 1)
-               argv[argc++] = "-v";
+               argv[(*argc)++] = "-v";
        else if (verbosity < 0)
-               argv[argc++] = "-q";
+               argv[(*argc)++] = "-q";
+ }
+ static int fetch_multiple(struct string_list *list)
+ {
+       int i, result = 0;
+       const char *argv[12] = { "fetch", "--append" };
+       int argc = 2;
+       add_options_to_argv(&argc, argv);
  
        if (!append && !dry_run) {
                int errcode = truncate_fetch_head();
@@@ -925,6 -940,21 +946,21 @@@ int cmd_fetch(int argc, const char **ar
                }
        }
  
+       if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
+               const char *options[10];
+               int num_options = 0;
+               /* Set recursion as default when we already are recursing */
+               if (submodule_prefix[0])
+                       set_config_fetch_recurse_submodules(1);
+               gitmodules_config();
+               git_config(submodule_config, NULL);
+               add_options_to_argv(&num_options, options);
+               result = fetch_populated_submodules(num_options, options,
+                                                   submodule_prefix,
+                                                   recurse_submodules == RECURSE_SUBMODULES_ON,
+                                                   verbosity < 0);
+       }
        /* All names were strdup()ed or strndup()ed */
        list.strdup_strings = 1;
        string_list_clear(&list, 0);
diff --combined git-pull.sh
index 20a3bbea07c259ec1f19353b2888fde20e8b67da,a5ab19538cec365d1c7bfab5059c04b341a376aa..eb87f49062b70d707adebca4013809822123608b
@@@ -38,7 -38,7 +38,7 @@@ test -z "$(git ls-files -u)" || die_con
  test -f "$GIT_DIR/MERGE_HEAD" && die_merge
  
  strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
- log_arg= verbosity= progress=
+ log_arg= verbosity= progress= recurse_submodules=
  merge_args=
  curr_branch=$(git symbolic-ref -q HEAD)
  curr_branch_short="${curr_branch#refs/heads/}"
        --no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)
                rebase=false
                ;;
+       --recurse-submodules)
+               recurse_submodules=--recurse-submodules
+               ;;
+       --no-recurse-submodules)
+               recurse_submodules=--no-recurse-submodules
+               ;;
        --d|--dr|--dry|--dry-|--dry-r|--dry-ru|--dry-run)
                dry_run=--dry-run
                ;;
@@@ -201,7 -207,10 +207,7 @@@ test true = "$rebase" && 
                        die "updating an unborn branch with changes added to the index"
                fi
        else
 -              git update-index --ignore-submodules --refresh &&
 -              git diff-files --ignore-submodules --quiet &&
 -              git diff-index --ignore-submodules --cached --quiet HEAD -- ||
 -              die "refusing to pull with rebase: your working tree is not up-to-date"
 +              require_clean_work_tree "pull with rebase" "Please commit or stash them."
        fi
        oldremoteref= &&
        . git-parse-remote &&
        done
  }
  orig_head=$(git rev-parse -q --verify HEAD)
- git fetch $verbosity $progress $dry_run --update-head-ok "$@" || exit 1
+ git fetch $verbosity $progress $dry_run $recurse_submodules --update-head-ok "$@" || exit 1
  test -z "$dry_run" || exit 0
  
  curr_head=$(git rev-parse -q --verify HEAD)