Merge branch 'fg/submodule-clone-depth'
authorJunio C Hamano <gitster@pobox.com>
Mon, 15 Jul 2013 17:28:48 +0000 (10:28 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 15 Jul 2013 17:28:48 +0000 (10:28 -0700)
Allow shallow-cloning of submodules with "git submodule update".

* fg/submodule-clone-depth:
Add --depth to submodule update/add

1  2 
Documentation/git-submodule.txt
git-submodule.sh
t/t7400-submodule-basic.sh
t/t7406-submodule-update.sh
index 134282700c7831ad0af1770475ed5767dd980f72,605419f1895114f4292695109defba9c5e4c1015..bfef8a0c62a56865cfe2335841efcb4535642287
@@@ -10,12 -10,12 +10,12 @@@ SYNOPSI
  --------
  [verse]
  'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
-             [--reference <repository>] [--] <repository> [<path>]
+             [--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] update [--init] [--remote] [-N|--no-fetch]
-             [-f|--force] [--rebase] [--reference <repository>]
+             [-f|--force] [--rebase] [--reference <repository>] [--depth <depth>]
              [--merge] [--recursive] [--] [<path>...]
  'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
              [commit] [--] [<path>...]
@@@ -159,9 -159,7 +159,9 @@@ update:
        This will make the submodules HEAD be detached unless `--rebase` or
        `--merge` is specified or the key `submodule.$name.update` is set to
        `rebase`, `merge` or `none`. `none` can be overridden by specifying
 -      `--checkout`.
 +      `--checkout`. Setting the key `submodule.$name.update` to `!command`
 +      will cause `command` to be run. `command` can be any arbitrary shell
 +      command that takes a single argument, namely the sha1 to update to.
  +
  If the submodule is not yet initialized, and you just want to use the
  setting as stored in .gitmodules, you can automatically initialize the
@@@ -264,7 -262,7 +264,7 @@@ OPTION
  --remote::
        This option is only valid for the update command.  Instead of using
        the superproject's recorded SHA-1 to update the submodule, use the
 -      status of the submodule's remote tracking branch.  The remote used
 +      status of the submodule's remote-tracking branch.  The remote used
        is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
        The remote branch used defaults to `master`, but the branch name may
        be overridden by setting the `submodule.<name>.branch` option in
@@@ -330,6 -328,12 +330,12 @@@ for linkgit:git-clone[1]'s `--reference
        only in the submodules of the current repo, but also
        in any nested submodules inside those submodules (and so on).
  
+ --depth::
+       This option is valid for add and update commands. Create a 'shallow'
+       clone with a history truncated to the specified number of revisions.
+       See linkgit:git-clone[1]
  <path>...::
        Paths to submodule(s). When specified this will restrict the command
        to only operate on the submodules found at the specified paths.
diff --combined git-submodule.sh
index c87515de10037a280dfed3b4751f8f60c4bcbea3,2458e1fcfba9b5615f26e45fd03c9ec558a1be96..2979197087f2c6d97e2945008394d50c16a195a5
@@@ -14,13 -14,10 +14,13 @@@ USAGE="[--quiet] add [-b <branch>] [-f|
     or: $dashless [--quiet] foreach [--recursive] <command>
     or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
  OPTIONS_SPEC=
 +SUBDIRECTORY_OK=Yes
  . git-sh-setup
  . git-sh-i18n
  . git-parse-remote
  require_work_tree
 +wt_prefix=$(git rev-parse --show-prefix)
 +cd_to_toplevel
  
  command=
  branch=
@@@ -35,6 -32,7 +35,7 @@@ nofetch
  update=
  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
@@@ -109,50 -107,14 +110,50 @@@ resolve_relative_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 '/'.
 +#
 +# The output is the first argument as a path relative to the second argument,
 +# which defaults to $wt_prefix if it is omitted.
 +relative_path ()
 +{
 +      local target curdir result
 +      target=$1
 +      curdir=${2-$wt_prefix}
 +      curdir=${curdir%/}
 +      result=
 +
 +      while test -n "$curdir"
 +      do
 +              case "$target" in
 +              "$curdir/"*)
 +                      target=${target#"$curdir"/}
 +                      break
 +                      ;;
 +              esac
 +
 +              result="${result}../"
 +              if test "$curdir" = "${curdir%/*}"
 +              then
 +                      curdir=
 +              else
 +                      curdir="${curdir%/*}"
 +              fi
 +      done
 +
 +      echo "$result$target"
 +}
 +
  #
  # Get submodule info for registered submodules
  # $@ = path to limit submodule list
  #
  module_list()
  {
 +      eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
        (
 -              git ls-files --error-unmatch --stage -- "$@" ||
 +              git ls-files -z --error-unmatch --stage -- "$@" ||
                echo "unmatched pathspec exists"
        ) |
        perl -e '
        my ($null_sha1) = ("0" x 40);
        my @out = ();
        my $unmatched = 0;
 +      $/ = "\0";
        while (<STDIN>) {
                if (/^unmatched pathspec/) {
                        $unmatched = 1;
@@@ -251,6 -212,7 +252,7 @@@ module_clone(
        name=$2
        url=$3
        reference="$4"
+       depth="$5"
        quiet=
        if test -n "$GIT_QUIET"
        then
                mkdir -p "$gitdir_base"
                (
                        clear_local_git_env
-                       git clone $quiet -n ${reference:+"$reference"} \
+                       git clone $quiet ${depth:+"$depth"} -n ${reference:+"$reference"} \
                                --separate-git-dir "$gitdir" "$url" "$sm_path"
                ) ||
                die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
@@@ -322,7 -284,6 +324,7 @@@ isnumber(
  cmd_add()
  {
        # parse $args after "submodule ... add".
 +      reference_path=
        while test $# -ne 0
        do
                case "$1" in
                        ;;
                --reference)
                        case "$2" in '') usage ;; esac
 -                      reference="--reference=$2"
 +                      reference_path=$2
                        shift
                        ;;
                --reference=*)
 -                      reference="$1"
 +                      reference_path="${1#--reference=}"
                        ;;
                --name)
                        case "$2" in '') usage ;; esac
                        custom_name=$2
                        shift
                        ;;
+               --depth)
+                       case "$2" in '') usage ;; esac
+                       depth="--depth=$2"
+                       shift
+                       ;;
+               --depth=*)
+                       depth=$1
+                       ;;
                --)
                        shift
                        break
                shift
        done
  
 +      if test -n "$reference_path"
 +      then
 +              is_absolute_path "$reference_path" ||
 +              reference_path="$wt_prefix$reference_path"
 +
 +              reference="--reference=$reference_path"
 +      fi
 +
        repo=$1
        sm_path=$2
  
                usage
        fi
  
 +      is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
 +
        # assure repo is absolute or relative to parent
        case "$repo" in
        ./*|../*)
 +              test -z "$wt_prefix" ||
 +              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
                ;;
@@@ -459,7 -415,7 +469,7 @@@ Use -f if you really want to add it." >
                                echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
                        fi
                fi
-               module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" || exit
+               module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit
                (
                        clear_local_git_env
                        cd "$sm_path" &&
@@@ -525,23 -481,21 +535,23 @@@ cmd_foreach(
                die_if_unmatched "$mode"
                if test -e "$sm_path"/.git
                then
 -                      say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
 +                      displaypath=$(relative_path "$sm_path")
 +                      say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
                        name=$(module_name "$sm_path")
                        (
                                prefix="$prefix$sm_path/"
                                clear_local_git_env
 -                              # we make $path available to scripts ...
 -                              path=$sm_path
                                cd "$sm_path" &&
 +                              sm_path=$(relative_path "$sm_path") &&
 +                              # we make $path available to scripts ...
 +                              path=$sm_path &&
                                eval "$@" &&
                                if test -n "$recursive"
                                then
                                        cmd_foreach "--recursive" "$@"
                                fi
                        ) <&3 3<&- ||
 -                      die "$(eval_gettext "Stopping at '\$sm_path'; script returned non-zero status.")"
 +                      die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
                fi
        done
  }
@@@ -580,14 -534,12 +590,14 @@@ cmd_init(
                die_if_unmatched "$mode"
                name=$(module_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 '\$sm_path' in .gitmodules")"
 +                      die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")"
  
                        # Possibly a url relative to parent
                        case "$url" in
                                ;;
                        esac
                        git config submodule."$name".url "$url" ||
 -                      die "$(eval_gettext "Failed to register url for submodule path '\$sm_path'")"
 +                      die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")"
  
 -                      say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
 +                      say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")"
                fi
  
                # Copy "update" setting when it is not set yet
                test -z "$upd" ||
                test -n "$(git config submodule."$name".update)" ||
                git config submodule."$name".update "$upd" ||
 -              die "$(eval_gettext "Failed to register update mode for submodule path '\$sm_path'")"
 +              die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
        done
  }
  
@@@ -652,29 -604,27 +662,29 @@@ cmd_deinit(
                die_if_unmatched "$mode"
                name=$(module_name "$sm_path") || exit
  
 +              displaypath=$(relative_path "$sm_path")
 +
                # Remove the submodule work tree (unless the user already did it)
                if test -d "$sm_path"
                then
                        # Protect submodules containing a .git directory
                        if test -d "$sm_path/.git"
                        then
 -                              echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")"
 +                              echo >&2 "$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")"
                                die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
                        fi
  
                        if test -z "$force"
                        then
                                git rm -qn "$sm_path" ||
 -                              die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
 +                              die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
                        fi
                        rm -rf "$sm_path" &&
 -                      say "$(eval_gettext "Cleared directory '\$sm_path'")" ||
 -                      say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")"
 +                      say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
 +                      say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
                fi
  
 -              mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")"
 +              mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
  
                # Remove the .git/config entries (unless the user already did it)
                if test -n "$(git config --get-regexp submodule."$name\.")"
                        # the user later decides to init this submodule again
                        url=$(git config submodule."$name".url)
                        git config --remove-section submodule."$name" 2>/dev/null &&
 -                      say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$sm_path'")"
 +                      say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
                fi
        done
  }
@@@ -736,6 -686,14 +746,14 @@@ cmd_update(
                --checkout)
                        update="checkout"
                        ;;
+               --depth)
+                       case "$2" in '') usage ;; esac
+                       depth="--depth=$2"
+                       shift
+                       ;;
+               --depth=*)
+                       depth=$1
+                       ;;
                --)
                        shift
                        break
                        update_module=$(git config submodule."$name".update)
                fi
  
 +              displaypath=$(relative_path "$prefix$sm_path")
 +
                if test "$update_module" = "none"
                then
 -                      echo "Skipping submodule '$prefix$sm_path'"
 +                      echo "Skipping submodule '$displaypath'"
                        continue
                fi
  
                        # Only mention uninitialized submodules when its
                        # path have been specified
                        test "$#" != "0" &&
 -                      say "$(eval_gettext "Submodule path '\$prefix\$sm_path' not initialized
 +                      say "$(eval_gettext "Submodule path '\$displaypath' not initialized
  Maybe you want to use 'update --init'?")"
                        continue
                fi
  
                if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
                then
-                       module_clone "$sm_path" "$name" "$url" "$reference" || exit
+                       module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
                        cloned_modules="$cloned_modules;$name"
                        subsha1=
                else
                        subsha1=$(clear_local_git_env; cd "$sm_path" &&
                                git rev-parse --verify HEAD) ||
 -                      die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")"
 +                      die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
                fi
  
                if test -n "$remote"
                                (clear_local_git_env; cd "$sm_path" &&
                                        ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
                                         test -z "$rev") || git-fetch)) ||
 -                              die "$(eval_gettext "Unable to fetch in submodule path '\$prefix\$sm_path'")"
 +                              die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
                        fi
  
                        # Is this something we just cloned?
                        case "$update_module" in
                        rebase)
                                command="git rebase"
 -                              die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$prefix\$sm_path'")"
 -                              say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': rebased into '\$sha1'")"
 +                              die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
 +                              say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
                                must_die_on_failure=yes
                                ;;
                        merge)
                                command="git merge"
 -                              die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$prefix\$sm_path'")"
 -                              say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': merged in '\$sha1'")"
 +                              die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
 +                              say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
 +                              must_die_on_failure=yes
 +                              ;;
 +                      !*)
 +                              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'")"
                                must_die_on_failure=yes
                                ;;
                        *)
                                command="git checkout $subforce -q"
 -                              die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$prefix\$sm_path'")"
 -                              say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': checked out '\$sha1'")"
 +                              die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
 +                              say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
                                ;;
                        esac
  
                        res=$?
                        if test $res -gt 0
                        then
 -                              die_msg="$(eval_gettext "Failed to recurse into submodule path '\$prefix\$sm_path'")"
 +                              die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
                                if test $res -eq 1
                                then
                                        err="${err};$die_msg"
@@@ -1010,7 -960,6 +1028,7 @@@ cmd_summary() 
        fi
  
        cd_to_toplevel
 +      eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
        # Get modified modules cared by user
        modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
                sane_egrep '^:([0-7]* )?160000' |
                ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
                missing_dst=t
  
 +              display_name=$(relative_path "$name")
 +
                total_commits=
                case "$missing_src,$missing_dst" in
                t,)
 -                      errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_src")"
 +                      errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_src")"
                        ;;
                ,t)
 -                      errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_dst")"
 +                      errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_dst")"
                        ;;
                t,t)
 -                      errmsg="$(eval_gettext "  Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
 +                      errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"
                        ;;
                *)
                        errmsg=
                        submodule="$(gettext "submodule")"
                        if test $mod_dst = 160000
                        then
 -                              echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
 +                              echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
                        else
 -                              echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
 +                              echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
                        fi
                else
 -                      echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
 +                      echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
                fi
                if test -n "$errmsg"
                then
@@@ -1189,7 -1136,7 +1207,7 @@@ cmd_status(
                die_if_unmatched "$mode"
                name=$(module_name "$sm_path") || exit
                url=$(git config submodule."$name".url)
 -              displaypath="$prefix$sm_path"
 +              displaypath=$(relative_path "$prefix$sm_path")
                if test "$stage" = U
                then
                        say "U$sha1 $displaypath"
                        say "-$sha1 $displaypath"
                        continue;
                fi
 -              set_name_rev "$sm_path" "$sha1"
                if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path"
                then
 +                      set_name_rev "$sm_path" "$sha1"
                        say " $sha1 $displaypath$revname"
                else
                        if test -z "$cached"
                        then
                                sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
 -                              set_name_rev "$sm_path" "$sha1"
                        fi
 +                      set_name_rev "$sm_path" "$sha1"
                        say "+$sha1 $displaypath$revname"
                fi
  
@@@ -1284,8 -1231,7 +1302,8 @@@ cmd_sync(
  
                if git config "submodule.$name.url" >/dev/null 2>/dev/null
                then
 -                      say "$(eval_gettext "Synchronizing submodule url for '\$prefix\$sm_path'")"
 +                      displaypath=$(relative_path "$prefix$sm_path")
 +                      say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"
                        git config submodule."$name".url "$super_config_url"
  
                        if test -e "$sm_path"/.git
index 50e6ad7458c48842408e2afc20f84c117120c262,42cd6de463a108b073be23cadc8bb4ada7d2847a..5ee97b003a879a0b6a558265e94c18582aa836c0
@@@ -78,7 -78,7 +78,7 @@@ test_expect_success 'submodule add' 
        (
                cd addtest &&
                git submodule add -q "$submodurl" submod >actual &&
 -              test ! -s actual &&
 +              test_must_be_empty actual &&
                echo "gitdir: ../.git/modules/submod" >expect &&
                test_cmp expect submod/.git &&
                (
@@@ -212,32 -212,6 +212,32 @@@ test_expect_success 'submodule add wit
        test_cmp empty untracked
  '
  
 +test_expect_success 'submodule add in subdirectory' '
 +      echo "refs/heads/master" >expect &&
 +      >empty &&
 +
 +      mkdir addtest/sub &&
 +      (
 +              cd addtest/sub &&
 +              git submodule add "$submodurl" ../realsubmod3 &&
 +              git submodule init
 +      ) &&
 +
 +      rm -f heads head untracked &&
 +      inspect addtest/realsubmod3 ../.. &&
 +      test_cmp expect heads &&
 +      test_cmp expect head &&
 +      test_cmp empty untracked
 +'
 +
 +test_expect_success 'submodule add in subdirectory with relative path should fail' '
 +      (
 +              cd addtest/sub &&
 +              test_must_fail git submodule add ../../ submod3 2>../../output.err
 +      ) &&
 +      test_i18ngrep toplevel output.err
 +'
 +
  test_expect_success 'setup - add an example entry to .gitmodules' '
        GIT_CONFIG=.gitmodules \
        git config submodule.example.url git://example.com/init.git
@@@ -334,7 -308,7 +334,7 @@@ test_expect_success 'update should wor
  
        mkdir init &&
        git submodule update -q >update.out &&
 -      test ! -s update.out &&
 +      test_must_be_empty update.out &&
  
        inspect init &&
        test_cmp expect head-sha1
@@@ -345,26 -319,6 +345,26 @@@ test_expect_success 'status should be "
        grep "^ $rev1" list
  '
  
 +test_expect_success 'status "up-to-date" from subdirectory' '
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule status >../list
 +      ) &&
 +      grep "^ $rev1" list &&
 +      grep "\\.\\./init" list
 +'
 +
 +test_expect_success 'status "up-to-date" from subdirectory with path' '
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule status ../init >../list
 +      ) &&
 +      grep "^ $rev1" list &&
 +      grep "\\.\\./init" list
 +'
 +
  test_expect_success 'status should be "modified" after submodule commit' '
        (
                cd init &&
@@@ -445,25 -399,6 +445,25 @@@ test_expect_success 'update --init' 
        git rev-parse --resolve-git-dir init/.git
  '
  
 +test_expect_success 'update --init from subdirectory' '
 +      mv init init2 &&
 +      git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
 +      git config --remove-section submodule.example &&
 +      test_must_fail git config submodule.example.url &&
 +
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule update ../init >update.out &&
 +              cat update.out &&
 +              test_i18ngrep "not initialized" update.out &&
 +              test_must_fail git rev-parse --resolve-git-dir ../init/.git &&
 +
 +              git submodule update --init ../init
 +      ) &&
 +      git rev-parse --resolve-git-dir init/.git
 +'
 +
  test_expect_success 'do not add files from a submodule' '
  
        git reset --hard &&
@@@ -761,7 -696,7 +761,7 @@@ test_expect_success 'submodule add --na
                rm -rf repo &&
                git rm repo &&
                git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual &&
 -              test ! -s actual &&
 +              test_must_be_empty actual &&
                echo "gitdir: ../.git/modules/submod" >expect &&
                test_cmp expect submod/.git &&
                (
@@@ -837,21 -772,6 +837,21 @@@ test_expect_success 'submodule deinit s
        rmdir init
  '
  
 +test_expect_success 'submodule deinit from subdirectory' '
 +      git submodule update --init &&
 +      git config submodule.example.foo bar &&
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule deinit ../init >../output
 +      ) &&
 +      grep "\\.\\./init" output &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -n "$(git config --get-regexp "submodule\.example2\.")" &&
 +      test -f example2/.git &&
 +      rmdir init
 +'
 +
  test_expect_success 'submodule deinit . deinits all initialized submodules' '
        git submodule update --init &&
        git config submodule.example.foo bar &&
@@@ -948,19 -868,19 +948,35 @@@ test_expect_success 'submodule deinit f
        test -n "$(git config --get-regexp "submodule\.example\.")"
  '
  
 +test_expect_success 'submodule with UTF-8 name' '
 +      svname=$(printf "\303\245 \303\244\303\266") &&
 +      mkdir "$svname" &&
 +      (
 +              cd "$svname" &&
 +              git init &&
 +              >sub &&
 +              git add sub &&
 +              git commit -m "init sub"
 +      ) &&
 +      test_config core.precomposeunicode true &&
 +      git submodule add ./"$svname" &&
 +      git submodule >&2 &&
 +      test -n "$(git submodule | grep "$svname")"
 +'
++
+ test_expect_success 'submodule add clone shallow submodule' '
+       mkdir super &&
+       pwd=$(pwd)
+       (
+               cd super &&
+               git init &&
+               git submodule add --depth=1 file://"$pwd"/example2 submodule &&
+               (
+                       cd submodule &&
+                       test 1 = $(git log --oneline | wc -l)
+               )
+       )
+ '
  test_done
index bc7cfcd835a22fbfcdd2105aa8c2410884a52cb2,e0a06e25e766d67466fccec83706f98af85041b8..b192f936bcbe794f0691550d1bf38714b1359d01
@@@ -80,21 -80,6 +80,21 @@@ test_expect_success 'submodule update d
        )
  '
  
 +test_expect_success 'submodule update from subdirectory' '
 +      (cd super/submodule &&
 +       git reset --hard HEAD~1
 +      ) &&
 +      mkdir super/sub &&
 +      (cd super/sub &&
 +       (cd ../submodule &&
 +        compare_head
 +       ) &&
 +       git submodule update ../submodule &&
 +       cd ../submodule &&
 +       ! compare_head
 +      )
 +'
 +
  apos="'";
  test_expect_success 'submodule update does not fetch already present commits' '
        (cd submodule &&
@@@ -294,35 -279,6 +294,35 @@@ test_expect_success 'submodule update 
        )
  '
  
 +test_expect_success 'submodule update - command in .git/config' '
 +      (cd super &&
 +       git config submodule.submodule.update "!git checkout"
 +      ) &&
 +      (cd super/submodule &&
 +        git reset --hard HEAD^
 +      ) &&
 +      (cd super &&
 +       (cd submodule &&
 +        compare_head
 +       ) &&
 +       git submodule update submodule &&
 +       cd submodule &&
 +       ! compare_head
 +      )
 +'
 +
 +test_expect_success 'submodule update - command in .git/config catches failure' '
 +      (cd super &&
 +       git config submodule.submodule.update "!false"
 +      ) &&
 +      (cd super/submodule &&
 +        git reset --hard HEAD^
 +      ) &&
 +      (cd super &&
 +       test_must_fail git submodule update submodule
 +      )
 +'
 +
  test_expect_success 'submodule init picks up rebase' '
        (cd super &&
         git config -f .gitmodules submodule.rebasing.update rebase &&
@@@ -729,14 -685,24 +729,24 @@@ test_expect_success 'submodule update p
  test_expect_success SYMLINKS 'submodule update can handle symbolic links in pwd' '
        mkdir -p linked/dir &&
        ln -s linked/dir linkto &&
-       (
-               cd linkto &&
-               git clone "$TRASH_DIRECTORY"/super_update_r2 super &&
-               (
-                       cd super &&
-                       git submodule update --init --recursive
-               )
+       (cd linkto &&
+        git clone "$TRASH_DIRECTORY"/super_update_r2 super &&
+        (cd super &&
+         git submodule update --init --recursive
+        )
        )
  '
  
+ test_expect_success 'submodule update clone shallow submodule' '
+       git clone cloned super3 &&
+       pwd=$(pwd)
+       (cd super3 &&
+        sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp &&
+        mv -f .gitmodules.tmp .gitmodules &&
+        git submodule update --init --depth=3
+        (cd submodule &&
+         test 1 = $(git log --oneline | wc -l)
+        )
+       )
+ '
  test_done