Merge branch 'sb/submodule-deinit-all'
authorJunio C Hamano <gitster@pobox.com>
Tue, 17 May 2016 21:38:19 +0000 (14:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 17 May 2016 21:38:20 +0000 (14:38 -0700)
Correct faulty recommendation to use "git submodule deinit ." when
de-initialising all submodules, which would result in a strange
error message in a pathological corner case.

* sb/submodule-deinit-all:
submodule deinit: require '--all' instead of '.' for all submodules

1  2 
Documentation/git-submodule.txt
git-submodule.sh
t/t7400-submodule-basic.sh
index 13adebf7b75f2ab122c4d23708493ef098d3548d,ad851838cc96df3e6b920c83f62a02061b8cae80..9226c4380c6c147108af9d38d7f7101c732a2095
@@@ -13,10 -13,10 +13,10 @@@ SYNOPSI
              [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
  'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
  'git submodule' [--quiet] init [--] [<path>...]
- 'git submodule' [--quiet] deinit [-f|--force] [--] <path>...
+ 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
  'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
              [-f|--force] [--rebase|--merge] [--reference <repository>]
 -            [--depth <depth>] [--recursive] [--] [<path>...]
 +            [--depth <depth>] [--recursive] [--jobs <n>] [--] [<path>...]
  'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
              [commit] [--] [<path>...]
  'git submodule' [--quiet] foreach [--recursive] <command>
@@@ -140,12 -140,15 +140,15 @@@ deinit:
        tree. Further calls to `git submodule update`, `git submodule foreach`
        and `git submodule sync` will skip any unregistered submodules until
        they are initialized again, so use this command if you don't want to
-       have a local checkout of the submodule in your work tree anymore. If
+       have a local checkout of the submodule in your working tree anymore. If
        you really want to remove a submodule from the repository and commit
        that use linkgit:git-rm[1] instead.
  +
- If `--force` is specified, the submodule's work tree will be removed even if
- it contains local modifications.
+ When the command is run without pathspec, it errors out,
+ instead of deinit-ing everything, to prevent mistakes.
+ +
+ If `--force` is specified, the submodule's working tree will
+ be removed even if it contains local modifications.
  
  update::
  +
@@@ -247,6 -250,10 +250,10 @@@ OPTION
  --quiet::
        Only print error messages.
  
+ --all::
+       This option is only valid for the deinit command. Unregister all
+       submodules in the working tree.
  -b::
  --branch::
        Branch of repository to add as submodule.
  --force::
        This option is only valid for add, deinit and update commands.
        When running add, allow adding an otherwise ignored submodule path.
-       When running deinit the submodule work trees will be removed even if
-       they contain local changes.
+       When running deinit the submodule working trees will be removed even
+       if they contain local changes.
        When running update (only effective with the checkout procedure),
        throw away local changes in submodules when switching to a
        different commit; and always run a checkout operation in the
@@@ -377,11 -384,6 +384,11 @@@ for linkgit:git-clone[1]'s `--reference
        clone with a history truncated to the specified number of revisions.
        See linkgit:git-clone[1]
  
 +-j <n>::
 +--jobs <n>::
 +      This option is only valid for the update command.
 +      Clone new submodules in parallel with as many jobs.
 +      Defaults to the `submodule.fetchJobs` option.
  
  <path>...::
        Paths to submodule(s). When specified this will restrict the command
diff --combined git-submodule.sh
index 14d02cc4bc2d55c63f5a49fa78b599e8e649e6a3,fb68f1fa7c35aa319737e8e51e23873a20f9fa4c..72fa3912831e3e981012fca5f4d6a3309ac7606b
@@@ -8,7 -8,7 +8,7 @@@ dashless=$(basename "$0" | sed -e 's/-
  USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
     or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
     or: $dashless [--quiet] init [--] [<path>...]
-    or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
+    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
     or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--reference <repository>] [--recursive] [--] [<path>...]
     or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
     or: $dashless [--quiet] foreach [--recursive] <command>
@@@ -46,6 -46,79 +46,6 @@@ prefix
  custom_name=
  depth=
  
 -# The function takes at most 2 arguments. The first argument is the
 -# URL that navigates to the submodule origin repo. When relative, this URL
 -# is relative to the superproject origin URL repo. The second up_path
 -# argument, if specified, is the relative path that navigates
 -# from the submodule working tree to the superproject working tree.
 -#
 -# The output of the function is the origin URL of the submodule.
 -#
 -# The output will either be an absolute URL or filesystem path (if the
 -# superproject origin URL is an absolute URL or filesystem path,
 -# respectively) or a relative file system path (if the superproject
 -# origin URL is a relative file system path).
 -#
 -# When the output is a relative file system path, the path is either
 -# relative to the submodule working tree, if up_path is specified, or to
 -# the superproject working tree otherwise.
 -resolve_relative_url ()
 -{
 -      remote=$(get_default_remote)
 -      remoteurl=$(git config "remote.$remote.url") ||
 -              remoteurl=$(pwd) # the repository is its own authoritative upstream
 -      url="$1"
 -      remoteurl=${remoteurl%/}
 -      sep=/
 -      up_path="$2"
 -
 -      case "$remoteurl" in
 -      *:*|/*)
 -              is_relative=
 -              ;;
 -      ./*|../*)
 -              is_relative=t
 -              ;;
 -      *)
 -              is_relative=t
 -              remoteurl="./$remoteurl"
 -              ;;
 -      esac
 -
 -      while test -n "$url"
 -      do
 -              case "$url" in
 -              ../*)
 -                      url="${url#../}"
 -                      case "$remoteurl" in
 -                      */*)
 -                              remoteurl="${remoteurl%/*}"
 -                              ;;
 -                      *:*)
 -                              remoteurl="${remoteurl%:*}"
 -                              sep=:
 -                              ;;
 -                      *)
 -                              if test -z "$is_relative" || test "." = "$remoteurl"
 -                              then
 -                                      die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
 -                              else
 -                                      remoteurl=.
 -                              fi
 -                              ;;
 -                      esac
 -                      ;;
 -              ./*)
 -                      url="${url#./}"
 -                      ;;
 -              *)
 -                      break;;
 -              esac
 -      done
 -      remoteurl="$remoteurl$sep${url%/}"
 -      echo "${is_relative:+${up_path}}${remoteurl#./}"
 -}
 -
  # Resolve a path to be relative to another path.  This is intended for
  # converting submodule paths when git-submodule is run in a subdirectory
  # and only handles paths where the directory separator is '/'.
@@@ -119,16 -192,6 +119,16 @@@ isnumber(
        n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
  }
  
 +# Sanitize the local git environment for use within a submodule. We
 +# can't simply use clear_local_git_env since we want to preserve some
 +# of the settings from GIT_CONFIG_PARAMETERS.
 +sanitize_submodule_env()
 +{
 +      sanitized_config=$(git submodule--helper sanitize-config)
 +      clear_local_git_env
 +      GIT_CONFIG_PARAMETERS=$sanitized_config
 +}
 +
  #
  # Add a new submodule to the working tree, .gitmodules and the index
  #
@@@ -218,7 -281,7 +218,7 @@@ cmd_add(
                die "$(gettext "Relative path can only be used from the toplevel of the working tree")"
  
                # dereference source url relative to parent's url
 -              realrepo=$(resolve_relative_url "$repo") || exit
 +              realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
                ;;
        *:*|/*)
                # absolute url
@@@ -284,9 -347,9 +284,9 @@@ Use -f if you really want to add it." >
                                echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
                        fi
                fi
 -              git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" "$reference" "$depth" || exit
 +              git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${depth:+"$depth"} || exit
                (
 -                      clear_local_git_env
 +                      sanitize_submodule_env
                        cd "$sm_path" &&
                        # ash fails to wordsplit ${branch:+-b "$branch"...}
                        case "$branch" in
@@@ -350,12 -413,12 +350,12 @@@ cmd_foreach(
                die_if_unmatched "$mode"
                if test -e "$sm_path"/.git
                then
 -                      displaypath=$(relative_path "$sm_path")
 -                      say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
 +                      displaypath=$(relative_path "$prefix$sm_path")
 +                      say "$(eval_gettext "Entering '\$displaypath'")"
                        name=$(git submodule--helper name "$sm_path")
                        (
                                prefix="$prefix$sm_path/"
 -                              clear_local_git_env
 +                              sanitize_submodule_env
                                cd "$sm_path" &&
                                sm_path=$(relative_path "$sm_path") &&
                                # we make $path available to scripts ...
                                        cmd_foreach "--recursive" "$@"
                                fi
                        ) <&3 3<&- ||
 -                      die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
 +                      die "$(eval_gettext "Stopping at '\$displaypath'; script returned non-zero status.")"
                fi
        done
  }
@@@ -404,7 -467,50 +404,7 @@@ cmd_init(
                shift
        done
  
 -      git submodule--helper list --prefix "$wt_prefix" "$@" |
 -      while read mode sha1 stage sm_path
 -      do
 -              die_if_unmatched "$mode"
 -              name=$(git submodule--helper name "$sm_path") || exit
 -
 -              displaypath=$(relative_path "$sm_path")
 -
 -              # Copy url setting when it is not set yet
 -              if test -z "$(git config "submodule.$name.url")"
 -              then
 -                      url=$(git config -f .gitmodules submodule."$name".url)
 -                      test -z "$url" &&
 -                      die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")"
 -
 -                      # Possibly a url relative to parent
 -                      case "$url" in
 -                      ./*|../*)
 -                              url=$(resolve_relative_url "$url") || exit
 -                              ;;
 -                      esac
 -                      git config submodule."$name".url "$url" ||
 -                      die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")"
 -
 -                      say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")"
 -              fi
 -
 -              # Copy "update" setting when it is not set yet
 -              if upd="$(git config -f .gitmodules submodule."$name".update)" &&
 -                 test -n "$upd" &&
 -                 test -z "$(git config submodule."$name".update)"
 -              then
 -                      case "$upd" in
 -                      checkout | rebase | merge | none)
 -                              ;; # known modes of updating
 -                      *)
 -                              echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
 -                              upd=none
 -                              ;;
 -                      esac
 -                      git config submodule."$name".update "$upd" ||
 -                      die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
 -              fi
 -      done
 +      git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} "$@"
  }
  
  #
  cmd_deinit()
  {
        # parse $args after "submodule ... deinit".
+       deinit_all=
        while test $# -ne 0
        do
                case "$1" in
                -q|--quiet)
                        GIT_QUIET=1
                        ;;
+               --all)
+                       deinit_all=t
+                       ;;
                --)
                        shift
                        break
                shift
        done
  
-       if test $# = 0
+       if test -n "$deinit_all" && test "$#" -ne 0
+       then
+               echo >&2 "$(eval_gettext "pathspec and --all are incompatible")"
+               usage
+       fi
+       if test $# = 0 && test -z "$deinit_all"
        then
-               die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
+               die "$(eval_gettext "Use '--all' if you really want to deinitialize all submodules")"
        fi
  
        git submodule--helper list --prefix "$wt_prefix" "$@" |
  }
  
  is_tip_reachable () (
 -      clear_local_git_env
 +      sanitize_submodule_env &&
        cd "$1" &&
        rev=$(git rev-list -n 1 "$2" --not --all 2>/dev/null) &&
        test -z "$rev"
  )
  
  fetch_in_submodule () (
 -      clear_local_git_env
 +      sanitize_submodule_env &&
        cd "$1" &&
        case "$2" in
        '')
@@@ -557,14 -672,6 +566,14 @@@ cmd_update(
                --depth=*)
                        depth=$1
                        ;;
 +              -j|--jobs)
 +                      case "$2" in '') usage ;; esac
 +                      jobs="--jobs=$2"
 +                      shift
 +                      ;;
 +              --jobs=*)
 +                      jobs=$1
 +                      ;;
                --)
                        shift
                        break
                cmd_init "--" "$@" || return
        fi
  
 -      cloned_modules=
 -      git submodule--helper list --prefix "$wt_prefix" "$@" | {
 +      {
 +      git submodule--helper update-clone ${GIT_QUIET:+--quiet} \
 +              ${wt_prefix:+--prefix "$wt_prefix"} \
 +              ${prefix:+--recursive-prefix "$prefix"} \
 +              ${update:+--update "$update"} \
 +              ${reference:+--reference "$reference"} \
 +              ${depth:+--depth "$depth"} \
 +              ${jobs:+$jobs} \
 +              "$@" || echo "#unmatched"
 +      } | {
        err=
 -      while read mode sha1 stage sm_path
 +      while read mode sha1 stage just_cloned sm_path
        do
                die_if_unmatched "$mode"
 -              if test "$stage" = U
 -              then
 -                      echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 -                      continue
 -              fi
 +
                name=$(git submodule--helper name "$sm_path") || exit
                url=$(git config submodule."$name".url)
                branch=$(get_submodule_config "$name" branch master)
  
                displaypath=$(relative_path "$prefix$sm_path")
  
 -              if test "$update_module" = "none"
 +              if test $just_cloned -eq 1
                then
 -                      echo "Skipping submodule '$displaypath'"
 -                      continue
 -              fi
 -
 -              if test -z "$url"
 -              then
 -                      # Only mention uninitialized submodules when its
 -                      # path have been specified
 -                      test "$#" != "0" &&
 -                      say "$(eval_gettext "Submodule path '\$displaypath' not initialized
 -Maybe you want to use 'update --init'?")"
 -                      continue
 -              fi
 -
 -              if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
 -              then
 -                      git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
 -                      cloned_modules="$cloned_modules;$name"
                        subsha1=
 +                      update_module=checkout
                else
 -                      subsha1=$(clear_local_git_env; cd "$sm_path" &&
 +                      subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
                                git rev-parse --verify HEAD) ||
                        die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
                fi
                        if test -z "$nofetch"
                        then
                                # Fetch remote before determining tracking $sha1
 -                              (clear_local_git_env; cd "$sm_path" && git-fetch) ||
 +                              (sanitize_submodule_env; cd "$sm_path" && git-fetch) ||
                                die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
                        fi
 -                      remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
 -                      sha1=$(clear_local_git_env; cd "$sm_path" &&
 +                      remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
 +                      sha1=$(sanitize_submodule_env; cd "$sm_path" &&
                                git rev-parse --verify "${remote_name}/${branch}") ||
                        die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
                fi
                                die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain $sha1. Direct fetching of that commit failed.")"
                        fi
  
 -                      # Is this something we just cloned?
 -                      case ";$cloned_modules;" in
 -                      *";$name;"*)
 -                              # then there is no local change to integrate
 -                              update_module=checkout ;;
 -                      esac
 -
                        must_die_on_failure=
                        case "$update_module" in
                        checkout)
                                ;;
                        !*)
                                command="${update_module#!}"
 -                              die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
 -                              say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
 +                              die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$displaypath'")"
 +                              say_msg="$(eval_gettext "Submodule path '\$displaypath': '\$command \$sha1'")"
                                must_die_on_failure=yes
                                ;;
                        *)
                                die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
                        esac
  
 -                      if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
 +                      if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")
                        then
                                say "$say_msg"
                        elif test -n "$must_die_on_failure"
                if test -n "$recursive"
                then
                        (
 -                              prefix="$prefix$sm_path/"
 -                              clear_local_git_env
 +                              prefix=$(relative_path "$prefix$sm_path/")
 +                              wt_prefix=
 +                              sanitize_submodule_env
                                cd "$sm_path" &&
                                eval cmd_update
                        )
  
  set_name_rev () {
        revname=$( (
 -              clear_local_git_env
 +              sanitize_submodule_env
                cd "$1" && {
                        git describe "$2" 2>/dev/null ||
                        git describe --tags "$2" 2>/dev/null ||
@@@ -1031,7 -1157,7 +1040,7 @@@ cmd_status(
                else
                        if test -z "$cached"
                        then
 -                              sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
 +                              sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD)
                        fi
                        set_name_rev "$sm_path" "$sha1"
                        say "+$sha1 $displaypath$revname"
                then
                        (
                                prefix="$displaypath/"
 -                              clear_local_git_env
 +                              sanitize_submodule_env
 +                              wt_prefix=
                                cd "$sm_path" &&
                                eval cmd_status
                        ) ||
@@@ -1097,9 -1222,9 +1106,9 @@@ cmd_sync(
                        # guarantee a trailing /
                        up_path=${up_path%/}/ &&
                        # path from submodule work tree to submodule origin repo
 -                      sub_origin_url=$(resolve_relative_url "$url" "$up_path") &&
 +                      sub_origin_url=$(git submodule--helper resolve-relative-url "$url" "$up_path") &&
                        # path from superproject work tree to submodule origin repo
 -                      super_config_url=$(resolve_relative_url "$url") || exit
 +                      super_config_url=$(git submodule--helper resolve-relative-url "$url") || exit
                        ;;
                *)
                        sub_origin_url="$url"
                        if test -e "$sm_path"/.git
                        then
                        (
 -                              clear_local_git_env
 +                              sanitize_submodule_env
                                cd "$sm_path"
                                remote=$(get_default_remote)
                                git config remote."$remote".url "$sub_origin_url"
index 90d80d369c7e9c35f7f86b50e660b95cd279ccaa,cc3cca09f3743eab042e61804048c4b7b9ef6ad8..3570f7bb8c8955a1bf519eda3278392d249e6fd1
@@@ -11,6 -11,10 +11,10 @@@ subcommands of git submodule
  
  . ./test-lib.sh
  
+ test_expect_success 'submodule deinit works on empty repository' '
+       git submodule deinit --all
+ '
  test_expect_success 'setup - initial commit' '
        >t &&
        git add t &&
        git branch initial
  '
  
 +test_expect_success 'submodule init aborts on missing .gitmodules file' '
 +      test_when_finished "git update-index --remove sub" &&
 +      git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub &&
 +      # missing the .gitmodules file here
 +      test_must_fail git submodule init 2>actual &&
 +      test_i18ngrep "No url found for submodule path" actual
 +'
 +
 +test_expect_success 'submodule update aborts on missing .gitmodules file' '
 +      test_when_finished "git update-index --remove sub" &&
 +      git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub &&
 +      # missing the .gitmodules file here
 +      git submodule update sub 2>actual &&
 +      test_i18ngrep "Submodule path .sub. not initialized" actual
 +'
 +
  test_expect_success 'configuration parsing' '
        test_when_finished "rm -f .gitmodules" &&
        cat >.gitmodules <<-\EOF &&
@@@ -478,7 -466,7 +482,7 @@@ test_expect_success 'update --init' 
        git config --remove-section submodule.example &&
        test_must_fail git config submodule.example.url &&
  
 -      git submodule update init > update.out &&
 +      git submodule update init 2> update.out &&
        cat update.out &&
        test_i18ngrep "not initialized" update.out &&
        test_must_fail git rev-parse --resolve-git-dir init/.git &&
@@@ -496,7 -484,7 +500,7 @@@ test_expect_success 'update --init fro
        mkdir -p sub &&
        (
                cd sub &&
 -              git submodule update ../init >update.out &&
 +              git submodule update ../init 2>update.out &&
                cat update.out &&
                test_i18ngrep "not initialized" update.out &&
                test_must_fail git rev-parse --resolve-git-dir ../init/.git &&
@@@ -834,47 -822,6 +838,47 @@@ test_expect_success 'submodule add --na
        )
  '
  
 +test_expect_success 'recursive relative submodules stay relative' '
 +      test_when_finished "rm -rf super clone2 subsub sub3" &&
 +      mkdir subsub &&
 +      (
 +              cd subsub &&
 +              git init &&
 +              >t &&
 +              git add t &&
 +              git commit -m "initial commit"
 +      ) &&
 +      mkdir sub3 &&
 +      (
 +              cd sub3 &&
 +              git init &&
 +              >t &&
 +              git add t &&
 +              git commit -m "initial commit" &&
 +              git submodule add ../subsub dirdir/subsub &&
 +              git commit -m "add submodule subsub"
 +      ) &&
 +      mkdir super &&
 +      (
 +              cd super &&
 +              git init &&
 +              >t &&
 +              git add t &&
 +              git commit -m "initial commit" &&
 +              git submodule add ../sub3 &&
 +              git commit -m "add submodule sub"
 +      ) &&
 +      git clone super clone2 &&
 +      (
 +              cd clone2 &&
 +              git submodule update --init --recursive &&
 +              echo "gitdir: ../.git/modules/sub3" >./sub3/.git_expect &&
 +              echo "gitdir: ../../../.git/modules/sub3/modules/dirdir/subsub" >./sub3/dirdir/subsub/.git_expect
 +      ) &&
 +      test_cmp clone2/sub3/.git_expect clone2/sub3/.git &&
 +      test_cmp clone2/sub3/dirdir/subsub/.git_expect clone2/sub3/dirdir/subsub/.git
 +'
 +
  test_expect_success 'submodule add with an existing name fails unless forced' '
        (
                cd addtest2 &&
@@@ -914,8 -861,9 +918,9 @@@ test_expect_success 'submodule deinit w
                git init &&
                >file &&
                git add file &&
 -              git commit -m "repo should not be empty"
 +              git commit -m "repo should not be empty" &&
-               git submodule deinit .
+               git submodule deinit . &&
+               git submodule deinit --all
        )
  '
  
@@@ -957,6 -905,19 +962,19 @@@ test_expect_success 'submodule deinit 
        rmdir init example2
  '
  
+ test_expect_success 'submodule deinit --all deinits all initialized submodules' '
+       git submodule update --init &&
+       git config submodule.example.foo bar &&
+       git config submodule.example2.frotz nitfol &&
+       test_must_fail git submodule deinit &&
+       git submodule deinit --all >actual &&
+       test -z "$(git config --get-regexp "submodule\.example\.")" &&
+       test -z "$(git config --get-regexp "submodule\.example2\.")" &&
+       test_i18ngrep "Cleared directory .init" actual &&
+       test_i18ngrep "Cleared directory .example2" actual &&
+       rmdir init example2
+ '
  test_expect_success 'submodule deinit deinits a submodule when its work tree is missing or empty' '
        git submodule update --init &&
        rm -rf init example2/* example2/.git &&
@@@ -1023,6 -984,10 +1041,10 @@@ test_expect_success 'submodule deinit i
        test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
        test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
        test_i18ngrep "Cleared directory .init" actual &&
+       git submodule deinit --all >actual &&
+       test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
+       test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
+       test_i18ngrep "Cleared directory .init" actual &&
        rmdir init example2
  '