Merge branch 'wk/submodule-on-branch'
Make sure 'submodule update' modes that do not detach HEADs can be used more pleasantly by checking out a concrete branch when cloning them to prime the well. * wk/submodule-on-branch: Documentation: describe 'submodule update --remote' use case submodule: explicit local branch creation in module_clone submodule: document module_clone arguments in comments submodule: make 'checkout' update_module mode more explicitmaint
						commit
						06c27689dd
					
				| 
						 | 
				
			
			@ -15,8 +15,8 @@ SYNOPSIS
 | 
			
		|||
'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>] [--depth <depth>]
 | 
			
		||||
	      [--merge] [--recursive] [--] [<path>...]
 | 
			
		||||
	      [-f|--force] [--rebase|--merge|--checkout] [--reference <repository>]
 | 
			
		||||
	      [--depth <depth>] [--recursive] [--] [<path>...]
 | 
			
		||||
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
 | 
			
		||||
	      [commit] [--] [<path>...]
 | 
			
		||||
'git submodule' [--quiet] foreach [--recursive] <command>
 | 
			
		||||
| 
						 | 
				
			
			@ -155,13 +155,31 @@ it contains local modifications.
 | 
			
		|||
 | 
			
		||||
update::
 | 
			
		||||
	Update the registered submodules, i.e. clone missing submodules and
 | 
			
		||||
	checkout the commit specified in the index of the containing repository.
 | 
			
		||||
	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`. 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.
 | 
			
		||||
	checkout the commit specified in the index of the containing
 | 
			
		||||
	repository.  The update mode defaults to `checkout`, but can be
 | 
			
		||||
	configured with the `submodule.<name>.update` setting or the
 | 
			
		||||
	`--rebase`, `--merge`, or `--checkout` options.
 | 
			
		||||
+
 | 
			
		||||
For updates that clone missing submodules, checkout-mode updates will
 | 
			
		||||
create submodules with detached HEADs; all other modes will create
 | 
			
		||||
submodules with a local branch named after `submodule.<path>.branch`.
 | 
			
		||||
+
 | 
			
		||||
For updates that do not clone missing submodules, the submodule's HEAD
 | 
			
		||||
is only touched when the remote reference does not match the
 | 
			
		||||
submodule's HEAD (for none-mode updates, the submodule is never
 | 
			
		||||
touched).  The remote reference is usually the gitlinked commit from
 | 
			
		||||
the superproject's tree, but with `--remote` it is the upstream
 | 
			
		||||
subproject's `submodule.<name>.branch`.  This remote reference is
 | 
			
		||||
integrated with the submodule's HEAD using the specified update mode.
 | 
			
		||||
For checkout-mode updates, that will result in a detached HEAD.  For
 | 
			
		||||
rebase- and merge-mode updates, the commit referenced by the
 | 
			
		||||
submodule's HEAD may change, but the symbolic reference will remain
 | 
			
		||||
unchanged (i.e. checked-out branches will still be checked-out
 | 
			
		||||
branches, and detached HEADs will still be detached HEADs).  If none
 | 
			
		||||
of the builtin modes fit your needs, set `submodule.<name>.update` to
 | 
			
		||||
`!command` to configure a custom integration command.  `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
 | 
			
		||||
| 
						 | 
				
			
			@ -281,6 +299,16 @@ In order to ensure a current tracking branch state, `update --remote`
 | 
			
		|||
fetches the submodule's remote repository before calculating the
 | 
			
		||||
SHA-1.  If you don't want to fetch, you should use `submodule update
 | 
			
		||||
--remote --no-fetch`.
 | 
			
		||||
+
 | 
			
		||||
Use this option to integrate changes from the upstream subproject with
 | 
			
		||||
your submodule's current HEAD.  Alternatively, you can run `git pull`
 | 
			
		||||
from the submodule, which is equivalent except for the remote branch
 | 
			
		||||
name: `update --remote` uses the default upstream repository and
 | 
			
		||||
`submodule.<name>.branch`, while `git pull` uses the submodule's
 | 
			
		||||
`branch.<name>.merge`.  Prefer `submodule.<name>.branch` if you want
 | 
			
		||||
to distribute the default upstream branch with the superproject and
 | 
			
		||||
`branch.<name>.merge` if you want a more native feel while working in
 | 
			
		||||
the submodule itself.
 | 
			
		||||
 | 
			
		||||
-N::
 | 
			
		||||
--no-fetch::
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,10 @@ submodule.<name>.branch::
 | 
			
		|||
	A remote branch name for tracking updates in the upstream submodule.
 | 
			
		||||
	If the option is not specified, it defaults to 'master'.  See the
 | 
			
		||||
	`--remote` documentation in linkgit:git-submodule[1] for details.
 | 
			
		||||
+
 | 
			
		||||
This branch name is also used for the local branch created by
 | 
			
		||||
non-checkout cloning updates.  See the `update` documentation in
 | 
			
		||||
linkgit:git-submodule[1] for details.
 | 
			
		||||
 | 
			
		||||
submodule.<name>.fetchRecurseSubmodules::
 | 
			
		||||
	This option can be used to control recursive fetching of this
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -241,6 +241,15 @@ module_name()
 | 
			
		|||
#
 | 
			
		||||
# Clone a submodule
 | 
			
		||||
#
 | 
			
		||||
# $1 = submodule path
 | 
			
		||||
# $2 = submodule name
 | 
			
		||||
# $3 = URL to clone
 | 
			
		||||
# $4 = reference repository to reuse (empty for independent)
 | 
			
		||||
# $5 = depth argument for shallow clones (empty for deep)
 | 
			
		||||
# $6 = (remote-tracking) starting point for the local branch (empty for HEAD)
 | 
			
		||||
# $7 = local branch to create (empty for a detached HEAD, unless $6 is
 | 
			
		||||
#      also empty, in which case the local branch is left unchanged)
 | 
			
		||||
#
 | 
			
		||||
# Prior to calling, cmd_update checks that a possibly existing
 | 
			
		||||
# path is not a git repository.
 | 
			
		||||
# Likewise, cmd_add checks that path does not exist at all,
 | 
			
		||||
| 
						 | 
				
			
			@ -253,6 +262,8 @@ module_clone()
 | 
			
		|||
	url=$3
 | 
			
		||||
	reference="$4"
 | 
			
		||||
	depth="$5"
 | 
			
		||||
	start_point="$6"
 | 
			
		||||
	local_branch="$7"
 | 
			
		||||
	quiet=
 | 
			
		||||
	if test -n "$GIT_QUIET"
 | 
			
		||||
	then
 | 
			
		||||
| 
						 | 
				
			
			@ -306,7 +317,16 @@ module_clone()
 | 
			
		|||
	echo "gitdir: $rel/$a" >"$sm_path/.git"
 | 
			
		||||
 | 
			
		||||
	rel=$(echo $a | sed -e 's|[^/][^/]*|..|g')
 | 
			
		||||
	(clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
 | 
			
		||||
	(
 | 
			
		||||
		clear_local_git_env
 | 
			
		||||
		cd "$sm_path" &&
 | 
			
		||||
		GIT_WORK_TREE=. git config core.worktree "$rel/$b" &&
 | 
			
		||||
		# ash fails to wordsplit ${local_branch:+-B "$local_branch"...}
 | 
			
		||||
		case "$local_branch" in
 | 
			
		||||
		'') git checkout -f -q ${start_point:+"$start_point"} ;;
 | 
			
		||||
		?*) git checkout -f -q -B "$local_branch" ${start_point:+"$start_point"} ;;
 | 
			
		||||
		esac
 | 
			
		||||
	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
isnumber()
 | 
			
		||||
| 
						 | 
				
			
			@ -469,16 +489,15 @@ Use -f if you really want to add it." >&2
 | 
			
		|||
				echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit
 | 
			
		||||
		(
 | 
			
		||||
			clear_local_git_env
 | 
			
		||||
			cd "$sm_path" &&
 | 
			
		||||
			# ash fails to wordsplit ${branch:+-b "$branch"...}
 | 
			
		||||
			case "$branch" in
 | 
			
		||||
			'') git checkout -f -q ;;
 | 
			
		||||
			?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
 | 
			
		||||
			esac
 | 
			
		||||
		) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
 | 
			
		||||
		if test -n "$branch"
 | 
			
		||||
		then
 | 
			
		||||
			start_point="origin/$branch"
 | 
			
		||||
			local_branch="$branch"
 | 
			
		||||
		else
 | 
			
		||||
			start_point=""
 | 
			
		||||
			local_branch=""
 | 
			
		||||
		fi
 | 
			
		||||
		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$start_point" "$local_branch" || exit
 | 
			
		||||
	fi
 | 
			
		||||
	git config submodule."$sm_name".url "$realrepo"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -799,32 +818,35 @@ cmd_update()
 | 
			
		|||
		fi
 | 
			
		||||
		name=$(module_name "$sm_path") || exit
 | 
			
		||||
		url=$(git config submodule."$name".url)
 | 
			
		||||
		branch=$(get_submodule_config "$name" branch master)
 | 
			
		||||
		config_branch=$(get_submodule_config "$name" branch)
 | 
			
		||||
		branch="${config_branch:-master}"
 | 
			
		||||
		local_branch="$branch"
 | 
			
		||||
		if ! test -z "$update"
 | 
			
		||||
		then
 | 
			
		||||
			update_module=$update
 | 
			
		||||
		else
 | 
			
		||||
			update_module=$(git config submodule."$name".update)
 | 
			
		||||
			case "$update_module" in
 | 
			
		||||
			'')
 | 
			
		||||
				;; # Unset update mode
 | 
			
		||||
			checkout | rebase | merge | none)
 | 
			
		||||
				;; # Known update modes
 | 
			
		||||
			!*)
 | 
			
		||||
				;; # Custom update command
 | 
			
		||||
			*)
 | 
			
		||||
				die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
 | 
			
		||||
				;;
 | 
			
		||||
			esac
 | 
			
		||||
			if test -z "$update_module"
 | 
			
		||||
			then
 | 
			
		||||
				update_module="checkout"
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		displaypath=$(relative_path "$prefix$sm_path")
 | 
			
		||||
 | 
			
		||||
		if test "$update_module" = "none"
 | 
			
		||||
		then
 | 
			
		||||
		case "$update_module" in
 | 
			
		||||
		none)
 | 
			
		||||
			echo "Skipping submodule '$displaypath'"
 | 
			
		||||
			continue
 | 
			
		||||
		fi
 | 
			
		||||
			;;
 | 
			
		||||
		checkout)
 | 
			
		||||
			local_branch=""
 | 
			
		||||
			;;
 | 
			
		||||
		rebase | merge | !*)
 | 
			
		||||
			;;
 | 
			
		||||
		*)
 | 
			
		||||
			die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
 | 
			
		||||
		esac
 | 
			
		||||
 | 
			
		||||
		if test -z "$url"
 | 
			
		||||
		then
 | 
			
		||||
| 
						 | 
				
			
			@ -838,7 +860,8 @@ Maybe you want to use 'update --init'?")"
 | 
			
		|||
 | 
			
		||||
		if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
 | 
			
		||||
		then
 | 
			
		||||
			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
 | 
			
		||||
			start_point="origin/${branch}"
 | 
			
		||||
			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$start_point" "$local_branch" || exit
 | 
			
		||||
			cloned_modules="$cloned_modules;$name"
 | 
			
		||||
			subsha1=
 | 
			
		||||
		else
 | 
			
		||||
| 
						 | 
				
			
			@ -884,11 +907,16 @@ Maybe you want to use 'update --init'?")"
 | 
			
		|||
			case ";$cloned_modules;" in
 | 
			
		||||
			*";$name;"*)
 | 
			
		||||
				# then there is no local change to integrate
 | 
			
		||||
				update_module= ;;
 | 
			
		||||
				update_module='!git reset --hard -q'
 | 
			
		||||
			esac
 | 
			
		||||
 | 
			
		||||
			must_die_on_failure=
 | 
			
		||||
			case "$update_module" in
 | 
			
		||||
			checkout)
 | 
			
		||||
				command="git checkout $subforce -q"
 | 
			
		||||
				die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
 | 
			
		||||
				say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
 | 
			
		||||
				;;
 | 
			
		||||
			rebase)
 | 
			
		||||
				command="git rebase"
 | 
			
		||||
				die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
 | 
			
		||||
| 
						 | 
				
			
			@ -908,10 +936,7 @@ Maybe you want to use 'update --init'?")"
 | 
			
		|||
				must_die_on_failure=yes
 | 
			
		||||
				;;
 | 
			
		||||
			*)
 | 
			
		||||
				command="git checkout $subforce -q"
 | 
			
		||||
				die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
 | 
			
		||||
				say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
 | 
			
		||||
				;;
 | 
			
		||||
				die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
 | 
			
		||||
			esac
 | 
			
		||||
 | 
			
		||||
			if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,6 +63,9 @@ test_expect_success 'setup a submodule tree' '
 | 
			
		|||
	 git submodule add ../none none &&
 | 
			
		||||
	 test_tick &&
 | 
			
		||||
	 git commit -m "none"
 | 
			
		||||
	) &&
 | 
			
		||||
	(cd super &&
 | 
			
		||||
	 git tag initial-setup
 | 
			
		||||
	)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -703,7 +706,7 @@ test_expect_success 'submodule update places git-dir in superprojects git-dir re
 | 
			
		|||
	git clone super_update_r super_update_r2 &&
 | 
			
		||||
	(cd super_update_r2 &&
 | 
			
		||||
	 git submodule update --init --recursive >actual &&
 | 
			
		||||
	 test_i18ngrep "Submodule path .submodule/subsubmodule.: checked out" actual &&
 | 
			
		||||
	 test_i18ngrep "Submodule path .submodule/subsubmodule.: .git reset --hard -q" actual &&
 | 
			
		||||
	 (cd submodule/subsubmodule &&
 | 
			
		||||
	  git log > ../../expected
 | 
			
		||||
	 ) &&
 | 
			
		||||
| 
						 | 
				
			
			@ -775,4 +778,37 @@ test_expect_success 'submodule update --recursive drops module name before recur
 | 
			
		|||
	)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'submodule update --checkout clones detached HEAD' '
 | 
			
		||||
	git clone super super4 &&
 | 
			
		||||
	echo "detached HEAD" >expected &&
 | 
			
		||||
	(cd super4 &&
 | 
			
		||||
	 git reset --hard initial-setup &&
 | 
			
		||||
	 git submodule init submodule &&
 | 
			
		||||
	 git submodule update >> /tmp/log 2>&1 &&
 | 
			
		||||
	 (cd submodule &&
 | 
			
		||||
	  git symbolic-ref HEAD > ../../actual ||
 | 
			
		||||
	  echo "detached HEAD" > ../../actual
 | 
			
		||||
	 )
 | 
			
		||||
	) &&
 | 
			
		||||
	test_cmp actual expected &&
 | 
			
		||||
	rm -rf super4
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'submodule update --merge clones attached HEAD' '
 | 
			
		||||
	git clone super super4 &&
 | 
			
		||||
	echo "refs/heads/master" >expected &&
 | 
			
		||||
	(cd super4 &&
 | 
			
		||||
	 git reset --hard initial-setup &&
 | 
			
		||||
	 git submodule init submodule &&
 | 
			
		||||
	 git config submodule.submodule.update merge &&
 | 
			
		||||
	 git submodule update --merge &&
 | 
			
		||||
	 (cd submodule &&
 | 
			
		||||
	  git symbolic-ref HEAD > ../../actual ||
 | 
			
		||||
	  echo "detached HEAD" > ../../actual
 | 
			
		||||
	 )
 | 
			
		||||
	) &&
 | 
			
		||||
	test_cmp actual expected &&
 | 
			
		||||
	rm -rf super4
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_done
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue