All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC] Introduce git submodule add|update --attach
@ 2013-12-30  1:49 Francesco Pretto
  2013-12-31 20:05 ` Phil Hord
  2014-01-02 20:07 ` Junio C Hamano
  0 siblings, 2 replies; 144+ messages in thread
From: Francesco Pretto @ 2013-12-30  1:49 UTC (permalink / raw)
  To: git; +Cc: Francesco Pretto

Hello everybody,

by default "git submodule" performs its add or update operations on a detached
HEAD. This works well when using an existing full-fledged/indipendent project as
the submodule, as there's less frequent need to update it or commit back
changes. When the submodule is actually a large portion of shareable code
between  different projects, and the superproject needs to track very closely
the evolution of the submodule (or the other way around), I feel more confortable
to reattach the HEAD of the submodule with an existing branch. This can be as
simple as having a superproject "project1" in branch "master" with a submodule
"common" attached to the branch "master-project1" or, in a more development
workflow, "project1" in branch "featureA" with the same submodule "common"
attached to a similarly named branch "featureA". Doing this in git requires me
the following:

# Maintainer
$ git submodule add --branch "master-project1" <repository> common
$ git commit -m "Added submodule"
$ git config -f .gitmodules submodule.common.ignore all
$ git push
$ cd <path>
$ git checkout "master-project1"

# Developer
$ git pull
$ git submodule init
$ git submodule update --remote
$ cd <path>
$ branch="$(git config -f ..\.gitmodules submodule.common.branch)"; git checkout $branch

While the burden for the repository maitainer/administrator is acceptable, in
the developer point of view there are two problems:
1) Checking out an attached HEAD of a specified branch as when using "--remote"
is not really simple as it could be and could require lauching of scrips or
reading some repository specific documentation. Also in Windows platform the
syntax for inline shell evaluation of commands is less known between users;
2) There's no way to store a similar default behaviour in the repository except
by using scripts. Also recently submodule.<modulename>.update custom !commands
in no more supported when stored in .gitmodules [1].

The attached patch tries to solve these problems by introducing an "--attach"
switch to the "add" and "update" submodule commands and a "--detach" switch just
for the "update" command. It also add the support for an 'submodule.<name>.attach'
property when updating. Using the "--attach" switch when adding a submodule does:
- create the submodule checking out an attached HEAD;
- set the 'submodule.<name>.attach' property to 'true';
- set the 'submodule.<name>.ignore' property to 'all' (this is useful as
attaching to the branch doesn't require tracking of revision sha1).

The rationale of setting 'attach' and 'ignore' properties when adding a
submodule with the "--attach" switch is to give a convenient default behaviour.
No other properties are set: the repository responsible will still be required
to configure a different 'submodule.<name>.update' behaviour separetely, if he
wants that.

When updating, using the '--attach' switch or operating in a repository with
'submodule.<name>.attach' set to 'true' will:
- checkout a branch with an attached HEAD if the repository was just cloned;
- perform a fast-forward only merge of changes if it's a 'checkout' update,
keeping the HEAD attached;
- reattach the HEAD prior performing a 'merge', 'rebase' or '!command' update
operation if the HEAD was found detached.

'--attach' or 'submodule.<name>.attach' set to true also implies '--remote', as
it's needed the origin HEAD sha1 to verify the current HEAD state.

A '--detach' switch is also available. Using the '--detach' switch or
operating in a repository with 'submodule.<name>.attach' set to 'false' during
update will:
- checkout a detached HEAD if the repository was just cloned (same behaviour as
before);
- detach the HEAD prior performing a 'merge', 'rebase' or '!command' update
operation if the HEAD was found attached.

'submodule.<name>.attach' works the same way as 'submodule.<name>.update'
property: git copies the values found in ".gitmodules" in ".git/config" when
performing an "init" command. "update" looks for the values in ".git/config"
only.

'--attach' and '--detach' switches override an opposite behaviour of 'submodule.<name>.attach'
properties.

The patch is small (touches only git-submodule.sh) and 100% additive with
respect to currently documented behaviour: when using "add" and "update"
commands without the introduced switches and properties, git shall operate as
before. As a bonus (but this was done to ease conditionals and keep the code
clean) it also clarifies and validates the content of 'submodule.<name>.update'
during 'update' command, warning the user if it's not one of the supported
values 'checkout', 'merge', 'rebase' and 'none'. Please note that 'checkout'
update command was documented in upstream "Documentation/gitmodules.txt" [2] as
a valid 'submodule.<name>.update' value and code in upstream "git-submodule.sh"
implicitly assumes it as recognized value. "Documentation/git-submodule.txt"
doesn't mention it properly and I guess this is the reason why it wasn't
considered for the validation in [1] patch.

Using this patch, the previous workflow becomes:

# Maintainer
$ git submodule add --branch "master-project1" --attach <repository> <path>
$ git commit -m "Added submodule"
$ git push

# Developer
$ git pull
$ git submodule init
$ git submodule update

Is there interest in supporting this workflow and seeing this patch applied?

Thanks,
Francesco

[1] http://marc.info/?l=git&m=138610752125816&w=2
[2] Documentation/gitmodules.txt: "If 'checkout' (the default)..."

Signed-off-by: Francesco Pretto <ceztko@gmail.com>
---
 Documentation/git-submodule.txt |  37 ++++++---
 Documentation/gitmodules.txt    |  11 ++-
 git-submodule.sh                | 172 +++++++++++++++++++++++++++++++++++++---
 3 files changed, 197 insertions(+), 23 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index bfef8a0..452376d 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -10,13 +10,14 @@ SYNOPSIS
 --------
 [verse]
 'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
-	      [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
+	      [--reference <repository>] [--attach] [--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>] [--depth <depth>]
-	      [--merge] [--recursive] [--] [<path>...]
+	      [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach]
+	      [--depth <depth>] [--merge] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
 	      [commit] [--] [<path>...]
 'git submodule' [--quiet] foreach [--recursive] <command>
@@ -107,6 +108,10 @@ is the superproject and submodule repositories will be kept
 together in the same relative location, and only the
 superproject's URL needs to be provided: git-submodule will correctly
 locate the submodule using the relative URL in .gitmodules.
++
+If `--attach` is specified, the submodule will be registered to be
+checked out with an an attached HEAD. Also `submodule.<name>.attach` will
+be set to `true` and `submodule.<name>.ignore` will be set to `all`.
 
 status::
 	Show the status of the submodules. This will print the SHA-1 of the
@@ -156,12 +161,15 @@ 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.
+	This will make the submodules HEAD be detached unless `--attach` is
+	specified or `submodule.$name.attach` is set to `true`. The last setting
+	can always be overridden specifying `--detach`. Update mode can be
+	selected specifying `--checkout`, `--rebase` or `--merge` switches
+	or setting the key `submodule.$name.update` to `checkout`, `rebase`,
+	`merge` or `none`. `none` will cause the submodule to be skipped during
+	the update. 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
@@ -270,6 +278,17 @@ OPTIONS
 	be overridden by setting the `submodule.<name>.branch` option in
 	either `.gitmodules` or `.git/config` (with `.git/config` taking
 	precedence).
+
+--attach::
+	This option is only valid for the add and update commands. Cause the
+	result of an add or update operation to be an attached HEAD. In the
+	update command , if `submodule.<name>.branch` is not set, it will
+	default to `master`. Note: for the update command `--attach` also
+	implies `--remote`.
+
+--detach::
+	This option is only valid for the update command. Cause the result
+	of the update operation to be forcedly a detached HEAD.
 +
 This works for any of the supported update procedures (`--checkout`,
 `--rebase`, etc.).  The only change is the source of the target SHA-1.
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index f7be93f..e6c3360 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -37,8 +37,10 @@ submodule.<name>.url::
 
 submodule.<name>.update::
 	Defines what to do when the submodule is updated by the superproject.
-	If 'checkout' (the default), the new commit specified in the
-	superproject will be checked out in the submodule on a detached HEAD.
+	If 'checkout' (the default), the new commit (or the branch, when using
+	the '--attach' switch or the 'submodule.<name>.attach' property is set
+	to 'true' during an update operation) specified in the superproject will
+	be checked out in the submodule.
 	If 'rebase', the current branch of the submodule will be rebased onto
 	the commit specified in the superproject. If 'merge', the commit
 	specified in the superproject will be merged into the current branch
@@ -54,6 +56,11 @@ submodule.<name>.branch::
 	If the option is not specified, it defaults to 'master'.  See the
 	`--remote` documentation in linkgit:git-submodule[1] for details.
 
+submodule.<name>.attach::
+	Determine if the update operation will produce a detached HEAD or not.
+	Valid values are `true` or `false`. If the property is set to `true`
+	and `submodule.<name>.branch`, it will default to `master`
+
 submodule.<name>.fetchRecurseSubmodules::
 	This option can be used to control recursive fetching of this
 	submodule. If this option is also present in the submodules entry in
diff --git a/git-submodule.sh b/git-submodule.sh
index 2677f2e..3951fa2 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -5,11 +5,11 @@
 # Copyright (c) 2007 Lars Hjemli
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
+USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--attach] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
-   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach] [--merge] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
@@ -36,6 +36,7 @@ update=
 prefix=
 custom_name=
 depth=
+attach=
 
 # The function takes at most 2 arguments. The first argument is the
 # URL that navigates to the submodule origin repo. When relative, this URL
@@ -352,6 +353,9 @@ cmd_add()
 			custom_name=$2
 			shift
 			;;
+		--attach)
+			attach="true"
+			;;
 		--depth)
 			case "$2" in '') usage ;; esac
 			depth="--depth=$2"
@@ -475,8 +479,17 @@ Use -f if you really want to add it." >&2
 			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" ;;
+			'')
+				git checkout -f -q
+				;;
+			?*)
+				if test -n "$attach"
+				then
+					git checkout -f -q "$branch"
+				else
+					git checkout -f -q -B "$branch" "origin/$branch"
+				fi
+				;;
 			esac
 		) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
 	fi
@@ -491,6 +504,12 @@ Use -f if you really want to add it." >&2
 	then
 		git config -f .gitmodules submodule."$sm_name".branch "$branch"
 	fi &&
+	if test -n "$attach"
+	then
+		# We'll stay stick to the HEAD, no need to track revision sha1
+		git config -f .gitmodules submodule."$sm_name".attach "true"
+		git config -f .gitmodules submodule."$sm_name".ignore "all"
+	fi &&
 	git add --force .gitmodules ||
 	die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
 }
@@ -622,7 +641,7 @@ cmd_init()
 		   test -z "$(git config submodule."$name".update)"
 		then
 			case "$upd" in
-			rebase | merge | none)
+			checkout | rebase | merge | none)
 				;; # known modes of updating
 			*)
 				echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
@@ -632,6 +651,23 @@ cmd_init()
 			git config submodule."$name".update "$upd" ||
 			die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
 		fi
+
+		# Copy "attach" setting when it is not set yet
+		if attached="$(git config -f .gitmodules submodule."$name".attach)" &&
+		   test -n "$attached" &&
+		   test -z "$(git config submodule."$name".attach)"
+		then
+			case "$attached" in
+			true | false)
+				;; # Valid attach flag values
+			*)
+				echo >&2 "warning: invalid attach flag value for submodule '$name'"
+				upd=none
+				;;
+			esac
+			git config submodule."$name".attach "$attached" ||
+			die "$(eval_gettext "Failed to register attached option for submodule path '\$displaypath'")"
+		fi
 	done
 }
 
@@ -750,6 +786,14 @@ cmd_update()
 		--reference=*)
 			reference="$1"
 			;;
+		--attach)
+			if test "$attach" = "false" ; then usage ; fi
+			attach="true"
+			;;
+		--detach)
+			if test "$attach" = "true" ; then usage ; fi
+			attach="false"
+			;;
 		-m|--merge)
 			update="merge"
 			;;
@@ -800,11 +844,44 @@ cmd_update()
 		name=$(module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		branch=$(get_submodule_config "$name" branch master)
+		if test -n "$attach"
+		then
+			attach_module=$attach
+		else
+			attach_module=$(git config submodule."$name".attach)
+			case "$attach_module" in
+			'')
+				;; # Unset attach flag
+			true|false)
+				;; # Valid attach flag values
+			*)
+				echo >&2 "warning: invalid attach flag value for submodule '$name'"
+				attach_module=
+				;;
+			esac
+		fi
+		if test "$attach_module" = "false"
+		then
+			# Normalize attach 'false' flag value
+			attach_module=
+		fi
 		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
+			*)
+				update_module=
+				echo >&2 "warning: invalid update mode for submodule '$name'"
+				;;
+			esac
 		fi
 
 		displaypath=$(relative_path "$prefix$sm_path")
@@ -836,7 +913,7 @@ Maybe you want to use 'update --init'?")"
 			die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
 		fi
 
-		if test -n "$remote"
+		if test -n "$remote" -o -n "$attach_module"
 		then
 			if test -z "$nofetch"
 			then
@@ -850,7 +927,16 @@ Maybe you want to use 'update --init'?")"
 			die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
 		fi
 
-		if test "$subsha1" != "$sha1" -o -n "$force"
+		head_rev_ref=$(clear_local_git_env; cd "$sm_path" && git rev-parse --abbrev-ref HEAD) ||
+		die "$(eval_gettext "Unable to determine revision ref in submodule path '\$sm_path'")"
+		if test "$head_rev_ref" = "HEAD"
+		then
+			# Determine if the HEAD is detached
+			head_detached="true"
+		fi
+
+		if test "$subsha1" != "$sha1" || test -n "$attach_module" -a -n "$head_detached" ||
+			test -z "$attach_module" -a -z "$head_detached" || test -n "$force"
 		then
 			subforce=$force
 			# If we don't already have a -f flag and the submodule has never been checked out
@@ -870,40 +956,102 @@ Maybe you want to use 'update --init'?")"
 			fi
 
 			# Is this something we just cloned?
+			just_cloned=
 			case ";$cloned_modules;" in
 			*";$name;"*)
 				# then there is no local change to integrate
-				update_module= ;;
+				update_module="checkout"
+				just_cloned=yes
+				;;
 			esac
 
+			if test -z "$update_module"
+			then
+				# Fallback to checkout
+				update_module="checkout"
+			fi
+			
+			command_pre=:
+			suffix_pre=
+			if test "$update_module" = "checkout"
+			then
+				if test -n "$attach_module" -a -z "$just_cloned"
+				then
+					# We need to attach to the HEAD/switch the branch prior
+					# performing any fast-forward update
+					command_pre="git checkout $subforce -q"
+					suffix_pre=$branch
+				fi
+			else
+				if test -n "$attach_module" -a -n "$head_detached"
+				then
+					# We need to reattach to the head
+					command_pre="git checkout $subforce -q"
+					suffix_pre=$branch
+				elif test -z "$attach_module" -a -z "$head_detached"
+				then
+					# We need to detach from the head
+					command_pre="git checkout $subforce -q"
+					suffix_pre=$sha1
+				fi
+			fi
+
 			must_die_on_failure=
+			custom_update=
+			suffix=
 			case "$update_module" in
 			rebase)
 				command="git rebase"
+				suffix=$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"
+				suffix=$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
 				;;
+			checkout)
+				if test -n "$attach_module"
+				then
+					if test -n "$just_cloned"
+					then
+						command="git checkout $subforce -q"
+						suffix=$branch
+					else
+						# Perform a fast-forward only merge of the origin
+						command="git merge $subforce --ff-only"
+						suffix="origin/$branch"
+					fi
+					die_msg="$(eval_gettext "Unable to checkout banch '\$branch' in submodule path '\$displaypath'")"
+					say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out branch '\$branch'")"
+				else
+					command="git checkout $subforce -q"
+					suffix=$sha1
+					die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
+					say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
+				fi
+				;;
 			!*)
 				command="${update_module#!}"
+				suffix=$sha1
 				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
+				custom_update=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'")"
+				# Valid user configurable update modes are already filtered above
+				die "$(eval_gettext "Unexpected update mode in the current flow")"
 				;;
 			esac
 
-			if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
+			if (clear_local_git_env; cd "$sm_path" &&
+				$command_pre "$suffix_pre" &&
+				$command "$suffix")
 			then
 				say "$say_msg"
 			elif test -n "$must_die_on_failure"
-- 
1.8.5.2.227.g53f3478.dirty

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [PATCH/RFC] Introduce git submodule add|update --attach
  2013-12-30  1:49 [PATCH/RFC] Introduce git submodule add|update --attach Francesco Pretto
@ 2013-12-31 20:05 ` Phil Hord
  2014-01-02 18:48   ` Francesco Pretto
  2014-01-02 20:07 ` Junio C Hamano
  1 sibling, 1 reply; 144+ messages in thread
From: Phil Hord @ 2013-12-31 20:05 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: git

On Sun, Dec 29, 2013 at 8:49 PM, Francesco Pretto <ceztko@gmail.com> wrote:
>
> by default "git submodule" performs its add or update operations on a detached
> HEAD. This works well when using an existing full-fledged/indipendent project as
> the submodule, as there's less frequent need to update it or commit back
> changes. When the submodule is actually a large portion of shareable code
> between  different projects, and the superproject needs to track very closely
> the evolution of the submodule (or the other way around), I feel more confortable
> to reattach the HEAD of the submodule with an existing branch. This can be as
> simple as having a superproject "project1" in branch "master" with a submodule
> "common" attached to the branch "master-project1" or, in a more development
> workflow, "project1" in branch "featureA" with the same submodule "common"
> attached to a similarly named branch "featureA". Doing this in git requires me
> the following:
>
> # Maintainer
> $ git submodule add --branch "master-project1" <repository> common
> $ git commit -m "Added submodule"
> $ git config -f .gitmodules submodule.common.ignore all
> $ git push
> $ cd <path>
> $ git checkout "master-project1"
>
> # Developer
> $ git pull
> $ git submodule init
> $ git submodule update --remote
> $ cd <path>
> $ branch="$(git config -f ..\.gitmodules submodule.common.branch)"; git checkout $branch
>
> While the burden for the repository maitainer/administrator is acceptable, in
> the developer point of view there are two problems:
> 1) Checking out an attached HEAD of a specified branch as when using "--remote"
> is not really simple as it could be and could require lauching of scrips or
> reading some repository specific documentation. Also in Windows platform the
> syntax for inline shell evaluation of commands is less known between users;
> 2) There's no way to store a similar default behaviour in the repository except
> by using scripts. Also recently submodule.<modulename>.update custom !commands
> in no more supported when stored in .gitmodules [1].
>
> The attached patch tries to solve these problems by introducing an "--attach"
> switch to the "add" and "update" submodule commands and a "--detach" switch just
> for the "update" command. It also add the support for an 'submodule.<name>.attach'
> property when updating. Using the "--attach" switch when adding a submodule does:
> - create the submodule checking out an attached HEAD;
> - set the 'submodule.<name>.attach' property to 'true';
> - set the 'submodule.<name>.ignore' property to 'all' (this is useful as
> attaching to the branch doesn't require tracking of revision sha1).
>
> The rationale of setting 'attach' and 'ignore' properties when adding a
> submodule with the "--attach" switch is to give a convenient default behaviour.
> No other properties are set: the repository responsible will still be required
> to configure a different 'submodule.<name>.update' behaviour separetely, if he
> wants that.
>
> When updating, using the '--attach' switch or operating in a repository with
> 'submodule.<name>.attach' set to 'true' will:
> - checkout a branch with an attached HEAD if the repository was just cloned;
> - perform a fast-forward only merge of changes if it's a 'checkout' update,
> keeping the HEAD attached;
> - reattach the HEAD prior performing a 'merge', 'rebase' or '!command' update
> operation if the HEAD was found detached.

I need to understand this "reattach the HEAD" case better. Can you
give some examples of the expected behavior when merge, rebase or
!command is encountered?


> '--attach' or 'submodule.<name>.attach' set to true also implies '--remote', as
> it's needed the origin HEAD sha1 to verify the current HEAD state.
>
> A '--detach' switch is also available. Using the '--detach' switch or
> operating in a repository with 'submodule.<name>.attach' set to 'false' during
> update will:
> - checkout a detached HEAD if the repository was just cloned (same behaviour as
> before);
> - detach the HEAD prior performing a 'merge', 'rebase' or '!command' update
> operation if the HEAD was found attached.
>
> 'submodule.<name>.attach' works the same way as 'submodule.<name>.update'
> property: git copies the values found in ".gitmodules" in ".git/config" when
> performing an "init" command. "update" looks for the values in ".git/config"
> only.
>
> '--attach' and '--detach' switches override an opposite behaviour of 'submodule.<name>.attach'
> properties.
>
> The patch is small (touches only git-submodule.sh) and 100% additive with
> respect to currently documented behaviour: when using "add" and "update"
> commands without the introduced switches and properties, git shall operate as
> before. As a bonus (but this was done to ease conditionals and keep the code
> clean) it also clarifies and validates the content of 'submodule.<name>.update'
> during 'update' command, warning the user if it's not one of the supported
> values 'checkout', 'merge', 'rebase' and 'none'. Please note that 'checkout'
> update command was documented in upstream "Documentation/gitmodules.txt" [2] as
> a valid 'submodule.<name>.update' value and code in upstream "git-submodule.sh"
> implicitly assumes it as recognized value. "Documentation/git-submodule.txt"
> doesn't mention it properly and I guess this is the reason why it wasn't
> considered for the validation in [1] patch.
>
> Using this patch, the previous workflow becomes:
>
> # Maintainer
> $ git submodule add --branch "master-project1" --attach <repository> <path>
> $ git commit -m "Added submodule"
> $ git push
>
> # Developer
> $ git pull
> $ git submodule init
> $ git submodule update
>
> Is there interest in supporting this workflow and seeing this patch applied?
>
> Thanks,
> Francesco
>
> [1] http://marc.info/?l=git&m=138610752125816&w=2
> [2] Documentation/gitmodules.txt: "If 'checkout' (the default)..."
>
> Signed-off-by: Francesco Pretto <ceztko@gmail.com>
> ---
>  Documentation/git-submodule.txt |  37 ++++++---
>  Documentation/gitmodules.txt    |  11 ++-
>  git-submodule.sh                | 172 +++++++++++++++++++++++++++++++++++++---
>  3 files changed, 197 insertions(+), 23 deletions(-)
>
> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
> index bfef8a0..452376d 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -10,13 +10,14 @@ SYNOPSIS
>  --------
>  [verse]
>  'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
> -             [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
> +             [--reference <repository>] [--attach] [--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>] [--depth <depth>]
> -             [--merge] [--recursive] [--] [<path>...]
> +             [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach]
> +             [--depth <depth>] [--merge] [--recursive] [--] [<path>...]
>  'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
>               [commit] [--] [<path>...]
>  'git submodule' [--quiet] foreach [--recursive] <command>
> @@ -107,6 +108,10 @@ is the superproject and submodule repositories will be kept
>  together in the same relative location, and only the
>  superproject's URL needs to be provided: git-submodule will correctly
>  locate the submodule using the relative URL in .gitmodules.
> ++
> +If `--attach` is specified, the submodule will be registered to be
> +checked out with an an attached HEAD. Also `submodule.<name>.attach` will
> +be set to `true` and `submodule.<name>.ignore` will be set to `all`.
>
>  status::
>         Show the status of the submodules. This will print the SHA-1 of the
> @@ -156,12 +161,15 @@ 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.
> +       This will make the submodules HEAD be detached unless `--attach` is
> +       specified or `submodule.$name.attach` is set to `true`. The last setting
> +       can always be overridden specifying `--detach`. Update mode can be
> +       selected specifying `--checkout`, `--rebase` or `--merge` switches
> +       or setting the key `submodule.$name.update` to `checkout`, `rebase`,
> +       `merge` or `none`. `none` will cause the submodule to be skipped during
> +       the update. 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
> @@ -270,6 +278,17 @@ OPTIONS
>         be overridden by setting the `submodule.<name>.branch` option in
>         either `.gitmodules` or `.git/config` (with `.git/config` taking
>         precedence).
> +
> +--attach::
> +       This option is only valid for the add and update commands. Cause the

Grammar: 'Causes the result'

> +       result of an add or update operation to be an attached HEAD. In the
> +       update command , if `submodule.<name>.branch` is not set, it will

typo: space before comma.

Also, the pronoun "it" here is unclear to me.  Does this convey the
correct meaning?

   In the update operation, the branch named by 'submodule.<name>.branch' is
   checked out as the new HEAD of the submodule repository. If
   'submodule.<name>.branch' is not set, the 'master' branch is
checked out as the
   new HEAD of the submodule.

> +       default to `master`. Note: for the update command `--attach` also
> +       implies `--remote`.
> +
> +--detach::
> +       This option is only valid for the update command. Cause the result

 Grammar: 'Causes the result'

> +       of the update operation to be forcedly a detached HEAD.

"Forcedly" is a bit strong, maybe, slightly misplaced, and not a word,
besides.   How's this, instead:

   Forces the result of the update operation to be a detached HEAD in
the submodule.

>  +
>  This works for any of the supported update procedures (`--checkout`,
>  `--rebase`, etc.).  The only change is the source of the target SHA-1.
> diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
> index f7be93f..e6c3360 100644
> --- a/Documentation/gitmodules.txt
> +++ b/Documentation/gitmodules.txt
> @@ -37,8 +37,10 @@ submodule.<name>.url::
>
>  submodule.<name>.update::
>         Defines what to do when the submodule is updated by the superproject.
> -       If 'checkout' (the default), the new commit specified in the
> -       superproject will be checked out in the submodule on a detached HEAD.
> +       If 'checkout' (the default), the new commit (or the branch, when using
> +       the '--attach' switch or the 'submodule.<name>.attach' property is set
> +       to 'true' during an update operation) specified in the superproject will
> +       be checked out in the submodule.

IMHO, this wording is overcomplicated by this change.  How about:

       If 'checkout' (the default), the new commit specified in the superproject
       (or branch, with '--attach') will be checked out in the submodule.

>         If 'rebase', the current branch of the submodule will be rebased onto
>         the commit specified in the superproject. If 'merge', the commit
>         specified in the superproject will be merged into the current branch

Does the 'merge', 'rebase' and '!command' description need to be
updated, too?  Here and above it seems to still suggest the old
behavior is kept when --attach is used.


> @@ -54,6 +56,11 @@ submodule.<name>.branch::
>         If the option is not specified, it defaults to 'master'.  See the
>         `--remote` documentation in linkgit:git-submodule[1] for details.
>
> +submodule.<name>.attach::
> +       Determine if the update operation will produce a detached HEAD or not.
> +       Valid values are `true` or `false`. If the property is set to `true`
> +       and `submodule.<name>.branch`, it will default to `master`

I think you mean "...and 'submodule.<name>.branch' is not set, it
will...", right?

Some explanation of what happens when it _is_ set would be useful
here, too, I think.  But maybe I do not understand the nuances yet.

> +
>  submodule.<name>.fetchRecurseSubmodules::
>         This option can be used to control recursive fetching of this
>         submodule. If this option is also present in the submodules entry in
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 2677f2e..3951fa2 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -5,11 +5,11 @@
>  # Copyright (c) 2007 Lars Hjemli
>
>  dashless=$(basename "$0" | sed -e 's/-/ /')
> -USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
> +USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--attach] [--] <repository> [<path>]
>     or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
>     or: $dashless [--quiet] init [--] [<path>...]
>     or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
> -   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
> +   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach] [--merge] [--recursive] [--] [<path>...]
>     or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
>     or: $dashless [--quiet] foreach [--recursive] <command>
>     or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
> @@ -36,6 +36,7 @@ update=
>  prefix=
>  custom_name=
>  depth=
> +attach=
>
>  # The function takes at most 2 arguments. The first argument is the
>  # URL that navigates to the submodule origin repo. When relative, this URL
> @@ -352,6 +353,9 @@ cmd_add()
>                         custom_name=$2
>                         shift
>                         ;;
> +               --attach)
> +                       attach="true"
> +                       ;;
>                 --depth)
>                         case "$2" in '') usage ;; esac
>                         depth="--depth=$2"
> @@ -475,8 +479,17 @@ Use -f if you really want to add it." >&2
>                         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" ;;
> +                       '')
> +                               git checkout -f -q
> +                               ;;

Is this whitespace change intentional and necessary?

> +                       ?*)
> +                               if test -n "$attach"
> +                               then
> +                                       git checkout -f -q "$branch"
> +                               else
> +                                       git checkout -f -q -B "$branch" "origin/$branch"
> +                               fi
> +                               ;;
>                         esac
>                 ) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
>         fi
> @@ -491,6 +504,12 @@ Use -f if you really want to add it." >&2
>         then
>                 git config -f .gitmodules submodule."$sm_name".branch "$branch"
>         fi &&
> +       if test -n "$attach"
> +       then
> +               # We'll stay stick to the HEAD, no need to track revision sha1
> +               git config -f .gitmodules submodule."$sm_name".attach "true"
> +               git config -f .gitmodules submodule."$sm_name".ignore "all"
> +       fi &&
>         git add --force .gitmodules ||
>         die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
>  }
> @@ -622,7 +641,7 @@ cmd_init()
>                    test -z "$(git config submodule."$name".update)"
>                 then
>                         case "$upd" in
> -                       rebase | merge | none)
> +                       checkout | rebase | merge | none)

This belongs in a commit of its own.

>                                 ;; # known modes of updating
>                         *)
>                                 echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
> @@ -632,6 +651,23 @@ cmd_init()
>                         git config submodule."$name".update "$upd" ||
>                         die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
>                 fi
> +
> +               # Copy "attach" setting when it is not set yet
> +               if attached="$(git config -f .gitmodules submodule."$name".attach)" &&
> +                  test -n "$attached" &&
> +                  test -z "$(git config submodule."$name".attach)"
> +               then
> +                       case "$attached" in
> +                       true | false)
> +                               ;; # Valid attach flag values
> +                       *)
> +                               echo >&2 "warning: invalid attach flag value for submodule '$name'"
> +                               upd=none
> +                               ;;
> +                       esac
> +                       git config submodule."$name".attach "$attached" ||
> +                       die "$(eval_gettext "Failed to register attached option for submodule path '\$displaypath'")"
> +               fi
>         done
>  }
>
> @@ -750,6 +786,14 @@ cmd_update()
>                 --reference=*)
>                         reference="$1"
>                         ;;
> +               --attach)
> +                       if test "$attach" = "false" ; then usage ; fi
> +                       attach="true"
> +                       ;;
> +               --detach)
> +                       if test "$attach" = "true" ; then usage ; fi
> +                       attach="false"
> +                       ;;
>                 -m|--merge)
>                         update="merge"
>                         ;;
> @@ -800,11 +844,44 @@ cmd_update()
>                 name=$(module_name "$sm_path") || exit
>                 url=$(git config submodule."$name".url)
>                 branch=$(get_submodule_config "$name" branch master)
> +               if test -n "$attach"
> +               then
> +                       attach_module=$attach
> +               else
> +                       attach_module=$(git config submodule."$name".attach)
> +                       case "$attach_module" in
> +                       '')
> +                               ;; # Unset attach flag
> +                       true|false)
> +                               ;; # Valid attach flag values
> +                       *)
> +                               echo >&2 "warning: invalid attach flag value for submodule '$name'"
> +                               attach_module=
> +                               ;;
> +                       esac
> +               fi
> +               if test "$attach_module" = "false"
> +               then
> +                       # Normalize attach 'false' flag value
> +                       attach_module=
> +               fi
>                 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
> +                       *)
> +                               update_module=
> +                               echo >&2 "warning: invalid update mode for submodule '$name'"
> +                               ;;
> +                       esac

Probably belongs to the same "other" commit mentioned before.

>                 fi
>
>                 displaypath=$(relative_path "$prefix$sm_path")
> @@ -836,7 +913,7 @@ Maybe you want to use 'update --init'?")"
>                         die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
>                 fi
>
> -               if test -n "$remote"
> +               if test -n "$remote" -o -n "$attach_module"
>                 then
>                         if test -z "$nofetch"
>                         then
> @@ -850,7 +927,16 @@ Maybe you want to use 'update --init'?")"
>                         die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
>                 fi
>
> -               if test "$subsha1" != "$sha1" -o -n "$force"
> +               head_rev_ref=$(clear_local_git_env; cd "$sm_path" && git rev-parse --abbrev-ref HEAD) ||
> +               die "$(eval_gettext "Unable to determine revision ref in submodule path '\$sm_path'")"
> +               if test "$head_rev_ref" = "HEAD"
> +               then
> +                       # Determine if the HEAD is detached
> +                       head_detached="true"
> +               fi
> +
> +               if test "$subsha1" != "$sha1" || test -n "$attach_module" -a -n "$head_detached" ||
> +                       test -z "$attach_module" -a -z "$head_detached" || test -n "$force"
>                 then
>                         subforce=$force
>                         # If we don't already have a -f flag and the submodule has never been checked out
> @@ -870,40 +956,102 @@ Maybe you want to use 'update --init'?")"
>                         fi
>
>                         # Is this something we just cloned?
> +                       just_cloned=
>                         case ";$cloned_modules;" in
>                         *";$name;"*)
>                                 # then there is no local change to integrate
> -                               update_module= ;;
> +                               update_module="checkout"
> +                               just_cloned=yes
> +                               ;;
>                         esac
>
> +                       if test -z "$update_module"
> +                       then
> +                               # Fallback to checkout
> +                               update_module="checkout"
> +                       fi
> +
> +                       command_pre=:
> +                       suffix_pre=
> +                       if test "$update_module" = "checkout"
> +                       then
> +                               if test -n "$attach_module" -a -z "$just_cloned"
> +                               then
> +                                       # We need to attach to the HEAD/switch the branch prior
> +                                       # performing any fast-forward update
> +                                       command_pre="git checkout $subforce -q"
> +                                       suffix_pre=$branch
> +                               fi
> +                       else
> +                               if test -n "$attach_module" -a -n "$head_detached"
> +                               then
> +                                       # We need to reattach to the head
> +                                       command_pre="git checkout $subforce -q"
> +                                       suffix_pre=$branch
> +                               elif test -z "$attach_module" -a -z "$head_detached"
> +                               then
> +                                       # We need to detach from the head
> +                                       command_pre="git checkout $subforce -q"
> +                                       suffix_pre=$sha1
> +                               fi
> +                       fi
> +
>                         must_die_on_failure=
> +                       custom_update=
> +                       suffix=
>                         case "$update_module" in
>                         rebase)
>                                 command="git rebase"
> +                               suffix=$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"
> +                               suffix=$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
>                                 ;;
> +                       checkout)
> +                               if test -n "$attach_module"
> +                               then
> +                                       if test -n "$just_cloned"
> +                                       then
> +                                               command="git checkout $subforce -q"
> +                                               suffix=$branch
> +                                       else
> +                                               # Perform a fast-forward only merge of the origin
> +                                               command="git merge $subforce --ff-only"
> +                                               suffix="origin/$branch"
> +                                       fi
> +                                       die_msg="$(eval_gettext "Unable to checkout banch '\$branch' in submodule path '\$displaypath'")"
> +                                       say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out branch '\$branch'")"
> +                               else
> +                                       command="git checkout $subforce -q"
> +                                       suffix=$sha1
> +                                       die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
> +                                       say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
> +                               fi
> +                               ;;
>                         !*)
>                                 command="${update_module#!}"
> +                               suffix=$sha1
>                                 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
> +                               custom_update=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'")"
> +                               # Valid user configurable update modes are already filtered above
> +                               die "$(eval_gettext "Unexpected update mode in the current flow")"
>                                 ;;
>                         esac
>
> -                       if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
> +                       if (clear_local_git_env; cd "$sm_path" &&
> +                               $command_pre "$suffix_pre" &&
> +                               $command "$suffix")
>                         then
>                                 say "$say_msg"
>                         elif test -n "$must_die_on_failure"

I didn't have time to parse out all these conditional completion
commands in this review, but the feature seems sane to me, as I
understand it.

Phil

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH/RFC] Introduce git submodule add|update --attach
  2013-12-31 20:05 ` Phil Hord
@ 2014-01-02 18:48   ` Francesco Pretto
  2014-01-13 17:31     ` Junio C Hamano
  0 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-02 18:48 UTC (permalink / raw)
  To: Phil Hord; +Cc: git

Thanks for the comments, my replies below. Before, a couple of general
questions:
- I'm also writing some tests, should I commit them together with the
feature patch?
- to determine the attached/detached state I did this:

head_detached=
if test "$(rev-parse --abbrev-ref HEAD)" = "HEAD"
then
    head_detached="true"
fi

Is this correct?

2013/12/31 Phil Hord <phil.hord@gmail.com>
>
> On Sun, Dec 29, 2013 at 8:49 PM, Francesco Pretto <ceztko@gmail.com> wrote:
>  [...]
> >
> > When updating, using the '--attach' switch or operating in a repository with
> > 'submodule.<name>.attach' set to 'true' will:
> > - checkout a branch with an attached HEAD if the repository was just cloned;
> > - perform a fast-forward only merge of changes if it's a 'checkout' update,
> > keeping the HEAD attached;
> > - reattach the HEAD prior performing a 'merge', 'rebase' or '!command' update
> > operation if the HEAD was found detached.
>
> I need to understand this "reattach the HEAD" case better. Can you
> give some examples of the expected behavior when merge, rebase or
> !command is encountered?
>

Thanks for pointing this out, actually my patch was a bit lacking at
this. Reattaching the HEAD prior to merge, rebase or "!command" would
have caused just a *silent* "git checkout "<branch>", possibly leaving
orphaned commits forgotten.

My plans for the patch are now to implement this safer and, IMO,
intuitive behavior: let set say we have a submodule "mod" with the
HEAD detached at orphaned commit <orphaned-sha1>. Let say
"origin/<branch>" is at commit <origin-sha1>. Let say I set
"submodule.mod.attach" to "true" or I run "git submodule update" with
the "--attach" switch. The expected behavior for submodule "mod" would
be (pseudocode):

git checkout <branch>
if "merge" and "head_detached" then
    git merge <orphaned-sha1>
case:
    "merge":
        git merge <origin-sha1>
    "rebase":
        git rebase <origin-sha1>
    "!<command>":
        <command> <origin-sha1>
if "rebase" and "head_detached" then
   git merge <orphaned-sha1>

So, in both "merge|rebase" cases we merge back orphaned commits with a
"git merge", but the effect will be a merge or a rebase depending of
the ordering of the main "update" operation. We can't assume a merge
or rebase operation in the case of !command so we let the
responsibility of merging back orphaned commits to the user.

Sounds good?

>
> > +
> > +--attach::
> > +       This option is only valid for the add and update commands. Cause the
>
> Grammar: 'Causes the result'
>

Ok.

>
> > +       result of an add or update operation to be an attached HEAD. In the
> > +       update command , if `submodule.<name>.branch` is not set, it will
>
> typo: space before comma.
>

Ok.

>
> Also, the pronoun "it" here is unclear to me.  Does this convey the
> correct meaning?
>
>    In the update operation, the branch named by 'submodule.<name>.branch' is
>    checked out as the new HEAD of the submodule repository. If
>    'submodule.<name>.branch' is not set, the 'master' branch is
> checked out as the
>    new HEAD of the submodule.
>

Sounds good to me.

>
> > +       default to `master`. Note: for the update command `--attach` also
> > +       implies `--remote`.
> > +
> > +--detach::
> > +       This option is only valid for the update command. Cause the result
>
>  Grammar: 'Causes the result'
>

Ok.

>
> > +       of the update operation to be forcedly a detached HEAD.
>
> "Forcedly" is a bit strong, maybe, slightly misplaced, and not a word,
> besides.   How's this, instead:
>
>    Forces the result of the update operation to be a detached HEAD in
> the submodule.


Sounds good to me.

>
> >  submodule.<name>.update::
> >         Defines what to do when the submodule is updated by the superproject.
> > -       If 'checkout' (the default), the new commit specified in the
> > -       superproject will be checked out in the submodule on a detached HEAD.
> > +       If 'checkout' (the default), the new commit (or the branch, when using
> > +       the '--attach' switch or the 'submodule.<name>.attach' property is set
> > +       to 'true' during an update operation) specified in the superproject will
> > +       be checked out in the submodule.
>
> IMHO, this wording is overcomplicated by this change.  How about:
>
>        If 'checkout' (the default), the new commit specified in the superproject
>        (or branch, with '--attach') will be checked out in the submodule.
>

Sounds good to me.

>
> >         If 'rebase', the current branch of the submodule will be rebased onto
> >         the commit specified in the superproject. If 'merge', the commit
> >         specified in the superproject will be merged into the current branch
>
> Does the 'merge', 'rebase' and '!command' description need to be
> updated, too?  Here and above it seems to still suggest the old
> behavior is kept when --attach is used.
>

You are right, I'll improve those. Also I think the documentation was
a bit innacurate because, with the current git features state, it's
possible merge changes keeping the HEAD detached, and that's what
happen.


>
> > @@ -54,6 +56,11 @@ submodule.<name>.branch::
> >         If the option is not specified, it defaults to 'master'.  See the
> >         `--remote` documentation in linkgit:git-submodule[1] for details.
> >
> > +submodule.<name>.attach::
> > +       Determine if the update operation will produce a detached HEAD or not.
> > +       Valid values are `true` or `false`. If the property is set to `true`
> > +       and `submodule.<name>.branch`, it will default to `master`
>
> I think you mean "...and 'submodule.<name>.branch' is not set, it
> will...", right?


Correct. I'll fix it.

>
> Some explanation of what happens when it _is_ set would be useful
> here, too, I think.  But maybe I do not understand the nuances yet.
>

I think you're right. I'll improve it.

>
> > @@ -475,8 +479,17 @@ Use -f if you really want to add it." >&2
> >                         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" ;;
> > +                       '')
> > +                               git checkout -f -q
> > +                               ;;
>
> Is this whitespace change intentional and necessary?
>

It's unnecessary but it was intentional. In the file there are mixed
indentation styles for cases but when there are multiple statements
clauses the more frequent style is to span single statement clauses to
multi-line too. I touched the clause below to become muti-statenent so
here we are. Please tell me if it's more correct to not touch that
line.


>
> >  }
> > @@ -622,7 +641,7 @@ cmd_init()
> >                    test -z "$(git config submodule."$name".update)"
> >                 then
> >                         case "$upd" in
> > -                       rebase | merge | none)
> > +                       checkout | rebase | merge | none)
>
> This belongs in a commit of its own.
>

Agreed. I'll do it.

>
> >                                 ;; # known modes of updating
> >                         *)
> >                                 echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
> > @@ -632,6 +651,23 @@ cmd_init()
> >                         git config submodule."$name".update "$upd" ||
> >                         die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
> >                 fi
> > +
> > +               # Copy "attach" setting when it is not set yet
> > +               if attached="$(git config -f .gitmodules submodule."$name".attach)" &&
> > +                  test -n "$attached" &&
> > +                  test -z "$(git config submodule."$name".attach)"
> > +               then
> > +                       case "$attached" in
> > +                       true | false)
> > +                               ;; # Valid attach flag values
> > +                       *)
> > +                               echo >&2 "warning: invalid attach flag value for submodule '$name'"
> > +                               upd=none
> > +                               ;;
> > +                       esac
> > +                       git config submodule."$name".attach "$attached" ||
> > +                       die "$(eval_gettext "Failed to register attached option for submodule path '\$displaypath'")"
> > +               fi
> >         done
> >  }
> >
> > @@ -750,6 +786,14 @@ cmd_update()
> >                 --reference=*)
> >                         reference="$1"
> >                         ;;
> > +               --attach)
> > +                       if test "$attach" = "false" ; then usage ; fi
> > +                       attach="true"
> > +                       ;;
> > +               --detach)
> > +                       if test "$attach" = "true" ; then usage ; fi
> > +                       attach="false"
> > +                       ;;
> >                 -m|--merge)
> >                         update="merge"
> >                         ;;
> > @@ -800,11 +844,44 @@ cmd_update()
> >                 name=$(module_name "$sm_path") || exit
> >                 url=$(git config submodule."$name".url)
> >                 branch=$(get_submodule_config "$name" branch master)
> > +               if test -n "$attach"
> > +               then
> > +                       attach_module=$attach
> > +               else
> > +                       attach_module=$(git config submodule."$name".attach)
> > +                       case "$attach_module" in
> > +                       '')
> > +                               ;; # Unset attach flag
> > +                       true|false)
> > +                               ;; # Valid attach flag values
> > +                       *)
> > +                               echo >&2 "warning: invalid attach flag value for submodule '$name'"
> > +                               attach_module=
> > +                               ;;
> > +                       esac
> > +               fi
> > +               if test "$attach_module" = "false"
> > +               then
> > +                       # Normalize attach 'false' flag value
> > +                       attach_module=
> > +               fi
> >                 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
> > +                       *)
> > +                               update_module=
> > +                               echo >&2 "warning: invalid update mode for submodule '$name'"
> > +                               ;;
> > +                       esac
>
> Probably belongs to the same "other" commit mentioned before.
>

Agreed. Please confirm that you meant only the
submodule."$module".update part here as you quoted also a lof of code
that does belongs to the main "--attach" functionality.

>
> I didn't have time to parse out all these conditional completion
> commands in this review, but the feature seems sane to me, as I
> understand it.
>

Good. After a response I should be able to produce an improved patch.

Thanks,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH/RFC] Introduce git submodule add|update --attach
  2013-12-30  1:49 [PATCH/RFC] Introduce git submodule add|update --attach Francesco Pretto
  2013-12-31 20:05 ` Phil Hord
@ 2014-01-02 20:07 ` Junio C Hamano
  2014-01-02 23:42   ` Francesco Pretto
  1 sibling, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-02 20:07 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: git, Jens Lehmann, Heiko Voigt

Francesco Pretto <ceztko@gmail.com> writes:

> by default "git submodule" performs its add or update operations on a detached
> HEAD. This works well when using an existing full-fledged/indipendent project as
> the submodule, as there's less frequent need to update it or commit back
> changes. When the submodule is actually a large portion of shareable code
> between  different projects, and the superproject needs to track very closely
> the evolution of the submodule (or the other way around), I feel more confortable
> to reattach the HEAD of the submodule with an existing branch.

I may be missing some fundamental assumption in your mind when you
did this change, but in a workflow where somebody wants submodule
checkout to be on branches (as opposed to detached), wouldn't it
make more sense not to detach in the first place, rather than
introducing yet another option to "re-attach"?  The documentation of
"submodule update" seems to say that its "merge" and "rebase" modes
do not detach in the first place (and it alludes to "--checkout" but
it is unclear what it does purely from the documentation, as "git
submodule --help" does not even list it as one of the options).

And if there is a good reason why detaching to update and then
(perhaps after verifying the result or cleaning it up?  I dunno what
the expected use case is, so I am purely guessing) attaching the
result to a specific branch in separate steps, does it make sense to
give "--attach" option to "update" in the first place?  That makes
the whole thing into a single step, not giving the user a chance to
do anything in between, which I am guessing is the whole point of
your not using the existing "do not detach, work on a branch" modes.

Puzzled...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH/RFC] Introduce git submodule add|update --attach
  2014-01-02 20:07 ` Junio C Hamano
@ 2014-01-02 23:42   ` Francesco Pretto
  2014-01-03  0:26     ` Francesco Pretto
  2014-01-03  8:49     ` Francesco Pretto
  0 siblings, 2 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-02 23:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens Lehmann, Heiko Voigt

2014/1/2 Junio C Hamano <gitster@pobox.com>:
> Francesco Pretto <ceztko@gmail.com> writes:
>
>> by default "git submodule" performs its add or update operations on a detached
>> HEAD. This works well when using an existing full-fledged/indipendent project as
>> the submodule, as there's less frequent need to update it or commit back
>> changes. When the submodule is actually a large portion of shareable code
>> between  different projects, and the superproject needs to track very closely
>> the evolution of the submodule (or the other way around), I feel more confortable
>> to reattach the HEAD of the submodule with an existing branch.
>
> I may be missing some fundamental assumption in your mind when you
> did this change, but in a workflow where somebody wants submodule
> checkout to be on branches (as opposed to detached), wouldn't it
> make more sense not to detach in the first place, rather than
> introducing yet another option to "re-attach"?  The documentation of
> "submodule update" seems to say that its "merge" and "rebase" modes
> do not detach in the first place (and it alludes to "--checkout" but
> it is unclear what it does purely from the documentation, as "git
> submodule --help" does not even list it as one of the options).
>

Thanks for commenting: because of more checking I just spotted some
unuseful code in my patch in cmd_add() function. In short: it seems to
me "git submodule update" doesn't allow to work with attached an HEAD
(unless it is *manually* attached, as I regularly do). My feeling is
the documentation of "merge", "rebase" update commands is inaccurate
and doesn't really reflect what happen when adding a submodule with
"add" or cloning it for the first time with "update". You can look at
the following conditionals in the current code in git-submodule.sh:

## cmd_add()
case "$branch" in
'') git checkout -f -q ;;
?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
esac

## cmd_update()
# Is this something we just cloned?
case ";$cloned_modules;" in
    *";$name;"*)
    # then there is no local change to integrate
    update_module= ;;
esac

This means that the "add" command will always checkout an *attached*
HEAD but at the first clone of a different user the checkout will
resolve in "git checkout <sha1>", always producing a *detached* HEAD
and resulting in inconsistent HEAD state between who added the
submodule with "add" and who cloned it with "update". Subsequent
"merge" or "rebase" operations won't change this fact, the HEAD will
remain detached. The following test case confirms this, unless I did
something wrong:

-----------------------------------------------------------------
parentdir=$(pwd -P)
submodurl1=$(pwd -P)/repo1
submodurl2=$(pwd -P)/repo2
repourl=$(pwd -P)/repo

# Create repo to be added with submodules
cd $parentdir
mkdir repo
cd repo
git init
git config receive.denyCurrentBranch ignore
echo a >a
git add a
git commit -m "repo commit 1"

# Create repo repo1 to be used as submodule
cd $parentdir
mkdir repo1
cd repo1
git init
git config receive.denyCurrentBranch ignore
echo a >a
git add a
git commit -m "repo1 commit 1"

# Create repo repo2 to be used as submodule
cd $parentdir
mkdir repo2
cd repo2
git init
git config receive.denyCurrentBranch ignore
echo a >a
git add a
git commit -m "repo2 commit 1"

# Clone repo to test "git submodule update"
cd $parentdir
git clone "$repourl" repoclone

#
## Adding submodule with update "rebase", not specifying a <branch>
#

cd $parentdir/repo
git submodule add "$submodurl1" submod1
git config -f .gitmodules submodule.submod1.ignore all
git config -f .gitmodules submodule.submod1.update rebase
git commit -m "Added submodule"
###### repo/submod1 has an attached HEAD ######

cd $parentdir/repoclone
git pull
git submodule init
git submodule update
###### repoclone/submod1 has a detached HEAD --> note the inconsistency ######

#
## Adding submodule with update "rebase", specifying a <branch>
#
cd $parentdir/repo
git submodule add --branch master "$submodurl2" submod2
git config -f .gitmodules submodule.submod2.ignore all
git config -f .gitmodules submodule.submod2.update rebase
git add .
git commit -m "Added submodule"
###### repo/submod2 has a attached HEAD ######

cd $parentdir/repoclone
git pull
git submodule init
git submodule update --remote
###### repoclone/submod2 has a detached HEAD --> note the inconsistency ######

#
## Adding something to submod2 and test update "rebase" on repoclone
#

cd $parentdir/repo1
echo b >b
git add b
git commit -m "repo1 commit 2"

cd $parentdir/repoclone
git submodule update --remote
###### repoclone/submod1 has still a detached HEAD ######
-----------------------------------------------------------------


> And if there is a good reason why detaching to update and then
> (perhaps after verifying the result or cleaning it up?  I dunno what
> the expected use case is, so I am purely guessing) attaching the
> result to a specific branch in separate steps, does it make sense to
> give "--attach" option to "update" in the first place?  That makes
> the whole thing into a single step, not giving the user a chance to
> do anything in between, which I am guessing is the whole point of
> your not using the existing "do not detach, work on a branch" modes.
>

1) The "--attach" option in the "add" git submodule command is my
contribution to have the "attached" behavior by default for cloning
users, because it's not possible to obtain it by just setting the
update command to "merge" or "rebase";
2) The "--attach" and "--detach" switches for the "update" command are
needed just to override in the command line the setting of
"submodule.<module>.attach" (or its absence of value). Of course not
many users will need to use these switche. The others will just use
the provided "submodule.<module>.attach" value and issue "git update"
(or "git init", when needed to update properties).

Concluding, my point is that at the current state submodules in git
seem to be flawed because of the inconsistent HEAD state between "add"
and "update" users. With my patch applied the attached HEAD behavior
would be fully supported. At some point "git submodule add" (without
the "--attached" switch) could be also modified to produce a detached
HEAD by default, removing any remaining inconsistency.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH/RFC] Introduce git submodule add|update --attach
  2014-01-02 23:42   ` Francesco Pretto
@ 2014-01-03  0:26     ` Francesco Pretto
  2014-01-03  8:49     ` Francesco Pretto
  1 sibling, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-03  0:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens Lehmann, Heiko Voigt

2014/1/3 Francesco Pretto <ceztko@gmail.com>:
> Concluding, my point is that at the current state submodules in git
> seem to be flawed because of the inconsistent HEAD state between "add"
> and "update" users. With my patch applied the attached HEAD behavior
> would be fully supported. At some point "git submodule add" (without
> the "--attached" switch) could be also modified to produce a detached
> HEAD by default, removing any remaining inconsistency.
>

Also consider that ultimately my desired behavior for submodules is
the following:
1) I'd like cloning users to have an attached HEAD by default when
doing "git submodule update";
2) when using an attached HEAD, I'd like "git submodule update" to
also imply "--remote".

An alternative approach would be, for example, make "git submodule
update" honor the current documentation about the behavior of "merge"
and "rebase" update operations, if confirmed to be wrong, really
keeping the HEAD attached. That would be a breaking change, but at
least it would reflect currently documented behavior. I prefer my
original approach, because it adds more feasibility and it's not
breaking in the short time, but I'm open to that and other solutions.

Please let me know, what do you think about it.

Thank you,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH/RFC] Introduce git submodule add|update --attach
  2014-01-02 23:42   ` Francesco Pretto
  2014-01-03  0:26     ` Francesco Pretto
@ 2014-01-03  8:49     ` Francesco Pretto
  2014-01-03 18:06       ` [PATCH] submodule: Respect reqested branch on all clones W. Trevor King
  2014-01-05  2:50       ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Francesco Pretto
  1 sibling, 2 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-03  8:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens Lehmann, Heiko Voigt

2014/1/3 Francesco Pretto <ceztko@gmail.com>:
> Concluding, my point is that at the current state submodules in git
> seem to be flawed because of the inconsistent HEAD state between "add"
> and "update" users. With my patch applied the attached HEAD behavior
> would be fully supported. At some point "git submodule add" (without
> the "--attached" switch) could be also modified to produce a detached
> HEAD by default, removing any remaining inconsistency.

Junio, please let me amend this affirmation as it's inaccurate.
According to the current *upstream* features this should the supported
use case for submodules:
- there's a maintainer "add" user that adds the submodule. He will
need to track the upstream submodule revision sha1, so he will clone
the repository with an *attached* HEAD;
- there's a developer "update" use that just clone the submodule
repository and track the sha1 decided by the maintainer "add" user. He
won't need to track upstream submodule revision sha1 so cloning the
repository with a *detached* HEAD. Subsequent "merge" or "rebase"
update operations will keep the HEAD detached.

We should *not* modify/break this default workflow in any way.

The current documentation seems to be misleading when saying that
"This [the update command] will make the submodules HEAD be detached
**unless** --rebase or --merge is specified", as it seems to imply
that the update operation will result in a repository with the HEAD
attached. The repository will be indeed updated merging changes, but
the HEAD will stay detached.

Now, the use case I would like git to support is this:
- there's a maintainer "add" user that adds the submodule. He won't
track the upstream submodule revision sha1, so
"submodule.<module>.ignore" will be set to "all". He will still clone
the repository with an *attached* HEAD;
- there's a developer "update" user. He will clone the submodule
repository with an *attached* HEAD. Subsequent "merge" or "rebase"
update operations will keep the HEAD attached.

To fully support this workflow in my patch I want to:
- introduce a "submodule.<module>.attach" property so "update" users
will clone the submodule repository with an attached HEAD;
- introduce "--attach|--dettach" switches to "update" commmant to
eventually override "submodule.<module>.attach" property value in the
command line;
- introduce "--attach" (but better rename it to "--keep-attached" or
something else) switch to the "add" operation. This "--keep-attached"
will:
    * set "submodule.<module>.attach" to true;
    * set "submodule.<module>.ignore" to all.

Being the workflow complementary, and the behavior fully optional, I
think the proposed feature should be solid. Give me some time to
produce an improved patch and let see if I can convince you.

Regards,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH] submodule: Respect reqested branch on all clones
  2014-01-03  8:49     ` Francesco Pretto
@ 2014-01-03 18:06       ` W. Trevor King
  2014-01-04 22:09         ` Heiko Voigt
  2014-01-05  3:53         ` Francesco Pretto
  2014-01-05  2:50       ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Francesco Pretto
  1 sibling, 2 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-03 18:06 UTC (permalink / raw)
  To: Git
  Cc: Francesco Pretto, Junio C Hamano, Jens Lehmann, Heiko Voigt,
	W. Trevor King

From: "W. Trevor King" <wking@tremily.us>

The previous code only checked out the requested branch in cmd_add.
This commit moves the branch-checkout logic into module_clone, where
it can be shared by cmd_add and cmd_update.  I also update the initial
checkout command to use 'rebase' to preserve branches setup during
module_clone.

Signed-off-by: W. Trevor King <wking@tremily.us>
---

On Fri, Jan 03, 2014 at 09:49:01AM +0100, Francesco Pretto wrote:
> - there's a developer "update" user. He will clone the submodule
> repository with an *attached* HEAD. Subsequent "merge" or "rebase"
> update operations will keep the HEAD attached.

'merge' and 'rebase' updates don't change the HEAD attachment.
Branches stay branches and detached HEADs stay detached.  If you've
moved away from the 'checkout' update mechanism, the only thing you
still need is a way to get an initial checkout on a branch.  This
should do it (I can add tests if folks like the general approach).

 git-submodule.sh | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 2979197..e2e5a6c 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -253,6 +253,7 @@ module_clone()
 	url=$3
 	reference="$4"
 	depth="$5"
+	branch="$6"
 	quiet=
 	if test -n "$GIT_QUIET"
 	then
@@ -306,7 +307,14 @@ 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" &&
+		if test -n "$branch"; then
+			git checkout -f -q -B "$branch" "origin/$branch" && echo "checked out $branch"
+		fi
+	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
 }
 
 isnumber()
@@ -469,16 +477,7 @@ 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'")"
+		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$branch" || exit
 	fi
 	git config submodule."$sm_name".url "$realrepo"
 
@@ -815,7 +814,7 @@ 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
+			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$branch" || exit
 			cloned_modules="$cloned_modules;$name"
 			subsha1=
 		else
@@ -861,7 +860,12 @@ Maybe you want to use 'update --init'?")"
 			case ";$cloned_modules;" in
 			*";$name;"*)
 				# then there is no local change to integrate
-				update_module= ;;
+				if test -n "$branch"; then
+					update_module="!git reset --hard -q"
+				else
+					update_module=
+				fi
+				;;
 			esac
 
 			must_die_on_failure=
-- 
1.8.5.2.gaa5d535.dirty

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [PATCH] submodule: Respect reqested branch on all clones
  2014-01-03 18:06       ` [PATCH] submodule: Respect reqested branch on all clones W. Trevor King
@ 2014-01-04 22:09         ` Heiko Voigt
  2014-01-04 22:54           ` W. Trevor King
  2014-01-05  3:53         ` Francesco Pretto
  1 sibling, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-04 22:09 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

Hi,

On Fri, Jan 03, 2014 at 10:06:11AM -0800, W. Trevor King wrote:
> From: "W. Trevor King" <wking@tremily.us>
> 
> The previous code only checked out the requested branch in cmd_add.
> This commit moves the branch-checkout logic into module_clone, where
> it can be shared by cmd_add and cmd_update.  I also update the initial
> checkout command to use 'rebase' to preserve branches setup during
> module_clone.
> 
> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---
> 
> On Fri, Jan 03, 2014 at 09:49:01AM +0100, Francesco Pretto wrote:
> > - there's a developer "update" user. He will clone the submodule
> > repository with an *attached* HEAD. Subsequent "merge" or "rebase"
> > update operations will keep the HEAD attached.
> 
> 'merge' and 'rebase' updates don't change the HEAD attachment.
> Branches stay branches and detached HEADs stay detached.  If you've
> moved away from the 'checkout' update mechanism, the only thing you
> still need is a way to get an initial checkout on a branch.  This
> should do it (I can add tests if folks like the general approach).
> 
>  git-submodule.sh | 30 +++++++++++++++++-------------
>  1 file changed, 17 insertions(+), 13 deletions(-)
> 
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 2979197..e2e5a6c 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -253,6 +253,7 @@ module_clone()
>  	url=$3
>  	reference="$4"
>  	depth="$5"
> +	branch="$6"
>  	quiet=
>  	if test -n "$GIT_QUIET"
>  	then
> @@ -306,7 +307,14 @@ 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")

Why should this line be removed? Is it not needed for correct
worktree <-> repo linking of submodules?

> +	(
> +		clear_local_git_env
> +		cd "$sm_path" &&
> +		GIT_WORK_TREE=. git config core.worktree "$rel/$b" &&
> +		if test -n "$branch"; then
> +			git checkout -f -q -B "$branch" "origin/$branch" && echo "checked out $branch"
> +		fi
> +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
>  }
>  
>  isnumber()
> @@ -469,16 +477,7 @@ 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'")"
> +		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$branch" || exit
>  	fi
>  	git config submodule."$sm_name".url "$realrepo"
>  
> @@ -815,7 +814,7 @@ 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
> +			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$branch" || exit
>  			cloned_modules="$cloned_modules;$name"
>  			subsha1=
>  		else
> @@ -861,7 +860,12 @@ Maybe you want to use 'update --init'?")"
>  			case ";$cloned_modules;" in
>  			*";$name;"*)
>  				# then there is no local change to integrate
> -				update_module= ;;
> +				if test -n "$branch"; then
> +					update_module="!git reset --hard -q"

Does that not put the user in danger of loosing changes?

I am wondering if we should maybe take a little different approach:

If submodule.<name>.branch is configured:

	git submodule update

will checkout the configured branch instead of the sha1? Maybe something like
this (untested):

diff --git a/git-submodule.sh b/git-submodule.sh
index 2677f2e..eca519a 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -903,7 +903,13 @@ Maybe you want to use 'update --init'?")"
                                ;;
                        esac
 
-                       if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
+                       revision="$sha1"
+                       if test -n "$branch"
+                       then
+                               revision="$branch"
+                       fi
+
+                       if (clear_local_git_env; cd "$sm_path" && $command "$revision")
                        then
                                say "$say_msg"
                        elif test -n "$must_die_on_failure"


Then we do not need to write a command configuration into the local repository
configuration. If I understand the OP intention correctly, that should solve the
use-case.

Cheers Heiko

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [PATCH] submodule: Respect reqested branch on all clones
  2014-01-04 22:09         ` Heiko Voigt
@ 2014-01-04 22:54           ` W. Trevor King
  2014-01-05  0:39             ` Heiko Voigt
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-04 22:54 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 2293 bytes --]

On Sat, Jan 04, 2014 at 11:09:15PM +0100, Heiko Voigt wrote:
> On Fri, Jan 03, 2014 at 10:06:11AM -0800, W. Trevor King wrote:
> > @@ -306,7 +307,14 @@ 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")
> 
> Why should this line be removed? Is it not needed for correct
> worktree <-> repo linking of submodules?
> 
> > +	(
> > +		clear_local_git_env
> > +		cd "$sm_path" &&
> > +		GIT_WORK_TREE=. git config core.worktree "$rel/$b" &&
> > +		if test -n "$branch"; then
> > +			git checkout -f -q -B "$branch" "origin/$branch" && echo "checked out $branch"
> > +		fi
> > +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
> >  }

It's not removed, just merged with the branch manipulation that also
happens in a clean local environment in $sm_path.  Spawning two
sequential subshells with the same setup seemed like overkill.

> > @@ -861,7 +860,12 @@ Maybe you want to use 'update --init'?")"
> >  			case ";$cloned_modules;" in
> >  			*";$name;"*)
> >  				# then there is no local change to integrate
> > -				update_module= ;;
> > +				if test -n "$branch"; then
> > +					update_module="!git reset --hard -q"
> 
> Does that not put the user in danger of loosing changes?

No, because this is only happens for just-cloned modules.  The user
hasn't had time to make local changes yet.

> If submodule.<name>.branch is configured:
> 
> 	git submodule update
> 
> will checkout the configured branch instead of the sha1?

The use case described by Francesco, a submodule maintainer Alice sets
up the submodule, which downstream developer Bob want to checkout to a
branch.  I think that matching the exact commit specified by Alice in
Bob's checkout is important, even if the upstream developer Charlie
has advanced the referenced branch in the meantime.  Shifting the
referenced submodule commit should be an explicit decision made by
Alice, not a clone-time accident for Bob.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [PATCH] submodule: Respect reqested branch on all clones
  2014-01-04 22:54           ` W. Trevor King
@ 2014-01-05  0:39             ` Heiko Voigt
  2014-01-05  1:08               ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-05  0:39 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

On Sat, Jan 04, 2014 at 02:54:01PM -0800, W. Trevor King wrote:
> On Sat, Jan 04, 2014 at 11:09:15PM +0100, Heiko Voigt wrote:
> > On Fri, Jan 03, 2014 at 10:06:11AM -0800, W. Trevor King wrote:
> > > @@ -306,7 +307,14 @@ 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")
> > 
> > Why should this line be removed? Is it not needed for correct
> > worktree <-> repo linking of submodules?
> > 
> > > +	(
> > > +		clear_local_git_env
> > > +		cd "$sm_path" &&
> > > +		GIT_WORK_TREE=. git config core.worktree "$rel/$b" &&
> > > +		if test -n "$branch"; then
> > > +			git checkout -f -q -B "$branch" "origin/$branch" && echo "checked out $branch"
> > > +		fi
> > > +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
> > >  }
> 
> It's not removed, just merged with the branch manipulation that also
> happens in a clean local environment in $sm_path.  Spawning two
> sequential subshells with the same setup seemed like overkill.

Ah ok, thanks. For some reason I overlooked that.

> > > @@ -861,7 +860,12 @@ Maybe you want to use 'update --init'?")"
> > >  			case ";$cloned_modules;" in
> > >  			*";$name;"*)
> > >  				# then there is no local change to integrate
> > > -				update_module= ;;
> > > +				if test -n "$branch"; then
> > > +					update_module="!git reset --hard -q"
> > 
> > Does that not put the user in danger of loosing changes?
> 
> No, because this is only happens for just-cloned modules.  The user
> hasn't had time to make local changes yet.

Ah ok I see. But why the reset then? Doesn't the earlier git checkout in your
patch take care of checking out the branch and thus update to the right
revision?

> > If submodule.<name>.branch is configured:
> > 
> > 	git submodule update
> > 
> > will checkout the configured branch instead of the sha1?
> 
> The use case described by Francesco, a submodule maintainer Alice sets
> up the submodule, which downstream developer Bob want to checkout to a
> branch.  I think that matching the exact commit specified by Alice in
> Bob's checkout is important, even if the upstream developer Charlie
> has advanced the referenced branch in the meantime.  Shifting the
> referenced submodule commit should be an explicit decision made by
> Alice, not a clone-time accident for Bob.

But from what I understand of this part of Francesco's use-case description:

> # Developer
> $ git pull
> $ git submodule init
> $ git submodule update --remote
> $ cd <path>
> $ branch="$(git config -f ..\.gitmodules submodule.common.branch)"; git checkout $branch

Is that he wants to allow the developer to switch to following a branch instead
of an exact sha1 while some extension in the common module is still under
development. That makes it easier to develop in parallel in the submodule and
the superproject because you do not need to update the sha1 all the time.

E.g. its likely that changes have to be reviewed and cleaned up in the
submodule first until they can be merged to the master branch there. During
this time the developer follows the branch.
Once the submodule review is finished the superproject branch can switch back
to the exact model again (because the submodule will not change anymore) and
finish its implementation there.

Matching the exact commit and checking out the branch only if it points to that
exact commit does not really help the developer in this use-case. But I am only
guessing from my experience with development of features in submodule.

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH] submodule: Respect reqested branch on all clones
  2014-01-05  0:39             ` Heiko Voigt
@ 2014-01-05  1:08               ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-05  1:08 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 4045 bytes --]

On Sun, Jan 05, 2014 at 01:39:22AM +0100, Heiko Voigt wrote:
> On Sat, Jan 04, 2014 at 02:54:01PM -0800, W. Trevor King wrote:
> > On Sat, Jan 04, 2014 at 11:09:15PM +0100, Heiko Voigt wrote:
> > > On Fri, Jan 03, 2014 at 10:06:11AM -0800, W. Trevor King wrote:
> > > > @@ -861,7 +860,12 @@ Maybe you want to use 'update --init'?")"
> > > >  			case ";$cloned_modules;" in
> > > >  			*";$name;"*)
> > > >  				# then there is no local change to integrate
> > > > -				update_module= ;;
> > > > +				if test -n "$branch"; then
> > > > +					update_module="!git reset --hard -q"
> > > 
> > > Does that not put the user in danger of loosing changes?
> > 
> > No, because this is only happens for just-cloned modules.  The user
> > hasn't had time to make local changes yet.
> 
> Ah ok I see. But why the reset then? Doesn't the earlier git
> checkout in your patch take care of checking out the branch and thus
> update to the right revision?

The reset avoids a detached HEAD.  With an empty $update_module, the
following case block will setup:

  command="git checkout $subforce -q"

which is later called with:

  $command "$sha1"

That's going to give you a detached HEAD.  The new code sets up:

  command="git reset --hard -q"

which will keep you on the branch checked out in module_clone().

> > > If submodule.<name>.branch is configured:
> > > 
> > > 	git submodule update
> > > 
> > > will checkout the configured branch instead of the sha1?
> > 
> > The use case described by Francesco, a submodule maintainer Alice
> > sets up the submodule, which downstream developer Bob want to
> > checkout to a branch.  I think that matching the exact commit
> > specified by Alice in Bob's checkout is important, even if the
> > upstream developer Charlie has advanced the referenced branch in
> > the meantime.  Shifting the referenced submodule commit should be
> > an explicit decision made by Alice, not a clone-time accident for
> > Bob.
> 
> But from what I understand of this part of Francesco's use-case
> description:
> 
> > # Developer
> > $ git pull
> > $ git submodule init
> > $ git submodule update --remote
> > $ cd <path>
> > $ branch="$(git config -f ..\.gitmodules submodule.common.branch)"; git checkout $branch
> 
> Is that he wants to allow the developer to switch to following a
> branch instead of an exact sha1 while some extension in the common
> module is still under development. That makes it easier to develop
> in parallel in the submodule and the superproject because you do not
> need to update the sha1 all the time.

I'll wait for Francesco to clarify his use case.  All my patch does is
replace the manual:

  $ cd <path>
  $ branch="$(git config -f ..\.gitmodules submodule.common.branch)"; git checkout $branch

with an automatic (on update):

  $ branch="$(git config -f .gitmodules submodule.${name}.branch)";
  $ cd "$path"
  $ git checkout -f -q -B "$branch" "origin/$branch"
  $ git reset --hard -q "$sha"

when submodule.<name>.branch is configured.  Whether that last bit is
desirable or not is debatable.  If you *do* want to float the
submodule past the commit blessed by Alice, it's easy to add a manual:

  $ git submodule update --remote --rebase "$path"

If we drop the trailing reset (to float the checkout), it's harder to
rewind to the commit blessed by Alice, because distinguising between:

a) locally added stuff that we want to merge/rebase onto Alice's $sha,
   and
b) advancements from the automatic float that we *don't* want to
   merge/rebase onto Alice's $sha.

is difficult/impossible.  If you use the --checkout strategy (there
are no local commits), you can use:

  $ git submodule update --checkout "$path"

but you'd still need to update the branch references to point to the
that particular commit.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command
@ 2014-01-05  2:50       ` Francesco Pretto
  2014-01-05  2:50         ` [PATCH 2/2] Introduce git submodule attached update Francesco Pretto
                           ` (2 more replies)
  0 siblings, 3 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-05  2:50 UTC (permalink / raw)
  To: git; +Cc: Francesco Pretto

According to "Documentation/gitmodules.txt", 'checkout' is a valid
'submodule.<name>.update' command. Also "git-submodule.sh" refers to
it and processes it correctly. Reflect commit 'ac1fbb' to support this
syntax and also validates property values during 'update' command,
issuing a warning if the value found is unknwon.
---
 git-submodule.sh | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 2677f2e..1d041a7 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -622,7 +622,7 @@ cmd_init()
 		   test -z "$(git config submodule."$name".update)"
 		then
 			case "$upd" in
-			rebase | merge | none)
+			checkout | rebase | merge | none)
 				;; # known modes of updating
 			*)
 				echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
@@ -805,6 +805,18 @@ cmd_update()
 			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
+			*)
+				update_module=
+				echo >&2 "warning: invalid update mode for submodule '$name'"
+				;;
+			esac
 		fi
 
 		displaypath=$(relative_path "$prefix$sm_path")
-- 
1.8.5.2.230.g032cd47.dirty

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH 2/2] Introduce git submodule attached update
  2014-01-05  2:50       ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Francesco Pretto
@ 2014-01-05  2:50         ` Francesco Pretto
  2014-01-05 19:55           ` Francesco Pretto
  2014-01-05 20:33           ` Heiko Voigt
  2014-01-05 20:20         ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Heiko Voigt
  2014-01-05 20:44         ` W. Trevor King
  2 siblings, 2 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-05  2:50 UTC (permalink / raw)
  To: git; +Cc: Francesco Pretto

At the current state, the following use-case is not supported very
well in git:
- a maintainer adds a submodule, checking out a specific branch of
the repository. He doesn't track the upstream submodule revision sha1;
- a developer checkout the repository branch decided by the maintainer.
Subsequent "merge" or "rebase" update operations don't detach the HEAD.

To ease the above use-case this patch:
- introduces a "submodule.<module>.attached" property that, when set
  to "true", ensures that the "update" operation will result in
  the HEAD attached to a branch;
- introduces "--attach|--dettach" switches to the submodule "update"
  command: they attach/detach the HEAD, overriding
  "submodule.<module>.attached" property value;
- introduces "--attached-update" switch to the "add" operation. It:
    * sets "submodule.<module>.attached" to true;
    * sets "submodule.<module>.ignore" to all.

Using the '--attach' switch or operating in a repository with
'submodule.<name>.attached' set to 'true' during "update" will:
- checkout a branch with an attached HEAD if the repository was just
cloned;
- perform a fast-forward only merge of changes if it's a 'checkout'
update operation;
- reattach the HEAD prior performing a 'merge', 'rebase' or '!command'
update operation if the HEAD was found detached. Orphaned commits
will also be merged back in the branch.

'--attach' or 'submodule.<name>.attached' set to true also implies '--remote'.

Using  the '--detach' switch or operating in a repository with
'submodule.<name>.attached' set to 'false' during "update" will:
- checkout a detached HEAD if the repository was just cloned;
- detach the HEAD prior performing a 'merge', 'rebase' or '!command'
update operation if the HEAD was found attached.

'submodule.<name>.attached' works similarly to 'submodule.<name>.update'
property: git copies the values found in ".gitmodules" in ".git/config" when
performing an "init" command. "update" looks for values in ".git/config"
only.

'--attach' and '--detach' switches override an opposite behaviour
of 'submodule.<name>.attached' properties.

The patch is strongly additive and doesn't break any submodule specific
test. It also adds some tests specific to the added feature.
---
 Documentation/git-submodule.txt    |  48 +++++--
 Documentation/gitmodules.txt       |  10 +-
 git-submodule.sh                   | 154 +++++++++++++++++++--
 t/t7410-submodule-attached-head.sh | 268 +++++++++++++++++++++++++++++++++++++
 4 files changed, 457 insertions(+), 23 deletions(-)
 create mode 100755 t/t7410-submodule-attached-head.sh

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index bfef8a0..b97eefb 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -10,13 +10,14 @@ SYNOPSIS
 --------
 [verse]
 'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
-	      [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
+	      [--reference <repository>] [--attached-update] [--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>] [--depth <depth>]
-	      [--merge] [--recursive] [--] [<path>...]
+	      [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach]
+	      [--depth <depth>] [--merge] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
 	      [commit] [--] [<path>...]
 'git submodule' [--quiet] foreach [--recursive] <command>
@@ -107,6 +108,9 @@ is the superproject and submodule repositories will be kept
 together in the same relative location, and only the
 superproject's URL needs to be provided: git-submodule will correctly
 locate the submodule using the relative URL in .gitmodules.
++
+If `--attached-update` is specified, the property `submodule.<name>.attached`
+will be set to `true` and `submodule.<name>.ignore` will be set to `all`.
 
 status::
 	Show the status of the submodules. This will print the SHA-1 of the
@@ -156,12 +160,15 @@ 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.
+	This will make the submodules HEAD be detached unless `--attach` is
+	specified or `submodule.$name.attached` is set to `true`. The last setting
+	can always be overridden specifying `--detach`. Update mode can be
+	selected specifying `--checkout`, `--rebase` or `--merge` switches
+	or setting the key `submodule.$name.update` to `checkout`, `rebase`,
+	`merge` or `none`. `none` will cause the submodule to be skipped during
+	the update. 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
@@ -270,6 +277,23 @@ OPTIONS
 	be overridden by setting the `submodule.<name>.branch` option in
 	either `.gitmodules` or `.git/config` (with `.git/config` taking
 	precedence).
+
+--attached-update::
+	This option is only valid for the add command. Causes the add command
+	also to set the property `submodule.<name>.attached` to `true` and
+	the property `submodule.<name>.ignore` to `all`.
+
+--attach::
+	This option is only valid for the update commands. Causes the result
+	of an update operation to be an attached HEAD. In the update operation,
+	the branch named by 'submodule.<name>.branch' is checked out as the new
+	HEAD of the submodule repository. If 'submodule.<name>.branch' is not
+	set, the 'master' branch is checked out as the new HEAD of the
+	submodule. Note: `--attach` also implies `--remote`.
+
+--detach::
+	This option is only valid for the update command. Forces the result
+	of the update operation to be a detached HEAD in the submodule.
 +
 This works for any of the supported update procedures (`--checkout`,
 `--rebase`, etc.).  The only change is the source of the target SHA-1.
@@ -290,8 +314,7 @@ SHA-1.  If you don't want to fetch, you should use `submodule update
 --merge::
 	This option is only valid for the update command.
 	Merge the commit recorded in the superproject into the current branch
-	of the submodule. If this option is given, the submodule's HEAD will
-	not be detached. If a merge failure prevents this process, you will
+	of the submodule. If a merge failure prevents this process, you will
 	have to resolve the resulting conflicts within the submodule with the
 	usual conflict resolution tools.
 	If the key `submodule.$name.update` is set to `merge`, this option is
@@ -300,8 +323,7 @@ SHA-1.  If you don't want to fetch, you should use `submodule update
 --rebase::
 	This option is only valid for the update command.
 	Rebase the current branch onto the commit recorded in the
-	superproject. If this option is given, the submodule's HEAD will not
-	be detached. If a merge failure prevents this process, you will have
+	superproject. If a merge failure prevents this process, you will have
 	to resolve these failures with linkgit:git-rebase[1].
 	If the key `submodule.$name.update` is set to `rebase`, this option is
 	implicit.
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index f7be93f..9c436db 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -38,7 +38,8 @@ submodule.<name>.url::
 submodule.<name>.update::
 	Defines what to do when the submodule is updated by the superproject.
 	If 'checkout' (the default), the new commit specified in the
-	superproject will be checked out in the submodule on a detached HEAD.
+	superproject (or branch, with '--attach') will be checked out in
+	the submodule.
 	If 'rebase', the current branch of the submodule will be rebased onto
 	the commit specified in the superproject. If 'merge', the commit
 	specified in the superproject will be merged into the current branch
@@ -54,6 +55,13 @@ submodule.<name>.branch::
 	If the option is not specified, it defaults to 'master'.  See the
 	`--remote` documentation in linkgit:git-submodule[1] for details.
 
+submodule.<name>.attached::
+	Determine if the update operation will produce a detached HEAD or not.
+	Valid values are `true` or `false`. If the property is set to `true`
+	and `submodule.<name>.branch` is not set, the branch `master` will
+	be checked out. If `submodule.<name>.branch` is set the branch
+	specified will be checked out instead.
+
 submodule.<name>.fetchRecurseSubmodules::
 	This option can be used to control recursive fetching of this
 	submodule. If this option is also present in the submodules entry in
diff --git a/git-submodule.sh b/git-submodule.sh
index 1d041a7..bc6df2b 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -5,11 +5,11 @@
 # Copyright (c) 2007 Lars Hjemli
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
+USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--attached-update] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
-   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach] [--merge] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
@@ -36,6 +36,9 @@ update=
 prefix=
 custom_name=
 depth=
+attach=
+detach=
+attached_update=
 
 # The function takes at most 2 arguments. The first argument is the
 # URL that navigates to the submodule origin repo. When relative, this URL
@@ -352,6 +355,9 @@ cmd_add()
 			custom_name=$2
 			shift
 			;;
+		--attached-update)
+			attached_update=yes
+			;;
 		--depth)
 			case "$2" in '') usage ;; esac
 			depth="--depth=$2"
@@ -491,6 +497,12 @@ Use -f if you really want to add it." >&2
 	then
 		git config -f .gitmodules submodule."$sm_name".branch "$branch"
 	fi &&
+	if test -n "$attached_update"
+	then
+		# We'll stay stick to the HEAD, no need to track revision sha1
+		git config -f .gitmodules submodule."$sm_name".attached "true"
+		git config -f .gitmodules submodule."$sm_name".ignore "all"
+	fi &&
 	git add --force .gitmodules ||
 	die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
 }
@@ -632,6 +644,22 @@ cmd_init()
 			git config submodule."$name".update "$upd" ||
 			die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
 		fi
+
+		# Copy "attached" setting when it is not set yet
+		if attached="$(git config -f .gitmodules submodule."$name".attached)" &&
+		   test -n "$attached" &&
+		   test -z "$(git config submodule."$name".attached)"
+		then
+			case "$attached" in
+			true | false)
+				;; # Valid attach flag values
+			*)
+				echo >&2 "warning: invalid attach flag value for submodule '$name'"
+				;;
+			esac
+			git config submodule."$name".attached "$attached" ||
+			die "$(eval_gettext "Failed to register attach option for submodule path '\$displaypath'")"
+		fi
 	done
 }
 
@@ -750,6 +778,14 @@ cmd_update()
 		--reference=*)
 			reference="$1"
 			;;
+		--attach)
+			if test -n "$detach" ; then usage ; fi
+			attach=1
+			;;
+		--detach)
+			if test -n "$attach" ; then usage ; fi
+			detach=1
+			;;
 		-m|--merge)
 			update="merge"
 			;;
@@ -800,6 +836,28 @@ cmd_update()
 		name=$(module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		branch=$(get_submodule_config "$name" branch master)
+		attach_module=
+		detach_module=
+		if test -n "$attach" -o -n "$detach"
+		then
+			attach_module=$attach
+			detach_module=$detach
+		else
+			attached=$(git config submodule."$name".attached)
+			case "$attached" in
+			'')
+				;; # Unset attach flag
+			true)
+				attach_module=1
+				;;
+			false)
+				detach_module=1
+				;;
+			*)
+				echo >&2 "warning: invalid attach flag value for submodule '$name'"
+				;;
+			esac
+		fi
 		if ! test -z "$update"
 		then
 			update_module=$update
@@ -848,7 +906,16 @@ Maybe you want to use 'update --init'?")"
 			die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
 		fi
 
-		if test -n "$remote"
+		head_rev_ref=$(clear_local_git_env; cd "$sm_path" && git rev-parse --abbrev-ref HEAD) ||
+		die "$(eval_gettext "Unable to determine revision ref in submodule path '\$sm_path'")"
+		head_detached=
+		if test "$head_rev_ref" = "HEAD"
+		then
+			# Determine if the HEAD is detached
+			head_detached="true"
+		fi
+
+		if test -n "$remote" -o -n "$attach_module"
 		then
 			if test -z "$nofetch"
 			then
@@ -862,7 +929,8 @@ Maybe you want to use 'update --init'?")"
 			die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
 		fi
 
-		if test "$subsha1" != "$sha1" -o -n "$force"
+		if test "$subsha1" != "$sha1" || test -n "$attach_module" -a -n "$head_detached" ||
+			test -n "$detach_module" -a -z "$head_detached" || test -n "$force"
 		then
 			subforce=$force
 			# If we don't already have a -f flag and the submodule has never been checked out
@@ -882,40 +950,108 @@ Maybe you want to use 'update --init'?")"
 			fi
 
 			# Is this something we just cloned?
+			just_cloned=
 			case ";$cloned_modules;" in
 			*";$name;"*)
 				# then there is no local change to integrate
-				update_module= ;;
+				update_module="checkout"
+				just_cloned=yes
+				;;
 			esac
 
+			if test -z "$update_module"
+			then
+				# Fallback to checkout
+				update_module="checkout"
+			fi
+
+			command_attach=:
+			suffix_attach=
+			if test "$update_module" != "checkout"
+			then
+				if test -n "$attach_module" -a -n "$head_detached"
+				then
+					# We need to reattach to the branch
+					command_attach="git checkout $subforce -q"
+					suffix_attach=$branch
+				elif test -n "$detach_module" -a -z "$head_detached"
+				then
+					# We need to detach from the branch
+					command_attach="git checkout $subforce -q"
+					suffix_attach=$sha1
+				fi
+			fi
+
+			command_pre=:
+			suffix_pre=
+			command_post=:
+			suffix_pre=
+			suffix=
 			must_die_on_failure=
+			custom_update=
 			case "$update_module" in
 			rebase)
 				command="git rebase"
+				suffix=$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
+				if test -n "$attach_module" -a -n "$head_detached" && test "$subsha1" != "$sha1"
+				then
+					# After the rebase, we merge orphaned commits in the branch
+					command_post="git merge"
+					suffix_post=$subsha1
+				fi
 				;;
 			merge)
+				if test -n "$attach_module" -a -n "$head_detached" && test "$subsha1" != "$sha1"
+				then
+					# Prior the rebase, we merge orphaned commits in in the branch
+					command_pre="git merge"
+					suffix_pre=$subsha1
+				fi
 				command="git merge"
+				suffix=$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
 				;;
+			checkout)
+				if test -n "$attach_module"
+				then
+					command="git checkout $subforce -q"
+					suffix=$branch
+					die_msg="$(eval_gettext "Unable to checkout banch '\$branch' in submodule path '\$displaypath'")"
+					say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out branch '\$branch'")"
+					if test -z "$just_cloned" -a && test "$subsha1" != "$sha1"
+					then
+						# Perform a fast-forward only merge of the origin
+						command_post="git merge $subforce --ff-only"
+						suffix_post="origin/$branch"
+					fi
+				else
+					command="git checkout $subforce -q"
+					suffix=$sha1
+					die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
+					say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
+				fi
+				;;
 			!*)
 				command="${update_module#!}"
+				suffix=$sha1
 				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
+				custom_update=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'")"
+				# Valid user configurable update modes are already filtered above
+				die "$(eval_gettext "Unexpected update mode in the current flow")"
 				;;
 			esac
 
-			if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
+			if (clear_local_git_env; cd "$sm_path" && $command_attach "$suffix_attach" &&
+				$command_pre "$suffix_pre" && $command "$suffix" && $command_post "$suffix_pro")
 			then
 				say "$say_msg"
 			elif test -n "$must_die_on_failure"
diff --git a/t/t7410-submodule-attached-head.sh b/t/t7410-submodule-attached-head.sh
new file mode 100755
index 0000000..04b3018
--- /dev/null
+++ b/t/t7410-submodule-attached-head.sh
@@ -0,0 +1,268 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Francesco Pretto
+#
+
+test_description='Support for submodules with attached head
+
+This test verifies the sanity of the add and update git submodule commands with
+or without the --attached-update, --attach, --detach switches or the
+submoudule.<module>.attach property set
+'
+
+TEST_NO_CREATE_REPO=true
+. ./test-lib.sh
+
+submodurl1=$(pwd -P)/repo1
+submodurl2=$(pwd -P)/repo2
+repourl=$(pwd -P)/repo
+
+test_expect_success 'setup - create repository "repo1" to be used as submodule' '
+	mkdir repo1 &&
+	(
+		cd repo1 &&
+		git init &&
+		git config receive.denyCurrentBranch ignore &&
+		echo a >a &&
+		git add a &&
+		git commit -m "repo1 commit 1"
+	)
+'
+
+test_expect_success 'setup - reate repository "repo2" to be used as submodule' '
+	mkdir repo2 &&
+	(
+		cd repo2 &&
+		git init &&
+		git config receive.denyCurrentBranch ignore &&
+		echo a >a &&
+		git add a &&
+		git commit -m "repo2 commit 1"
+	)
+'
+
+test_expect_success 'setup - create repository "repo" to be added with sumodules' '
+	mkdir repo &&
+	(
+		cd repo &&
+		git init &&
+		git config receive.denyCurrentBranch ignore &&
+		echo a >a &&
+		git add a &&
+		git commit -m "repo commit 1"
+	)
+'
+
+test_expect_success 'setup - clone repository "repo" in "repoclone"' '
+	git clone "$repourl" repoclone
+'
+
+test_expect_success 'setup - add "mod1" as regular submodule of "repo"' '
+	(
+		cd repo &&
+		git submodule add "$submodurl1" submod1
+	)
+'
+
+test_expect_success 'setup - add "mod2" as update attached HEAD submodule of "repo"' '
+	(
+		cd repo &&
+		git submodule add --attached-update "$submodurl2" submod2
+	)
+'
+
+test_expect_success 'setup - commit submodules in repo' '
+	(
+		cd repo &&
+		git add . &&
+		git commit -m "Added submodules"
+	)
+'
+
+test_expect_success 'init submodules in cloned repo' '
+	(
+		cd repoclone &&
+		git pull &&
+		git submodule init
+	)
+'
+
+test_expect_success 'update submodules in cloned repo' '
+	(
+		cd repoclone &&
+		git submodule update
+	)
+'
+
+test_expect_success 'assert submod1 HEAD is detached in cloned repo' '
+	(
+		cd repoclone/submod1 &&
+		test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
+	)
+'
+
+test_expect_success 'assert submod2 HEAD is attached in cloned repo' '
+	(
+		cd repoclone/submod2 &&
+		test "$(git rev-parse --abbrev-ref HEAD)" != "HEAD"
+	)
+'
+
+test_expect_success 'update submodules with --attach in cloned repo' '
+	(
+		cd repoclone &&
+		git submodule update --attach
+	)
+'
+
+test_expect_success 'assert submod1 HEAD is attached in cloned repo' '
+	(
+		cd repoclone/submod1 &&
+		test "$(git rev-parse --abbrev-ref HEAD)" != "HEAD"
+	)
+'
+
+test_expect_success 'update submodules with --detach in cloned repo' '
+	(
+		cd repoclone &&
+		git submodule update --detach
+	)
+'
+
+test_expect_success 'assert submod1 HEAD is detached in cloned repo' '
+	(
+		cd repoclone/submod1 &&
+		test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
+	)
+'
+
+test_expect_success 'assert submod2 HEAD is detached in cloned repo' '
+	(
+		cd repoclone/submod2 &&
+		test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
+	)
+'
+
+test_expect_success 'update submodules in cloned repo (will restore HEAD states)' '
+	(
+		cd repoclone &&
+		git submodule update
+	)
+'
+
+test_expect_success 'assert submod1 HEAD is detached in cloned repo' '
+	(
+		cd repoclone/submod1 &&
+		test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
+	)
+'
+
+test_expect_success 'assert submod2 HEAD is attached in cloned repo' '
+	(
+		cd repoclone/submod2 &&
+		test "$(git rev-parse --abbrev-ref HEAD)" != "HEAD"
+	)
+'
+
+test_expect_success 'setup - add update operation to submodules' '
+	(
+		cd repo &&
+		git config  -f .gitmodules submodule.submod1.update merge &&
+		git config  -f .gitmodules submodule.submod2.update rebase &&
+		git add . &&
+		git commit -m "updated submodules"
+	)
+'
+
+test_expect_success 'setup - update cloned repo and reinitialize submodules' '
+	(
+		cd repoclone &&
+		git pull &&
+		git submodule init
+	)
+'
+
+test_expect_success 'add some content to repo2' '
+	(
+		cd repo2 &&
+		echo b >b &&
+		git add b &&
+		git commit -m "repo2 commit 2"
+	)
+'
+
+test_expect_success 'update sumodules in cloned repo and verify that submod2 matches repo2' '
+	(
+		cd repoclone &&
+		git submodule update &&
+		test -e submod2/b
+	)
+'
+
+test_expect_success 'prepend some content to repo1/a' '
+	(
+		cd repo1 &&
+		echo -e "b\na" >a &&
+		git add a &&
+		git commit -m "repo1 commit 2"
+	)
+'
+
+test_expect_success 'append some content in repoclone/submod1 and commit' '
+	(
+		cd repoclone/submod1 &&
+		echo c >>a &&
+		git add a &&
+		git commit -m "submod1 commit 1"
+	)
+'
+
+test_expect_success 'update repoclone submodules with --attach' '
+	(
+		cd repoclone &&
+		git submodule update --attach
+	)
+'
+
+test_expect_success 'verify repoclone submod1 merge with reattached orphaned commits was correct' '
+	(
+		cd repoclone/submod1 &&
+		test "$(<a)" = "$'b\na\nc'"
+	)
+'
+
+test_expect_success 'setup - set operation checkout to submodule sumod1 in repo' '
+	(
+		cd repo &&
+		git config  -f .gitmodules submodule.submod1.update checkout &&
+		git add . &&
+		git commit -m "updated submodules"
+	)
+'
+
+test_expect_success 'setup - update cloned repo and reinitialize submodules' '
+	(
+		cd repoclone &&
+		git pull &&
+		git submodule init
+	)
+'
+
+test_expect_success 'add some content to repo1' '
+	(
+		cd repo1 &&
+		echo b >b &&
+		git add b &&
+		git commit -m "repo1 commit 3"
+	)
+'
+
+test_expect_success 'update submodule submod2 (merge ff-only) and verify it matches repo2' '
+	(
+		cd repoclone &&
+		git submodule update &&
+		test -e submod2/b
+	)
+'
+
+test_done
-- 
1.8.5.2.230.g032cd47.dirty

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [PATCH] submodule: Respect reqested branch on all clones
  2014-01-03 18:06       ` [PATCH] submodule: Respect reqested branch on all clones W. Trevor King
  2014-01-04 22:09         ` Heiko Voigt
@ 2014-01-05  3:53         ` Francesco Pretto
  2014-01-05 16:17           ` [RFC v2] submodule: Respect requested " W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-05  3:53 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Junio C Hamano, Jens Lehmann, Heiko Voigt

Thanks for adding your contribute. My comments below:

2014/1/3 W. Trevor King <wking@tremily.us>:
>
> The previous code only checked out the requested branch in cmd_add.
> This commit moves the branch-checkout logic into module_clone, where
> it can be shared by cmd_add and cmd_update.  I also update the initial
> checkout command to use 'rebase' to preserve branches setup during
> module_clone.
> [...]
> @@ -306,7 +307,14 @@ 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" &&
> +               if test -n "$branch"; then
> +                       git checkout -f -q -B "$branch" "origin/$branch" && echo "checked out $branch"
> +               fi
> +       ) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
>  }

If I understand it correctly, looking at your intervention in
module_clone and cmd_update, when "submodule.<module>.branch" is set
during "update" the resulting first clone will always be a branch
checkout (cause $branch is filled with "branch" property). I believe
this will break a lot of tests, as the the documentation says that in
this configuration the HEAD should be detached. Also it could break
some users that rely on the current behavior.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05  3:53         ` Francesco Pretto
@ 2014-01-05 16:17           ` W. Trevor King
  2014-01-05 19:48             ` Heiko Voigt
                               ` (2 more replies)
  0 siblings, 3 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-05 16:17 UTC (permalink / raw)
  To: Git
  Cc: Francesco Pretto, Junio C Hamano, Jens Lehmann, Heiko Voigt,
	W. Trevor King

From: "W. Trevor King" <wking@tremily.us>

The previous code only checked out the requested branch in cmd_add.
This commit moves the branch-checkout logic into module_clone, where
it can be shared by cmd_add and cmd_update.  I also update the initial
checkout command to use 'rebase' to preserve branches setup during
module_clone.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
Changes since v1:
* Fix a 'reqested' -> 'requested' typo in the subject/summary.
* Restore a post-clone 'git checkout -f -q' for the empty-branch case
  in module_clone().
* Distinguish between $branch (which defaults to 'master') and a new
  $config_branch (which defaults to empty) in cmd_update

After these fixes, all the existing submodule tests pass.  If we want
to merge this, we'd still want new tests that demonstrate the new
functionality.

On Sun, Jan 05, 2014 at 04:53:12AM +0100, Francesco Pretto wrote:
> If I understand it correctly, looking at your intervention in
> module_clone and cmd_update, when "submodule.<module>.branch" is set
> during "update" the resulting first clone will always be a branch
> checkout (cause $branch is filled with "branch" property).

That's correct.

> I believe this will break a lot of tests,

Thanks for prompting me to run the tests.  This v2 now passes all of
the current submodule tests, and the functionality actually matches my
earlier descriptions of it ;).

> as the the documentation says that in this configuration the HEAD
> should be detached.

The current Documentation/git-submodule.txt has:

  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`.

It's not clear if this refers to the initial-clone update, future
post-clone updates, or both.  Ideally, the behavior should be the
same, but in the initial-clone case we don't have an existing
checked-out branch to work with.

> Also it could break some users that rely on the current behavior.

The current code always has a detached HEAD after an initial-clone
update, regardless of submodule.<name>.update, which doesn't match
those docs either.  Adding a check to only checkout
submodule.<name>.branch if submodule.<name>.update was 'rebase',
'merge', or 'none' would be easy, but I don't think that makes much
sense.  I can't see any reason for folks who specify
submodule.<name>.branch to prefer a detached HEAD over a local branch
matching the remote branch's name.  If they prefer checkout updates,
the first such update will return them to a detached HEAD.  If they
prefer merge/rebase updates, future updates will keep them on the same
branch.  All my commit does is setup that initial branch for folks who
get the submodule via 'update', in the same way it's currently setup
for folks who get the submodule via 'add'.

Cheers,
Trevor

 git-submodule.sh | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 2979197..167d4fa 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -253,6 +253,7 @@ module_clone()
 	url=$3
 	reference="$4"
 	depth="$5"
+	branch="$6"
 	quiet=
 	if test -n "$GIT_QUIET"
 	then
@@ -306,7 +307,15 @@ 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" &&
+		case "$branch" in
+		'') git checkout -f -q ;;
+		?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
+		esac
+	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
 }
 
 isnumber()
@@ -469,16 +478,7 @@ 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'")"
+		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$branch" || exit
 	fi
 	git config submodule."$sm_name".url "$realrepo"
 
@@ -787,7 +787,8 @@ 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}"
 		if ! test -z "$update"
 		then
 			update_module=$update
@@ -815,7 +816,7 @@ 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
+			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$config_branch" || exit
 			cloned_modules="$cloned_modules;$name"
 			subsha1=
 		else
@@ -861,7 +862,12 @@ Maybe you want to use 'update --init'?")"
 			case ";$cloned_modules;" in
 			*";$name;"*)
 				# then there is no local change to integrate
-				update_module= ;;
+				if test -n "$config_branch"; then
+					update_module="!git reset --hard -q"
+				else
+					update_module=
+				fi
+				;;
 			esac
 
 			must_die_on_failure=
-- 
1.8.4.100.gd81c160.dirty

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 16:17           ` [RFC v2] submodule: Respect requested " W. Trevor King
@ 2014-01-05 19:48             ` Heiko Voigt
  2014-01-05 21:24               ` W. Trevor King
  2014-01-05 21:27             ` Francesco Pretto
  2014-01-07 18:15             ` Junio C Hamano
  2 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-05 19:48 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

On Sun, Jan 05, 2014 at 08:17:00AM -0800, W. Trevor King wrote:
> From: "W. Trevor King" <wking@tremily.us>
> 
> The previous code only checked out the requested branch in cmd_add.
> This commit moves the branch-checkout logic into module_clone, where
> it can be shared by cmd_add and cmd_update.  I also update the initial
> checkout command to use 'rebase' to preserve branches setup during
> module_clone.
> 
> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---
> Changes since v1:
> * Fix a 'reqested' -> 'requested' typo in the subject/summary.
> * Restore a post-clone 'git checkout -f -q' for the empty-branch case
>   in module_clone().
> * Distinguish between $branch (which defaults to 'master') and a new
>   $config_branch (which defaults to empty) in cmd_update
> 
> After these fixes, all the existing submodule tests pass.  If we want
> to merge this, we'd still want new tests that demonstrate the new
> functionality.

I think this patch is going in the right direction. Making add() and
update() do the same is the right thing to do.

I would still like a complete description of Francesco's use case
though. Francesco: Could you give us a short description about what
exactly is your use-case? And please ignore all technical details how we
are going to implement this. I would like to know how, in an ideal
world, you would expect git to behave. Do you really only care about

	git submodule add

and the *initial*

	git submodule update

?

What happens if a developer already has the submodule and wants to work
on a feature?

> On Sun, Jan 05, 2014 at 04:53:12AM +0100, Francesco Pretto wrote:
> > If I understand it correctly, looking at your intervention in
> > module_clone and cmd_update, when "submodule.<module>.branch" is set
> > during "update" the resulting first clone will always be a branch
> > checkout (cause $branch is filled with "branch" property).
> 
> That's correct.
> 
> > I believe this will break a lot of tests,
> 
> Thanks for prompting me to run the tests.  This v2 now passes all of
> the current submodule tests, and the functionality actually matches my
> earlier descriptions of it ;).
> 
> > as the the documentation says that in this configuration the HEAD
> > should be detached.
> 
> The current Documentation/git-submodule.txt has:
> 
>   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`.
> 
> It's not clear if this refers to the initial-clone update, future
> post-clone updates, or both.  Ideally, the behavior should be the
> same, but in the initial-clone case we don't have an existing
> checked-out branch to work with.

I do not think that its actually important to end up with a detached
HEAD. The documentation just states it because in most cases there is no
other option. But I do not think anything will break if a branch points
to the exact sha1 we would checkout and we checkout the branch instead.

> > Also it could break some users that rely on the current behavior.
> 
> The current code always has a detached HEAD after an initial-clone
> update, regardless of submodule.<name>.update, which doesn't match
> those docs either.  Adding a check to only checkout
> submodule.<name>.branch if submodule.<name>.update was 'rebase',
> 'merge', or 'none' would be easy, but I don't think that makes much
> sense.  I can't see any reason for folks who specify
> submodule.<name>.branch to prefer a detached HEAD over a local branch
> matching the remote branch's name.  If they prefer checkout updates,
> the first such update will return them to a detached HEAD.  If they
> prefer merge/rebase updates, future updates will keep them on the same
> branch.  All my commit does is setup that initial branch for folks who
> get the submodule via 'update', in the same way it's currently setup
> for folks who get the submodule via 'add'.

I like your goal of putting this logic into one place. But a few things
still could be improved IMO.

>  git-submodule.sh | 34 ++++++++++++++++++++--------------
>  1 file changed, 20 insertions(+), 14 deletions(-)
> 
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 2979197..167d4fa 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -253,6 +253,7 @@ module_clone()
>  	url=$3
>  	reference="$4"
>  	depth="$5"
> +	branch="$6"
>  	quiet=
>  	if test -n "$GIT_QUIET"
>  	then
> @@ -306,7 +307,15 @@ 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" &&
> +		case "$branch" in
> +		'') git checkout -f -q ;;
> +		?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
> +		esac
> +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
>  }
>  
>  isnumber()
> @@ -469,16 +478,7 @@ 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'")"
> +		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$branch" || exit
>  	fi
>  	git config submodule."$sm_name".url "$realrepo"
>  
> @@ -787,7 +787,8 @@ 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}"
>  		if ! test -z "$update"
>  		then
>  			update_module=$update
> @@ -815,7 +816,7 @@ 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
> +			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$config_branch" || exit

In the simple case (update=checkout, no branch specified) with the new
checkout branch stuff in module_clone() this code here ends up calling
checkout twice.  First for master and then here later with the sha1.
This feels a little bit double. I would prefer if we skip the checkout
in module_clone() if its not necessary.

How about we move the whole "what to checkout"-decision into one place
instead of having it in update() and moving it from add() into
module_clone() ?

Previously there was not much in add() regarding checkout but since it
seems to grow (and now parts need to be shared between add() and
update()). I would like it if we could move that code into one central
location.

>  			cloned_modules="$cloned_modules;$name"
>  			subsha1=
>  		else
> @@ -861,7 +862,12 @@ Maybe you want to use 'update --init'?")"
>  			case ";$cloned_modules;" in
>  			*";$name;"*)
>  				# then there is no local change to integrate
> -				update_module= ;;
> +				if test -n "$config_branch"; then
> +					update_module="!git reset --hard -q"

If we get here the checkout has already been done. Shouldn't this rather
specify a noop. I.E. like

	update_module="!true"

?

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-05  2:50         ` [PATCH 2/2] Introduce git submodule attached update Francesco Pretto
@ 2014-01-05 19:55           ` Francesco Pretto
  2014-01-05 20:33           ` Heiko Voigt
  1 sibling, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-05 19:55 UTC (permalink / raw)
  To: git
  Cc: Francesco Pretto, Jens Lehmann, Heiko Voigt, W. Trevor King,
	Junio C Hamano

(Hmmpth, forgot signoff...)

To whom it may interest, added some CC.

2014/1/5 Francesco Pretto <ceztko@gmail.com>:
> At the current state, the following use-case is not supported very
> well in git:
> - a maintainer adds a submodule, checking out a specific branch of
> the repository. He doesn't track the upstream submodule revision sha1;
> - a developer checkout the repository branch decided by the maintainer.
> Subsequent "merge" or "rebase" update operations don't detach the HEAD.
>
> To ease the above use-case this patch:
> - introduces a "submodule.<module>.attached" property that, when set
>   to "true", ensures that the "update" operation will result in
>   the HEAD attached to a branch;
> - introduces "--attach|--dettach" switches to the submodule "update"
>   command: they attach/detach the HEAD, overriding
>   "submodule.<module>.attached" property value;
> - introduces "--attached-update" switch to the "add" operation. It:
>     * sets "submodule.<module>.attached" to true;
>     * sets "submodule.<module>.ignore" to all.
>
> Using the '--attach' switch or operating in a repository with
> 'submodule.<name>.attached' set to 'true' during "update" will:
> - checkout a branch with an attached HEAD if the repository was just
> cloned;
> - perform a fast-forward only merge of changes if it's a 'checkout'
> update operation;
> - reattach the HEAD prior performing a 'merge', 'rebase' or '!command'
> update operation if the HEAD was found detached. Orphaned commits
> will also be merged back in the branch.
>
> '--attach' or 'submodule.<name>.attached' set to true also implies '--remote'.
>
> Using  the '--detach' switch or operating in a repository with
> 'submodule.<name>.attached' set to 'false' during "update" will:
> - checkout a detached HEAD if the repository was just cloned;
> - detach the HEAD prior performing a 'merge', 'rebase' or '!command'
> update operation if the HEAD was found attached.
>
> 'submodule.<name>.attached' works similarly to 'submodule.<name>.update'
> property: git copies the values found in ".gitmodules" in ".git/config" when
> performing an "init" command. "update" looks for values in ".git/config"
> only.
>
> '--attach' and '--detach' switches override an opposite behaviour
> of 'submodule.<name>.attached' properties.
>
> The patch is strongly additive and doesn't break any submodule specific
> test. It also adds some tests specific to the added feature.
> ---
>  Documentation/git-submodule.txt    |  48 +++++--
>  Documentation/gitmodules.txt       |  10 +-
>  git-submodule.sh                   | 154 +++++++++++++++++++--
>  t/t7410-submodule-attached-head.sh | 268 +++++++++++++++++++++++++++++++++++++
>  4 files changed, 457 insertions(+), 23 deletions(-)
>  create mode 100755 t/t7410-submodule-attached-head.sh
>
> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
> index bfef8a0..b97eefb 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -10,13 +10,14 @@ SYNOPSIS
>  --------
>  [verse]
>  'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
> -             [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
> +             [--reference <repository>] [--attached-update] [--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>] [--depth <depth>]
> -             [--merge] [--recursive] [--] [<path>...]
> +             [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach]
> +             [--depth <depth>] [--merge] [--recursive] [--] [<path>...]
>  'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
>               [commit] [--] [<path>...]
>  'git submodule' [--quiet] foreach [--recursive] <command>
> @@ -107,6 +108,9 @@ is the superproject and submodule repositories will be kept
>  together in the same relative location, and only the
>  superproject's URL needs to be provided: git-submodule will correctly
>  locate the submodule using the relative URL in .gitmodules.
> ++
> +If `--attached-update` is specified, the property `submodule.<name>.attached`
> +will be set to `true` and `submodule.<name>.ignore` will be set to `all`.
>
>  status::
>         Show the status of the submodules. This will print the SHA-1 of the
> @@ -156,12 +160,15 @@ 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.
> +       This will make the submodules HEAD be detached unless `--attach` is
> +       specified or `submodule.$name.attached` is set to `true`. The last setting
> +       can always be overridden specifying `--detach`. Update mode can be
> +       selected specifying `--checkout`, `--rebase` or `--merge` switches
> +       or setting the key `submodule.$name.update` to `checkout`, `rebase`,
> +       `merge` or `none`. `none` will cause the submodule to be skipped during
> +       the update. 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
> @@ -270,6 +277,23 @@ OPTIONS
>         be overridden by setting the `submodule.<name>.branch` option in
>         either `.gitmodules` or `.git/config` (with `.git/config` taking
>         precedence).
> +
> +--attached-update::
> +       This option is only valid for the add command. Causes the add command
> +       also to set the property `submodule.<name>.attached` to `true` and
> +       the property `submodule.<name>.ignore` to `all`.
> +
> +--attach::
> +       This option is only valid for the update commands. Causes the result
> +       of an update operation to be an attached HEAD. In the update operation,
> +       the branch named by 'submodule.<name>.branch' is checked out as the new
> +       HEAD of the submodule repository. If 'submodule.<name>.branch' is not
> +       set, the 'master' branch is checked out as the new HEAD of the
> +       submodule. Note: `--attach` also implies `--remote`.
> +
> +--detach::
> +       This option is only valid for the update command. Forces the result
> +       of the update operation to be a detached HEAD in the submodule.
>  +
>  This works for any of the supported update procedures (`--checkout`,
>  `--rebase`, etc.).  The only change is the source of the target SHA-1.
> @@ -290,8 +314,7 @@ SHA-1.  If you don't want to fetch, you should use `submodule update
>  --merge::
>         This option is only valid for the update command.
>         Merge the commit recorded in the superproject into the current branch
> -       of the submodule. If this option is given, the submodule's HEAD will
> -       not be detached. If a merge failure prevents this process, you will
> +       of the submodule. If a merge failure prevents this process, you will
>         have to resolve the resulting conflicts within the submodule with the
>         usual conflict resolution tools.
>         If the key `submodule.$name.update` is set to `merge`, this option is
> @@ -300,8 +323,7 @@ SHA-1.  If you don't want to fetch, you should use `submodule update
>  --rebase::
>         This option is only valid for the update command.
>         Rebase the current branch onto the commit recorded in the
> -       superproject. If this option is given, the submodule's HEAD will not
> -       be detached. If a merge failure prevents this process, you will have
> +       superproject. If a merge failure prevents this process, you will have
>         to resolve these failures with linkgit:git-rebase[1].
>         If the key `submodule.$name.update` is set to `rebase`, this option is
>         implicit.
> diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
> index f7be93f..9c436db 100644
> --- a/Documentation/gitmodules.txt
> +++ b/Documentation/gitmodules.txt
> @@ -38,7 +38,8 @@ submodule.<name>.url::
>  submodule.<name>.update::
>         Defines what to do when the submodule is updated by the superproject.
>         If 'checkout' (the default), the new commit specified in the
> -       superproject will be checked out in the submodule on a detached HEAD.
> +       superproject (or branch, with '--attach') will be checked out in
> +       the submodule.
>         If 'rebase', the current branch of the submodule will be rebased onto
>         the commit specified in the superproject. If 'merge', the commit
>         specified in the superproject will be merged into the current branch
> @@ -54,6 +55,13 @@ submodule.<name>.branch::
>         If the option is not specified, it defaults to 'master'.  See the
>         `--remote` documentation in linkgit:git-submodule[1] for details.
>
> +submodule.<name>.attached::
> +       Determine if the update operation will produce a detached HEAD or not.
> +       Valid values are `true` or `false`. If the property is set to `true`
> +       and `submodule.<name>.branch` is not set, the branch `master` will
> +       be checked out. If `submodule.<name>.branch` is set the branch
> +       specified will be checked out instead.
> +
>  submodule.<name>.fetchRecurseSubmodules::
>         This option can be used to control recursive fetching of this
>         submodule. If this option is also present in the submodules entry in
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 1d041a7..bc6df2b 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -5,11 +5,11 @@
>  # Copyright (c) 2007 Lars Hjemli
>
>  dashless=$(basename "$0" | sed -e 's/-/ /')
> -USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
> +USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--attached-update] [--] <repository> [<path>]
>     or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
>     or: $dashless [--quiet] init [--] [<path>...]
>     or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
> -   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
> +   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--attach | --detach] [--merge] [--recursive] [--] [<path>...]
>     or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
>     or: $dashless [--quiet] foreach [--recursive] <command>
>     or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
> @@ -36,6 +36,9 @@ update=
>  prefix=
>  custom_name=
>  depth=
> +attach=
> +detach=
> +attached_update=
>
>  # The function takes at most 2 arguments. The first argument is the
>  # URL that navigates to the submodule origin repo. When relative, this URL
> @@ -352,6 +355,9 @@ cmd_add()
>                         custom_name=$2
>                         shift
>                         ;;
> +               --attached-update)
> +                       attached_update=yes
> +                       ;;
>                 --depth)
>                         case "$2" in '') usage ;; esac
>                         depth="--depth=$2"
> @@ -491,6 +497,12 @@ Use -f if you really want to add it." >&2
>         then
>                 git config -f .gitmodules submodule."$sm_name".branch "$branch"
>         fi &&
> +       if test -n "$attached_update"
> +       then
> +               # We'll stay stick to the HEAD, no need to track revision sha1
> +               git config -f .gitmodules submodule."$sm_name".attached "true"
> +               git config -f .gitmodules submodule."$sm_name".ignore "all"
> +       fi &&
>         git add --force .gitmodules ||
>         die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
>  }
> @@ -632,6 +644,22 @@ cmd_init()
>                         git config submodule."$name".update "$upd" ||
>                         die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
>                 fi
> +
> +               # Copy "attached" setting when it is not set yet
> +               if attached="$(git config -f .gitmodules submodule."$name".attached)" &&
> +                  test -n "$attached" &&
> +                  test -z "$(git config submodule."$name".attached)"
> +               then
> +                       case "$attached" in
> +                       true | false)
> +                               ;; # Valid attach flag values
> +                       *)
> +                               echo >&2 "warning: invalid attach flag value for submodule '$name'"
> +                               ;;
> +                       esac
> +                       git config submodule."$name".attached "$attached" ||
> +                       die "$(eval_gettext "Failed to register attach option for submodule path '\$displaypath'")"
> +               fi
>         done
>  }
>
> @@ -750,6 +778,14 @@ cmd_update()
>                 --reference=*)
>                         reference="$1"
>                         ;;
> +               --attach)
> +                       if test -n "$detach" ; then usage ; fi
> +                       attach=1
> +                       ;;
> +               --detach)
> +                       if test -n "$attach" ; then usage ; fi
> +                       detach=1
> +                       ;;
>                 -m|--merge)
>                         update="merge"
>                         ;;
> @@ -800,6 +836,28 @@ cmd_update()
>                 name=$(module_name "$sm_path") || exit
>                 url=$(git config submodule."$name".url)
>                 branch=$(get_submodule_config "$name" branch master)
> +               attach_module=
> +               detach_module=
> +               if test -n "$attach" -o -n "$detach"
> +               then
> +                       attach_module=$attach
> +                       detach_module=$detach
> +               else
> +                       attached=$(git config submodule."$name".attached)
> +                       case "$attached" in
> +                       '')
> +                               ;; # Unset attach flag
> +                       true)
> +                               attach_module=1
> +                               ;;
> +                       false)
> +                               detach_module=1
> +                               ;;
> +                       *)
> +                               echo >&2 "warning: invalid attach flag value for submodule '$name'"
> +                               ;;
> +                       esac
> +               fi
>                 if ! test -z "$update"
>                 then
>                         update_module=$update
> @@ -848,7 +906,16 @@ Maybe you want to use 'update --init'?")"
>                         die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
>                 fi
>
> -               if test -n "$remote"
> +               head_rev_ref=$(clear_local_git_env; cd "$sm_path" && git rev-parse --abbrev-ref HEAD) ||
> +               die "$(eval_gettext "Unable to determine revision ref in submodule path '\$sm_path'")"
> +               head_detached=
> +               if test "$head_rev_ref" = "HEAD"
> +               then
> +                       # Determine if the HEAD is detached
> +                       head_detached="true"
> +               fi
> +
> +               if test -n "$remote" -o -n "$attach_module"
>                 then
>                         if test -z "$nofetch"
>                         then
> @@ -862,7 +929,8 @@ Maybe you want to use 'update --init'?")"
>                         die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
>                 fi
>
> -               if test "$subsha1" != "$sha1" -o -n "$force"
> +               if test "$subsha1" != "$sha1" || test -n "$attach_module" -a -n "$head_detached" ||
> +                       test -n "$detach_module" -a -z "$head_detached" || test -n "$force"
>                 then
>                         subforce=$force
>                         # If we don't already have a -f flag and the submodule has never been checked out
> @@ -882,40 +950,108 @@ Maybe you want to use 'update --init'?")"
>                         fi
>
>                         # Is this something we just cloned?
> +                       just_cloned=
>                         case ";$cloned_modules;" in
>                         *";$name;"*)
>                                 # then there is no local change to integrate
> -                               update_module= ;;
> +                               update_module="checkout"
> +                               just_cloned=yes
> +                               ;;
>                         esac
>
> +                       if test -z "$update_module"
> +                       then
> +                               # Fallback to checkout
> +                               update_module="checkout"
> +                       fi
> +
> +                       command_attach=:
> +                       suffix_attach=
> +                       if test "$update_module" != "checkout"
> +                       then
> +                               if test -n "$attach_module" -a -n "$head_detached"
> +                               then
> +                                       # We need to reattach to the branch
> +                                       command_attach="git checkout $subforce -q"
> +                                       suffix_attach=$branch
> +                               elif test -n "$detach_module" -a -z "$head_detached"
> +                               then
> +                                       # We need to detach from the branch
> +                                       command_attach="git checkout $subforce -q"
> +                                       suffix_attach=$sha1
> +                               fi
> +                       fi
> +
> +                       command_pre=:
> +                       suffix_pre=
> +                       command_post=:
> +                       suffix_pre=
> +                       suffix=
>                         must_die_on_failure=
> +                       custom_update=
>                         case "$update_module" in
>                         rebase)
>                                 command="git rebase"
> +                               suffix=$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
> +                               if test -n "$attach_module" -a -n "$head_detached" && test "$subsha1" != "$sha1"
> +                               then
> +                                       # After the rebase, we merge orphaned commits in the branch
> +                                       command_post="git merge"
> +                                       suffix_post=$subsha1
> +                               fi
>                                 ;;
>                         merge)
> +                               if test -n "$attach_module" -a -n "$head_detached" && test "$subsha1" != "$sha1"
> +                               then
> +                                       # Prior the rebase, we merge orphaned commits in in the branch
> +                                       command_pre="git merge"
> +                                       suffix_pre=$subsha1
> +                               fi
>                                 command="git merge"
> +                               suffix=$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
>                                 ;;
> +                       checkout)
> +                               if test -n "$attach_module"
> +                               then
> +                                       command="git checkout $subforce -q"
> +                                       suffix=$branch
> +                                       die_msg="$(eval_gettext "Unable to checkout banch '\$branch' in submodule path '\$displaypath'")"
> +                                       say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out branch '\$branch'")"
> +                                       if test -z "$just_cloned" -a && test "$subsha1" != "$sha1"
> +                                       then
> +                                               # Perform a fast-forward only merge of the origin
> +                                               command_post="git merge $subforce --ff-only"
> +                                               suffix_post="origin/$branch"
> +                                       fi
> +                               else
> +                                       command="git checkout $subforce -q"
> +                                       suffix=$sha1
> +                                       die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
> +                                       say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
> +                               fi
> +                               ;;
>                         !*)
>                                 command="${update_module#!}"
> +                               suffix=$sha1
>                                 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
> +                               custom_update=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'")"
> +                               # Valid user configurable update modes are already filtered above
> +                               die "$(eval_gettext "Unexpected update mode in the current flow")"
>                                 ;;
>                         esac
>
> -                       if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
> +                       if (clear_local_git_env; cd "$sm_path" && $command_attach "$suffix_attach" &&
> +                               $command_pre "$suffix_pre" && $command "$suffix" && $command_post "$suffix_pro")
>                         then
>                                 say "$say_msg"
>                         elif test -n "$must_die_on_failure"
> diff --git a/t/t7410-submodule-attached-head.sh b/t/t7410-submodule-attached-head.sh
> new file mode 100755
> index 0000000..04b3018
> --- /dev/null
> +++ b/t/t7410-submodule-attached-head.sh
> @@ -0,0 +1,268 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2014 Francesco Pretto
> +#
> +
> +test_description='Support for submodules with attached head
> +
> +This test verifies the sanity of the add and update git submodule commands with
> +or without the --attached-update, --attach, --detach switches or the
> +submoudule.<module>.attach property set
> +'
> +
> +TEST_NO_CREATE_REPO=true
> +. ./test-lib.sh
> +
> +submodurl1=$(pwd -P)/repo1
> +submodurl2=$(pwd -P)/repo2
> +repourl=$(pwd -P)/repo
> +
> +test_expect_success 'setup - create repository "repo1" to be used as submodule' '
> +       mkdir repo1 &&
> +       (
> +               cd repo1 &&
> +               git init &&
> +               git config receive.denyCurrentBranch ignore &&
> +               echo a >a &&
> +               git add a &&
> +               git commit -m "repo1 commit 1"
> +       )
> +'
> +
> +test_expect_success 'setup - reate repository "repo2" to be used as submodule' '
> +       mkdir repo2 &&
> +       (
> +               cd repo2 &&
> +               git init &&
> +               git config receive.denyCurrentBranch ignore &&
> +               echo a >a &&
> +               git add a &&
> +               git commit -m "repo2 commit 1"
> +       )
> +'
> +
> +test_expect_success 'setup - create repository "repo" to be added with sumodules' '
> +       mkdir repo &&
> +       (
> +               cd repo &&
> +               git init &&
> +               git config receive.denyCurrentBranch ignore &&
> +               echo a >a &&
> +               git add a &&
> +               git commit -m "repo commit 1"
> +       )
> +'
> +
> +test_expect_success 'setup - clone repository "repo" in "repoclone"' '
> +       git clone "$repourl" repoclone
> +'
> +
> +test_expect_success 'setup - add "mod1" as regular submodule of "repo"' '
> +       (
> +               cd repo &&
> +               git submodule add "$submodurl1" submod1
> +       )
> +'
> +
> +test_expect_success 'setup - add "mod2" as update attached HEAD submodule of "repo"' '
> +       (
> +               cd repo &&
> +               git submodule add --attached-update "$submodurl2" submod2
> +       )
> +'
> +
> +test_expect_success 'setup - commit submodules in repo' '
> +       (
> +               cd repo &&
> +               git add . &&
> +               git commit -m "Added submodules"
> +       )
> +'
> +
> +test_expect_success 'init submodules in cloned repo' '
> +       (
> +               cd repoclone &&
> +               git pull &&
> +               git submodule init
> +       )
> +'
> +
> +test_expect_success 'update submodules in cloned repo' '
> +       (
> +               cd repoclone &&
> +               git submodule update
> +       )
> +'
> +
> +test_expect_success 'assert submod1 HEAD is detached in cloned repo' '
> +       (
> +               cd repoclone/submod1 &&
> +               test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
> +       )
> +'
> +
> +test_expect_success 'assert submod2 HEAD is attached in cloned repo' '
> +       (
> +               cd repoclone/submod2 &&
> +               test "$(git rev-parse --abbrev-ref HEAD)" != "HEAD"
> +       )
> +'
> +
> +test_expect_success 'update submodules with --attach in cloned repo' '
> +       (
> +               cd repoclone &&
> +               git submodule update --attach
> +       )
> +'
> +
> +test_expect_success 'assert submod1 HEAD is attached in cloned repo' '
> +       (
> +               cd repoclone/submod1 &&
> +               test "$(git rev-parse --abbrev-ref HEAD)" != "HEAD"
> +       )
> +'
> +
> +test_expect_success 'update submodules with --detach in cloned repo' '
> +       (
> +               cd repoclone &&
> +               git submodule update --detach
> +       )
> +'
> +
> +test_expect_success 'assert submod1 HEAD is detached in cloned repo' '
> +       (
> +               cd repoclone/submod1 &&
> +               test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
> +       )
> +'
> +
> +test_expect_success 'assert submod2 HEAD is detached in cloned repo' '
> +       (
> +               cd repoclone/submod2 &&
> +               test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
> +       )
> +'
> +
> +test_expect_success 'update submodules in cloned repo (will restore HEAD states)' '
> +       (
> +               cd repoclone &&
> +               git submodule update
> +       )
> +'
> +
> +test_expect_success 'assert submod1 HEAD is detached in cloned repo' '
> +       (
> +               cd repoclone/submod1 &&
> +               test "$(git rev-parse --abbrev-ref HEAD)" = "HEAD"
> +       )
> +'
> +
> +test_expect_success 'assert submod2 HEAD is attached in cloned repo' '
> +       (
> +               cd repoclone/submod2 &&
> +               test "$(git rev-parse --abbrev-ref HEAD)" != "HEAD"
> +       )
> +'
> +
> +test_expect_success 'setup - add update operation to submodules' '
> +       (
> +               cd repo &&
> +               git config  -f .gitmodules submodule.submod1.update merge &&
> +               git config  -f .gitmodules submodule.submod2.update rebase &&
> +               git add . &&
> +               git commit -m "updated submodules"
> +       )
> +'
> +
> +test_expect_success 'setup - update cloned repo and reinitialize submodules' '
> +       (
> +               cd repoclone &&
> +               git pull &&
> +               git submodule init
> +       )
> +'
> +
> +test_expect_success 'add some content to repo2' '
> +       (
> +               cd repo2 &&
> +               echo b >b &&
> +               git add b &&
> +               git commit -m "repo2 commit 2"
> +       )
> +'
> +
> +test_expect_success 'update sumodules in cloned repo and verify that submod2 matches repo2' '
> +       (
> +               cd repoclone &&
> +               git submodule update &&
> +               test -e submod2/b
> +       )
> +'
> +
> +test_expect_success 'prepend some content to repo1/a' '
> +       (
> +               cd repo1 &&
> +               echo -e "b\na" >a &&
> +               git add a &&
> +               git commit -m "repo1 commit 2"
> +       )
> +'
> +
> +test_expect_success 'append some content in repoclone/submod1 and commit' '
> +       (
> +               cd repoclone/submod1 &&
> +               echo c >>a &&
> +               git add a &&
> +               git commit -m "submod1 commit 1"
> +       )
> +'
> +
> +test_expect_success 'update repoclone submodules with --attach' '
> +       (
> +               cd repoclone &&
> +               git submodule update --attach
> +       )
> +'
> +
> +test_expect_success 'verify repoclone submod1 merge with reattached orphaned commits was correct' '
> +       (
> +               cd repoclone/submod1 &&
> +               test "$(<a)" = "$'b\na\nc'"
> +       )
> +'
> +
> +test_expect_success 'setup - set operation checkout to submodule sumod1 in repo' '
> +       (
> +               cd repo &&
> +               git config  -f .gitmodules submodule.submod1.update checkout &&
> +               git add . &&
> +               git commit -m "updated submodules"
> +       )
> +'
> +
> +test_expect_success 'setup - update cloned repo and reinitialize submodules' '
> +       (
> +               cd repoclone &&
> +               git pull &&
> +               git submodule init
> +       )
> +'
> +
> +test_expect_success 'add some content to repo1' '
> +       (
> +               cd repo1 &&
> +               echo b >b &&
> +               git add b &&
> +               git commit -m "repo1 commit 3"
> +       )
> +'
> +
> +test_expect_success 'update submodule submod2 (merge ff-only) and verify it matches repo2' '
> +       (
> +               cd repoclone &&
> +               git submodule update &&
> +               test -e submod2/b
> +       )
> +'
> +
> +test_done
> --
> 1.8.5.2.230.g032cd47.dirty
>

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command
  2014-01-05  2:50       ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Francesco Pretto
  2014-01-05  2:50         ` [PATCH 2/2] Introduce git submodule attached update Francesco Pretto
@ 2014-01-05 20:20         ` Heiko Voigt
  2014-01-05 20:44         ` W. Trevor King
  2 siblings, 0 replies; 144+ messages in thread
From: Heiko Voigt @ 2014-01-05 20:20 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: git

On Sun, Jan 05, 2014 at 03:50:48AM +0100, Francesco Pretto wrote:
> According to "Documentation/gitmodules.txt", 'checkout' is a valid
> 'submodule.<name>.update' command. Also "git-submodule.sh" refers to
> it and processes it correctly. Reflect commit 'ac1fbb' to support this
> syntax and also validates property values during 'update' command,
> issuing a warning if the value found is unknwon.

s/unknwon/unknown/

> ---
>  git-submodule.sh | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 2677f2e..1d041a7 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -622,7 +622,7 @@ cmd_init()
>  		   test -z "$(git config submodule."$name".update)"
>  		then
>  			case "$upd" in
> -			rebase | merge | none)
> +			checkout | rebase | merge | none)
>  				;; # known modes of updating
>  			*)
>  				echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
> @@ -805,6 +805,18 @@ cmd_update()
>  			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
> +			*)
> +				update_module=
> +				echo >&2 "warning: invalid update mode for submodule '$name'"

How about additionally telling the user the current value that is wrong
like this:

	echo >&2 "warning: invalid update mode '$update_module' for submodule '$name'"

?

But apart from those minor nits the patch looks good to me.

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-05  2:50         ` [PATCH 2/2] Introduce git submodule attached update Francesco Pretto
  2014-01-05 19:55           ` Francesco Pretto
@ 2014-01-05 20:33           ` Heiko Voigt
  2014-01-05 21:46             ` Francesco Pretto
  2014-01-05 23:22             ` Francesco Pretto
  1 sibling, 2 replies; 144+ messages in thread
From: Heiko Voigt @ 2014-01-05 20:33 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: git, Jens Lehmann

On Sun, Jan 05, 2014 at 03:50:49AM +0100, Francesco Pretto wrote:
> At the current state, the following use-case is not supported very
> well in git:
> - a maintainer adds a submodule, checking out a specific branch of
> the repository. He doesn't track the upstream submodule revision sha1;
> - a developer checkout the repository branch decided by the maintainer.
> Subsequent "merge" or "rebase" update operations don't detach the HEAD.

Could you please extend the description of your use-case so we can
understand your goal better?

The following questions directly pop into my mind:

 - What means the maintainer does not track the submodules sha1? Does
   that mean the superproject always refers to submodule commits using
   branches?
 - What happens if you want to go back to an earlier revision? Lets say
   a tagged release? How is ensured that you get the correct revision in
   the submodules?
 - In which situations does the developer or maintainer switch between
   your attached/detached mode?
 - What is the "repository branch" which is given to the developer by
   the maintainer used for? Who creates this branch and who merges into
   it?
 - What are these subsequent "merge" or "rebase" update operations? Do
   you mean everyone has submodule.name.update configured to merge or
   rebase?

Still puzzled.

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command
  2014-01-05  2:50       ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Francesco Pretto
  2014-01-05  2:50         ` [PATCH 2/2] Introduce git submodule attached update Francesco Pretto
  2014-01-05 20:20         ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Heiko Voigt
@ 2014-01-05 20:44         ` W. Trevor King
  2014-01-06 16:20           ` Junio C Hamano
  2 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-05 20:44 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: git, Heiko Voigt

[-- Attachment #1: Type: text/plain, Size: 971 bytes --]

On Sun, Jan 05, 2014 at 03:50:48AM +0100, Francesco Pretto wrote:
> +			case "$update_module" in
> +			'')
> +				;; # Unset update mode
> +			checkout | rebase | merge | none)
> +				;; # Known update modes
> +			!*)
> +				;; # Custom update command
> +			*)
> +				update_module=
> +				echo >&2 "warning: invalid update mode for submodule '$name'"
> +				;;
> +			esac

I'd prefer `die "…"` to `echo >&2 "…"`.  It's hard to know if mapping
the user's preferred (unknown) update mechanism to 'checkout' is
serious or not.

This commit also makes me think that --rebase, --merge, and --checkout
should be replaced with a single --update={rebase|merge|checkout|!…}
option, but that's probably food for another commit (and a long
finger-breaking deprecation period).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 19:48             ` Heiko Voigt
@ 2014-01-05 21:24               ` W. Trevor King
  2014-01-05 22:57                 ` Heiko Voigt
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-05 21:24 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 4112 bytes --]

On Sun, Jan 05, 2014 at 08:48:50PM +0100, Heiko Voigt wrote:
> On Sun, Jan 05, 2014 at 08:17:00AM -0800, W. Trevor King wrote:
> > It's not clear if this refers to the initial-clone update, future
> > post-clone updates, or both.  Ideally, the behavior should be the
> > same, but in the initial-clone case we don't have an existing
> > checked-out branch to work with.
> 
> I do not think that its actually important to end up with a detached
> HEAD. The documentation just states it because in most cases there
> is no other option. But I do not think anything will break if a
> branch points to the exact sha1 we would checkout and we checkout
> the branch instead.

There's no "if the remote-tracking branch points to the exact sha1"
logic in my patch.  If submodule.<name>.branch is set, it *always*
creates a new local branch of that name pointing to the exact sha1.
If submodule.<name>.branch is not set, we still create a detached-HEAD
checkout of the exact sha1.  Thinking through this more, perhaps the
logic should be:

* If submodule.<name>.update (defaulting to checkout) is checkout,
  create a detached HEAD.
* Otherwise, create a new branch submodule.<name>.branch (defaulting
  to master).

The motivation is that if submodule.<name>.update is checkout, the
user is unlikely to be developing locally in the submodule, as
subsequent updates would clobber their local commits.  Having a
detached HEAD is a helpful "don't develop here" reminder ;).  If
submodule.<name>.update is set, the user is likely to be developing
locally, and will probably want a local branch already checked out to
facilitate that.

> > -			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
> > +			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$config_branch" || exit
> 
> In the simple case (update=checkout, no branch specified) with the
> new checkout branch stuff in module_clone() this code here ends up
> calling checkout twice.  First for master and then here later with
> the sha1.  This feels a little bit double.

There is no guarantee that the remote master and the exact sha1 point
at the same commit.  Ideally we'd just clone the exact sha1 in this
case.

> I would prefer if we skip the checkout in module_clone() if its not
> necessary.

When I tried to drop the '' case here:

> > @@ -306,7 +307,15 @@ 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" &&
> > +		case "$branch" in
> > +		'') git checkout -f -q ;;
> > +		?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
> > +		esac
> > +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
> >  }

I got test-suite errors that I didn't get to the bottom of.  However…

> How about we move the whole "what to checkout"-decision into one place
> instead of having it in update() and moving it from add() into
> module_clone() ?

…this sounds like a good idea to me.  However, it would be a more
intrusive change, and there may be conflicts with Francesco's proposed
attach/detach functionality.  I'll wait until we have a clearer idea
of where that is headed before I attempt a more complete
consolidation.

> > -				update_module= ;;
> > +				if test -n "$config_branch"; then
> > +					update_module="!git reset --hard -q"
> 
> If we get here the checkout has already been done. Shouldn't this
> rather specify a noop. I.E. like
> 
> 	update_module="!true"

We are on a local branch at this point, but not neccessarily pointing
at the gitlinked sha1.  The reset here ensures that the new local
branch does indeed point at the gitlinked sha1.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 16:17           ` [RFC v2] submodule: Respect requested " W. Trevor King
  2014-01-05 19:48             ` Heiko Voigt
@ 2014-01-05 21:27             ` Francesco Pretto
  2014-01-05 21:47               ` W. Trevor King
  2014-01-06 14:47               ` Heiko Voigt
  2014-01-07 18:15             ` Junio C Hamano
  2 siblings, 2 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-05 21:27 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Junio C Hamano, Jens Lehmann, Heiko Voigt

2014/1/5 W. Trevor King <wking@tremily.us>:
> On Sun, Jan 05, 2014 at 04:53:12AM +0100, Francesco Pretto wrote:
>> Also it could break some users that rely on the current behavior.
>
> The current code always has a detached HEAD after an initial-clone
> update, regardless of submodule.<name>.update, which doesn't match
> those docs either.

I perfectly agree with you that the documentation is a bit
contradictory with regard to "update" command and detached HEAD.
That's why it's so hard to add a feature and keep the same spirit of
those that coded submodules at first. Also, I think that submodules
didn't get much feedback with regards to these pitfalls because many
people try to setup them, they see that "update" detaches the HEAD and
they think "hmmm, maybe submodules are not what I was looking for".

> Adding a check to only checkout
> submodule.<name>.branch if submodule.<name>.update was 'rebase',
> 'merge', or 'none' would be easy, but I don't think that makes much
> sense.  I can't see any reason for folks who specify
> submodule.<name>.branch to prefer a detached HEAD over a local branch
> matching the remote branch's name.

I think the reason is that it still matches the original use case of
submodules devs:
- the maintainer decides the specific commit developers should have;
- developers checkout that commit and don't pull (you can't do "git
pull" in a detached HEAD);
- they optionally get the upstream commit from the specified
"submodule.<name>.branch" with "--remote". They are still in a
detached HEAD and can't do "git pull".

Maybe who coded submodules at first was thinking that the best way to
contribute to a project is to checkout that repository, and not work
in the submodule. As said, this works well when the submodule
repository is a full project, and not a bunch of shared code.

> If they prefer checkout updates,
> the first such update will return them to a detached HEAD.  If they
> prefer merge/rebase updates, future updates will keep them on the same
> branch.  All my commit does is setup that initial branch for folks who
> get the submodule via 'update', in the same way it's currently setup
> for folks who get the submodule via 'add'.
>

My patch is in the same spirit but wants to obtain the same by being
100% additive and by not altering existing behavior in any way. Also
it covers:
- an "autoremote" behavior when the user wants an attached HEAD: with
your patch "--remote" is still needed to really update the branch with
"git submodule update":
- voluntary reattach/detach the HEAD with command line;
- ff-only merge of changes in the case of "checkout" in an attached
HEAD (doing "git checkout <branch>" is not enough);
- reattach of the HEAD with orphaned commits.

Unfortunately our patches are already a bit colliding. I'll wait for
other comments from git maintainers and let see. Anyway, I'm happy
because things are moving: after this debate git submodules will be
better for sure.

Cheers,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-05 20:33           ` Heiko Voigt
@ 2014-01-05 21:46             ` Francesco Pretto
  2014-01-06 14:06               ` Heiko Voigt
  2014-01-05 23:22             ` Francesco Pretto
  1 sibling, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-05 21:46 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: git, Jens Lehmann

2014/1/5 Heiko Voigt <hvoigt@hvoigt.net>:
>
> Could you please extend the description of your use-case so we can
> understand your goal better?
>

Just in case you missed the first patch iteration[1].

> The following questions directly pop into my mind:
>
>  - What means the maintainer does not track the submodules sha1? Does
>    that mean the superproject always refers to submodule commits using
>    branches?

It means he doesn't need to control other developers commit to be
checked out so he sets "submodule.<name>.ignore" to "all". In this way
he and the developers can work actively in their submodule copy.

>  - What happens if you want to go back to an earlier revision? Lets say
>    a tagged release? How is ensured that you get the correct revision in
>    the submodules?

"submodule.<name>.branch" is one setting that is not copied in
".git/config" by "git submodule init". "git submodule update" will use
the setting in ".gitmodules" if not overridden voluntarily by the
developer in ".git/config". The maintainer can change that setting in
".gitmodules" and commit the change. Modifies will be propagated by
the next "git pull && git submodule update" of the developer in the
superproject.

>  - In which situations does the developer or maintainer switch between
>    your attached/detached mode?

The developer/maintainer does so optionally and voluntarily and it
effects only its private working tree.

>  - What is the "repository branch" which is given to the developer by
>    the maintainer used for? Who creates this branch and who merges into
>    it?

The branch of course must exist prior submodule adding. In this
use-case it does not really matter who creates it and who merges into
it. Everyone with the right to merge into it has to work in the
submodule seamlessly, as it was working on separate clone of the same
repository used as the submodule.

>  - What are these subsequent "merge" or "rebase" update operations? Do
>    you mean everyone has submodule.name.update configured to merge or
>    rebase?
>

subsequent "merge" or "rebase" update operations are just the ones
after the initial clone/checkout, nothing particular.

Greetings,
Francesco

[1] http://marc.info/?l=git&m=138836829531511&w=2

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 21:27             ` Francesco Pretto
@ 2014-01-05 21:47               ` W. Trevor King
  2014-01-05 22:01                 ` W. Trevor King
  2014-01-06 14:47               ` Heiko Voigt
  1 sibling, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-05 21:47 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Git, Junio C Hamano, Jens Lehmann, Heiko Voigt

[-- Attachment #1: Type: text/plain, Size: 3735 bytes --]

On Sun, Jan 05, 2014 at 10:27:19PM +0100, Francesco Pretto wrote:
> 2014/1/5 W. Trevor King:
> > Adding a check to only checkout submodule.<name>.branch if
> > submodule.<name>.update was 'rebase', 'merge', or 'none' would be
> > easy, but I don't think that makes much sense.  I can't see any
> > reason for folks who specify submodule.<name>.branch to prefer a
> > detached HEAD over a local branch matching the remote branch's
> > name.
> 
> I think the reason is that it still matches the original use case of
> submodules devs:
> - the maintainer decides the specific commit developers should have;
> - developers checkout that commit and don't pull (you can't do "git
> pull" in a detached HEAD);
> - they optionally get the upstream commit from the specified
> "submodule.<name>.branch" with "--remote". They are still in a
> detached HEAD and can't do "git pull".
> 
> Maybe who coded submodules at first was thinking that the best way to
> contribute to a project is to checkout that repository, and not work
> in the submodule. As said, this works well when the submodule
> repository is a full project, and not a bunch of shared code.

You're saying that the detached HEAD is a feature because it breaks
pull?  And developers can't be trusted/trained to just not pull
reflexively?  I'm not buying that ;).  Although I was sad to see
jc/pull-training-wheel dropped and have that discussion stall out [1].

> > If they prefer checkout updates, the first such update will return
> > them to a detached HEAD.  If they prefer merge/rebase updates,
> > future updates will keep them on the same branch.  All my commit
> > does is setup that initial branch for folks who get the submodule
> > via 'update', in the same way it's currently setup for folks who
> > get the submodule via 'add'.
> 
> My patch is in the same spirit but wants to obtain the same by being
> 100% additive and by not altering existing behavior in any way.

My v2 patch doesn't break the current test suite.  I'd be surprised if
a change in such peripheral existing behavior as the post clone-update
branch actually break any user code, but I'd be happy to see links
that prove me wrong.

> Also it covers:
> - an "autoremote" behavior when the user wants an attached HEAD:
> with your patch "--remote" is still needed to really update the
> branch with "git submodule update":
> - voluntary reattach/detach the HEAD with command line;
> - ff-only merge of changes in the case of "checkout" in an attached
> HEAD (doing "git checkout <branch>" is not enough);
> - reattach of the HEAD with orphaned commits.

Personally, I don't think autoremote updates are worth the additional
UI complication (hence my alternative patch ;), but I'm open to
discussion on this point.  Can you make a case for why and explicit
--remote update is burdensome?

I'm also not entirely clear on the problems avoided or workflows
enhanced via the last two entries.  Could you sketch an example
workflow that makes that more obvious?

> Unfortunately our patches are already a bit colliding. I'll wait for
> other comments from git maintainers and let see. Anyway, I'm happy
> because things are moving: after this debate git submodules will be
> better for sure.

+1.  I floated my patch as a proof-of-concept for my side of this
debate, but I'm pretty happy with the current setup, so it's hard for
me to imagine submodules getting worse as a result of this ;).

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/236372

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 21:47               ` W. Trevor King
@ 2014-01-05 22:01                 ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-05 22:01 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Git, Junio C Hamano, Jens Lehmann, Heiko Voigt

[-- Attachment #1: Type: text/plain, Size: 2629 bytes --]

On Sun, Jan 05, 2014 at 01:47:52PM -0800, W. Trevor King wrote:
> On Sun, Jan 05, 2014 at 10:27:19PM +0100, Francesco Pretto wrote:
> > 2014/1/5 W. Trevor King:
> > Also it covers:
> > - an "autoremote" behavior when the user wants an attached HEAD:
> > with your patch "--remote" is still needed to really update the
> > branch with "git submodule update":
> > - voluntary reattach/detach the HEAD with command line;
> > - ff-only merge of changes in the case of "checkout" in an attached
> > HEAD (doing "git checkout <branch>" is not enough);
> > - reattach of the HEAD with orphaned commits.
> 
> Personally, I don't think autoremote updates are worth the additional
> UI complication (hence my alternative patch ;), but I'm open to
> discussion on this point.  Can you make a case for why and explicit
> --remote update is burdensome?
> 
> I'm also not entirely clear on the problems avoided or workflows
> enhanced via the last two entries.  Could you sketch an example
> workflow that makes that more obvious?

For example, your original patch [1] claimed a reduction from:

  # Maintainer
  $ git submodule add --branch "master-project1" <repository> common
  $ git commit -m "Added submodule"
  $ git config -f .gitmodules submodule.common.ignore all
  $ git push
  $ cd <path>
  $ git checkout "master-project1"

to:

  # Maintainer
  $ git submodule add --branch "master-project1" --attach <repository> <path>
  $ git commit -m "Added submodule"
  $ git push

My patch does not effect this maintainer flow at all, but I'm pretty
sure the initial checkout is already automatic:

  $ git --version
  git version 1.8.3.2
  $ cd b/
  $ git init
  Initialized empty Git repository in /tmp/b/.git/
  $ git submodule add --branch master ../a
  Cloning into 'a'...
  done.
  Checking connectivity... done
  $ cd a/
  $ git branch
  * master

You also claimed a reduction from:

  # Developer
  $ git pull
  $ git submodule init
  $ git submodule update --remote
  $ cd <path>
  $ branch="$(git config -f ..\.gitmodules submodule.common.branch)"; git checkout $branch

to:

  # Developer
  $ git pull
  $ git submodule init
  $ git submodule update

My patch should cover the developer reduction (auto branch checkout on
the initial cloning update) without confusing the situation with
autofloated updates.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/239799

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 21:24               ` W. Trevor King
@ 2014-01-05 22:57                 ` Heiko Voigt
  2014-01-05 23:39                   ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-05 22:57 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

On Sun, Jan 05, 2014 at 01:24:58PM -0800, W. Trevor King wrote:
> On Sun, Jan 05, 2014 at 08:48:50PM +0100, Heiko Voigt wrote:
> > On Sun, Jan 05, 2014 at 08:17:00AM -0800, W. Trevor King wrote:
> > > It's not clear if this refers to the initial-clone update, future
> > > post-clone updates, or both.  Ideally, the behavior should be the
> > > same, but in the initial-clone case we don't have an existing
> > > checked-out branch to work with.
> > 
> > I do not think that its actually important to end up with a detached
> > HEAD. The documentation just states it because in most cases there
> > is no other option. But I do not think anything will break if a
> > branch points to the exact sha1 we would checkout and we checkout
> > the branch instead.
> 
> There's no "if the remote-tracking branch points to the exact sha1"
> logic in my patch.

I know I was more referring to the discussion whether detached HEAD for
submodules is important or not.

> If submodule.<name>.branch is set, it *always*
> creates a new local branch of that name pointing to the exact sha1.
> If submodule.<name>.branch is not set, we still create a detached-HEAD
> checkout of the exact sha1.

Thanks for this clarification. Since the usual usage with --remote is
with a remote-tracking branch, I confused this here. I am not sure
whether blindly creating a local branch from the recorded sha1 is the
right thing to do. In what situations would that be helpful?

At $dayjob we usually use feature branches for our work. So if someone
wants to work in a submodule you simply create a branch at the current
sha1 which you then send out for review.

The reason why one would set a branch option here is to share the
superproject branch with colleagues. He can make sure they can always
fetch and checkout the submodule even though the branch there is still
under cleanup and thus will be rebased often. The commit referenced by
sha1 would not be available to a developer fetching after a rebase.

> Thinking through this more, perhaps the
> logic should be:
> 
> * If submodule.<name>.update (defaulting to checkout) is checkout,
>   create a detached HEAD.
> * Otherwise, create a new branch submodule.<name>.branch (defaulting
>   to master).

Why not trigger the attached state with the submodule.<name>.branch
configuration option? If there is a local branch available use that, if
not the tracking branch (as it is currently). Then a developer can start
working on the branch with:

	cd submodule; git checkout -t origin/<branchname>

assuming that submodule update learns some more support for this.

> The motivation is that if submodule.<name>.update is checkout, the
> user is unlikely to be developing locally in the submodule, as
> subsequent updates would clobber their local commits.  Having a
> detached HEAD is a helpful "don't develop here" reminder ;).  If
> submodule.<name>.update is set, the user is likely to be developing
> locally, and will probably want a local branch already checked out to
> facilitate that.
> 
> > > -			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
> > > +			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$config_branch" || exit
> > 
> > In the simple case (update=checkout, no branch specified) with the
> > new checkout branch stuff in module_clone() this code here ends up
> > calling checkout twice.  First for master and then here later with
> > the sha1.  This feels a little bit double.
> 
> There is no guarantee that the remote master and the exact sha1 point
> at the same commit.  Ideally we'd just clone the exact sha1 in this
> case.
> 
> > I would prefer if we skip the checkout in module_clone() if its not
> > necessary.
> 
> When I tried to drop the '' case here:
> 
> > > @@ -306,7 +307,15 @@ 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" &&
> > > +		case "$branch" in
> > > +		'') git checkout -f -q ;;
> > > +		?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
> > > +		esac
> > > +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
> > >  }
> 
> I got test-suite errors that I didn't get to the bottom of.  However…
> 
> > How about we move the whole "what to checkout"-decision into one place
> > instead of having it in update() and moving it from add() into
> > module_clone() ?
> 
> …this sounds like a good idea to me.  However, it would be a more
> intrusive change, and there may be conflicts with Francesco's proposed
> attach/detach functionality.  I'll wait until we have a clearer idea
> of where that is headed before I attempt a more complete
> consolidation.

I agree, that would be good.

> > > -				update_module= ;;
> > > +				if test -n "$config_branch"; then
> > > +					update_module="!git reset --hard -q"
> > 
> > If we get here the checkout has already been done. Shouldn't this
> > rather specify a noop. I.E. like
> > 
> > 	update_module="!true"
> 
> We are on a local branch at this point, but not neccessarily pointing
> at the gitlinked sha1.  The reset here ensures that the new local
> branch does indeed point at the gitlinked sha1.

But isn't this a fresh clone? Why should the branch point at anything
else?

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-05 20:33           ` Heiko Voigt
  2014-01-05 21:46             ` Francesco Pretto
@ 2014-01-05 23:22             ` Francesco Pretto
  2014-01-06 14:18               ` Heiko Voigt
  1 sibling, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-05 23:22 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: git, Jens Lehmann

2014/1/5 Heiko Voigt <hvoigt@hvoigt.net>:
> Could you please extend the description of your use-case so we can
> understand your goal better?
>

Maybe I found better words to explain you my goal: the current git
submodule use-case threats the submodule as a project independent
dependency. My use case threats the submodule as part of the
superproject repository. It could be easier to say that in this way
submodules would behave very similarly to "svn:externals", something
that is actually missing in git. My goal is obtain this without
altering git behavior for the existing use case.

>  - In which situations does the developer or maintainer switch between
>    your attached/detached mode?

As I told you in the other answer this is voluntary done by the
developer, as he prefers. I came to the conclusion that the
"--attach|--detach" switches for the "update" command are not that
useful and can be removed. It's still possible to obtain the switch
between detached/attached very easily in this way:

# Attach submodule
$ git config submodule.<name>.attached "true"
$ git submodule update

# Detach submodule
$ git config submodule.<name>.attached "false"
$ git submodule update

# Unset property in both ".gitmodules" and ".git/config" means -> do nothing
$ git config --unset submodule.<name>.attached
$ git submodule update

Also my "submodule.<name>.attached" property at the moment behaves
like "submodule.<name>.update": it is copied in ".git/config" by "git
submodule init". This is probably a mistake: the overridden value
should be stored in ".git/config" only at the developer will, so the
maintainer has still a chance to modify it in ".gitmodules" and
propagate the behavior.

I would send an updated patch but at this point I prefer to wait for a
full review.

Thank you,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 22:57                 ` Heiko Voigt
@ 2014-01-05 23:39                   ` W. Trevor King
  2014-01-06  0:33                     ` W. Trevor King
  2014-01-06 15:47                     ` Re: " Heiko Voigt
  0 siblings, 2 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-05 23:39 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 4703 bytes --]

On Sun, Jan 05, 2014 at 11:57:33PM +0100, Heiko Voigt wrote:
> On Sun, Jan 05, 2014 at 01:24:58PM -0800, W. Trevor King wrote:
> > If submodule.<name>.branch is set, it *always* creates a new local
> > branch of that name pointing to the exact sha1.  If
> > submodule.<name>.branch is not set, we still create a
> > detached-HEAD checkout of the exact sha1.
> 
> Thanks for this clarification. Since the usual usage with --remote
> is with a remote-tracking branch, I confused this here. I am not
> sure whether blindly creating a local branch from the recorded sha1
> is the right thing to do. In what situations would that be helpful?

In any situation where your going to develop the submodule locally,
you're going to want a branch to develop in.  Starting local-submodule
developers off on a branch seems useful, even if we can only use
submodule.<name>.branch to guess at their preferred local branch name.
Sometimes (often?) the guess will be right.  However, A detached HEAD
will never be right for local development, so being right sometimes is
still an improvement ;).

> At $dayjob we usually use feature branches for our work. So if
> someone wants to work in a submodule you simply create a branch at
> the current sha1 which you then send out for review.

I'm all for named feature branches for development, and in this case
submodule.<name>.branch is likely to be the wrong choice.  However,
it's still safer to develop in that branch and then rename the branch
to match your feature than it would be to develop your fix with a
detached HEAD.  If your developers have enough discipline to always
checkout their feature branch before starting development, my patch
won't affect them.  However, I know a number of folks who go into
fight-or-flight mode when they have a detached HEAD :p.

> The reason why one would set a branch option here is to share the
> superproject branch with colleagues. He can make sure they can
> always fetch and checkout the submodule even though the branch there
> is still under cleanup and thus will be rebased often. The commit
> referenced by sha1 would not be available to a developer fetching
> after a rebase.

Yeah, floating gitlinks are something else.  I'd be happy to have that
functionality (gitlinks pointing to references) should be built into
gitlinks themselves, not added as an additional layer in the submodule
script.  This "gitlinked sha1 rebased out of existence" scenario is
the first I've heard where I think gitlinked references would be
useful.

> > Thinking through this more, perhaps the logic should be:
> > 
> > * If submodule.<name>.update (defaulting to checkout) is checkout,
> >   create a detached HEAD.
> > * Otherwise, create a new branch submodule.<name>.branch
> >   (defaulting to master).
> 
> Why not trigger the attached state with the submodule.<name>.branch
> configuration option? If there is a local branch available use that,
> if not the tracking branch (as it is currently). Then a developer
> can start working on the branch with:
> 
> 	cd submodule; git checkout -t origin/<branchname>
> 
> assuming that submodule update learns some more support for this.

Isn't that already what 'git update --remote <submodule>' already
does?

> > > > -				update_module= ;;
> > > > +				if test -n "$config_branch"; then
> > > > +					update_module="!git reset --hard -q"
> > > 
> > > If we get here the checkout has already been done. Shouldn't
> > > this rather specify a noop. I.E. like
> > > 
> > > 	update_module="!true"
> > 
> > We are on a local branch at this point, but not neccessarily
> > pointing at the gitlinked sha1.  The reset here ensures that the
> > new local branch does indeed point at the gitlinked sha1.
> 
> But isn't this a fresh clone? Why should the branch point at
> anything else?

We don't pass $sha1 to module_clone().  Before my patch, we don't even
pass $branch to module_clone().  That means that module_clone() will
only checkout the gitlinked sha1 when the upstream HEAD (or $branch
with my patch) happens to point to the gitlinked sha1.  For example,
if Alice adds Charie's repo as a submodule (gitlinking his current
master d2dbd39), then Charlie pushes a new commit d0de817 to his
master, and then Bob clones Alice's superproject.  Post-clone,
Charlie's submodule will have checked out Charlie's new d0de817, and
we need update's additional:

  git reset --hard -q d2dbd39

to rewind to Alice's gitlinked sha1.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 23:39                   ` W. Trevor King
@ 2014-01-06  0:33                     ` W. Trevor King
  2014-01-06  1:12                       ` W. Trevor King
  2014-01-06 15:47                     ` Re: " Heiko Voigt
  1 sibling, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-06  0:33 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 1631 bytes --]

On Sun, Jan 05, 2014 at 03:39:43PM -0800, W. Trevor King wrote:
> On Sun, Jan 05, 2014 at 11:57:33PM +0100, Heiko Voigt wrote:
> > The reason why one would set a branch option here is to share the
> > superproject branch with colleagues. He can make sure they can
> > always fetch and checkout the submodule even though the branch there
> > is still under cleanup and thus will be rebased often. The commit
> > referenced by sha1 would not be available to a developer fetching
> > after a rebase.
> 
> Yeah, floating gitlinks are something else.  I'd be happy to have
> that functionality (gitlinks pointing to references) be built into
> gitlinks themselves, not added as an additional layer in the
> submodule script.  This "gitlinked sha1 rebased out of existence"
> scenario is the first I've heard where I think gitlinked references
> would be useful.

On the other hand, if the subproject has such a rebase, a superproject
dev can hop into an existing checkout, update around the rebase, add a
superproject commit with the fixed sha1, and push that for other
superproject devs.  The only people who would need *automatic* rebase
recovery would be superproject devs update-cloning the subproject.
That's a small enough cross-section that I don't think it deserves the
ambiguity of gitlink-to-reference.  In that case, all you really need
is a way to force a recovery gitlink (i.e. add a 'commit' object to
the tree by hand).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06  0:33                     ` W. Trevor King
@ 2014-01-06  1:12                       ` W. Trevor King
  2014-01-06 16:02                         ` Heiko Voigt
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-06  1:12 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 2648 bytes --]

On Sun, Jan 05, 2014 at 04:33:14PM -0800, W. Trevor King wrote:
> The only people who would need *automatic* rebase recovery would be
> superproject devs update-cloning the subproject.  That's a small
> enough cross-section that I don't think it deserves the ambiguity of
> gitlink-to-reference.  In that case, all you really need is a way to
> force a recovery gitlink (i.e. add a 'commit' object to the tree by
> hand).

Actually, you recovering by hand is a lot easier.  Setup a
rebased-away gitlink target:

  mkdir subproject &&
  (
    cd subproject &&
    git init
    echo 'Subproject' > README &&
    git add README &&
    git commit -m 'Subproject v1' &&
    echo 'Changes' >> README &&
    git commit -am 'Subproject v2'
  ) &&
  mkdir superproject &&
  (
    cd superproject &&
    git init
    git submodule add ../subproject &&
    git commit -m 'Superproject v1'
  ) &&
  (
    cd subproject &&
    git reset --hard HEAD^ &&
    git reflog expire --expire=now --all &&
    git gc --aggressive --prune=now
  )

Then a recursive clone of the superproject dies:

  $ git clone --recursive superproject super2
  Cloning into 'super2'...
  done.
  Submodule 'subproject' (/tmp/x/subproject) registered for path 'subproject'
  Cloning into 'subproject'...
  done.
  fatal: reference is not a tree: f589144d16282d1a80d17a9032c6f1d332e38dd0
  Unable to checkout 'f589144d16282d1a80d17a9032c6f1d332e38dd0' in submodule path 'subproject'

But you still have the submodule checkout (up until the $sha1 setup):

  $ cd super2
  $ git diff
  diff --git a/subproject b/subproject
  index f589144..82d4553 160000
  --- a/subproject
  +++ b/subproject
  @@ -1 +1 @@
  -Subproject commit f589144d16282d1a80d17a9032c6f1d332e38dd0
  +Subproject commit 82d4553fe437ae014f22bbc87a082c6d19e5d9f9-dirty

And you can automatically update to match the upstream remote:

  $ git submodule update --remote --force
  Submodule path 'subproject': checked out '82d4553fe437ae014f22bbc87a082c6d19e5d9f9'
  $ git diff
  diff --git a/subproject b/subproject
  index f589144..82d4553 160000
  --- a/subproject
  +++ b/subproject
  @@ -1 +1 @@
  -Subproject commit f589144d16282d1a80d17a9032c6f1d332e38dd0
  +Subproject commit 82d4553fe437ae014f22bbc87a082c6d19e5d9f9

When explicitly updating to the superproject or subproject's
(--remote) new tip is so easy, I don't see a need for floating the
gitlinks themselves.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-05 21:46             ` Francesco Pretto
@ 2014-01-06 14:06               ` Heiko Voigt
  2014-01-06 17:47                 ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-06 14:06 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: git, Jens Lehmann, Junio C Hamano, W. Trevor King

On Sun, Jan 05, 2014 at 10:46:11PM +0100, Francesco Pretto wrote:
> 2014/1/5 Heiko Voigt <hvoigt@hvoigt.net>:
> > The following questions directly pop into my mind:
> >
> >  - What means the maintainer does not track the submodules sha1? Does
> >    that mean the superproject always refers to submodule commits using
> >    branches?
> 
> It means he doesn't need to control other developers commit to be
> checked out so he sets "submodule.<name>.ignore" to "all". In this way
> he and the developers can work actively in their submodule copy.

So practically speaking: You mean that the value of
submodule.<name>.ignore is set to "all" in the master branch of the
superproject? From your other email referring to svn:externals I figure
that.

> >  - What happens if you want to go back to an earlier revision? Lets say
> >    a tagged release? How is ensured that you get the correct revision in
> >    the submodules?
> 
> "submodule.<name>.branch" is one setting that is not copied in
> ".git/config" by "git submodule init". "git submodule update" will use
> the setting in ".gitmodules" if not overridden voluntarily by the
> developer in ".git/config". The maintainer can change that setting in
> ".gitmodules" and commit the change. Modifies will be propagated by
> the next "git pull && git submodule update" of the developer in the
> superproject.

I do not understand how does that ensure you get the correct submodule
revision when checking out a tagged release? To get a precise revision
the superproject needs to track a sha1 of a submodule commit. I do not
see how that has anything to do with submodule.<name>.branch?

> >  - In which situations does the developer or maintainer switch between
> >    your attached/detached mode?
> 
> The developer/maintainer does so optionally and voluntarily and it
> effects only its private working tree.

This does not answer my question. I would like to find out the reason
why one would do the switch.

> >  - What is the "repository branch" which is given to the developer by
> >    the maintainer used for? Who creates this branch and who merges into
> >    it?
> 
> The branch of course must exist prior submodule adding. In this
> use-case it does not really matter who creates it and who merges into
> it. Everyone with the right to merge into it has to work in the
> submodule seamlessly, as it was working on separate clone of the same
> repository used as the submodule.
o
Here is the same. I am searching for a description like:

If the developer works on a feature that needs a submodule change he:
  - creates a submodule branch
  - configures that submodule branch in the superproject:
  	git config -f .gitmodules submodule.common.branch dev/some-feature
	git commit -am "TEMP: track submodule common on branch"
 - and pushes out his superproject branch

The submodule branch is then posted for review and continued to work on.

Once everyone involved is happy with the submodule change the branch in
there gets merged to master.

Now the branch in the superproject is modified to drop the change in
.gitmodules and the sha1 reference in the superproject is updated to the
current master of the superproject.

The superproject branch is posted for review.

...

Could you describe something like this for your workflow? A complete
change lifecycle when a developer works, as you call it, "actively" in a
submodule?

> >  - What are these subsequent "merge" or "rebase" update operations? Do
> >    you mean everyone has submodule.name.update configured to merge or
> >    rebase?
> >
> 
> subsequent "merge" or "rebase" update operations are just the ones
> after the initial clone/checkout, nothing particular.

To clarify you are talking about issuing "git merge" or "git rebase"
commands in the superproject?

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-05 23:22             ` Francesco Pretto
@ 2014-01-06 14:18               ` Heiko Voigt
  2014-01-06 15:58                 ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-06 14:18 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: git, Jens Lehmann, W. Trevor King, Junio C Hamano

On Mon, Jan 06, 2014 at 12:22:23AM +0100, Francesco Pretto wrote:
> 2014/1/5 Heiko Voigt <hvoigt@hvoigt.net>:
> > Could you please extend the description of your use-case so we can
> > understand your goal better?
> >
> 
> Maybe I found better words to explain you my goal: the current git
> submodule use-case threats the submodule as a project independent
> dependency. My use case threats the submodule as part of the
> superproject repository. It could be easier to say that in this way
> submodules would behave very similarly to "svn:externals", something
> that is actually missing in git. My goal is obtain this without
> altering git behavior for the existing use case.

I am not so sure. svn:externals was IMO a hack in SVN to bind projects
together. It does not record the revision and so has nothing to do
with version control. If you simply want to always checkout the
development tip of some project you could do something like this:

	git submodule foreach 'git fetch && git checkout origin/master'

The demand for this 'missing feature' which we call the 'floating
submodules' model has been around for some time but until now we could
convince people that its not a feature but you are actually loosing
history information.

The workflow could always be changed to allow recording revisions. Which
is why you use git in the first place right? If you discard revisions
for submodules tracking down regression bugs can become a big problem or
completely impossible. Try using git bisect on such a history.

> >  - In which situations does the developer or maintainer switch between
> >    your attached/detached mode?
> 
> As I told you in the other answer this is voluntary done by the
> developer, as he prefers.

Could you tell me a typical reason?


> I came to the conclusion that the
> "--attach|--detach" switches for the "update" command are not that
> useful and can be removed. It's still possible to obtain the switch
> between detached/attached very easily in this way:
> 
> # Attach submodule
> $ git config submodule.<name>.attached "true"
> $ git submodule update
> 
> # Detach submodule
> $ git config submodule.<name>.attached "false"
> $ git submodule update
> 
> # Unset property in both ".gitmodules" and ".git/config" means -> do nothing
> $ git config --unset submodule.<name>.attached
> $ git submodule update
> 
> Also my "submodule.<name>.attached" property at the moment behaves
> like "submodule.<name>.update": it is copied in ".git/config" by "git
> submodule init". This is probably a mistake: the overridden value
> should be stored in ".git/config" only at the developer will, so the
> maintainer has still a chance to modify it in ".gitmodules" and
> propagate the behavior.
> 
> I would send an updated patch but at this point I prefer to wait for a
> full review.

Lets first discuss and figure out what is the real missing feature here
and what should be implemented before working further on the code.

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 21:27             ` Francesco Pretto
  2014-01-05 21:47               ` W. Trevor King
@ 2014-01-06 14:47               ` Heiko Voigt
  2014-01-06 16:56                 ` Junio C Hamano
  1 sibling, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-06 14:47 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: W. Trevor King, Git, Junio C Hamano, Jens Lehmann

On Sun, Jan 05, 2014 at 10:27:19PM +0100, Francesco Pretto wrote:
> 2014/1/5 W. Trevor King <wking@tremily.us>:
> > On Sun, Jan 05, 2014 at 04:53:12AM +0100, Francesco Pretto wrote:
> >> Also it could break some users that rely on the current behavior.
> >
> > The current code always has a detached HEAD after an initial-clone
> > update, regardless of submodule.<name>.update, which doesn't match
> > those docs either.
> 
> I perfectly agree with you that the documentation is a bit
> contradictory with regard to "update" command and detached HEAD.
> That's why it's so hard to add a feature and keep the same spirit of
> those that coded submodules at first. Also, I think that submodules
> didn't get much feedback with regards to these pitfalls because many
> people try to setup them, they see that "update" detaches the HEAD and
> they think "hmmm, maybe submodules are not what I was looking for".

I am not so sure about that. Why should detached HEAD make you think
like that? For us at $dayjob we have a pre-commit hook that denies you
to commit on a detached HEAD and asks you to create a branch first.

You then work on that branch and send it out for review. If the reviewer
is happy he merges it into a stable branch (master most times) of the
submodule. Only revisions that are on a stable branch in a submodule are
allowed to be linked in a superprojects branch that should be merged.

Before the submodule's branch gets merged we usually track the
development branches sha1 of the submodule in the superproject. For
cleanup in the submodule I currently use fixup! commits most times so
the referenced sha1 is not lost. In the very end when everyone is happy
with the submodule change I rebase, change the referenced sha1 in the
superproject and send the final branch out for review another time.

> > Adding a check to only checkout
> > submodule.<name>.branch if submodule.<name>.update was 'rebase',
> > 'merge', or 'none' would be easy, but I don't think that makes much
> > sense.  I can't see any reason for folks who specify
> > submodule.<name>.branch to prefer a detached HEAD over a local branch
> > matching the remote branch's name.
> 
> I think the reason is that it still matches the original use case of
> submodules devs:
> - the maintainer decides the specific commit developers should have;

Nope. We usually do not have a maintainer. We use a review based
workflow. Everyone is allowed to review. If you develop you need to send
you changes to a reviewer first who then merges when he is ok with it.

> - developers checkout that commit and don't pull (you can't do "git
> pull" in a detached HEAD);

Exactly. We consider pull evil ;-) Seriously: To update we only do fast
forward merges of local stable branches. Only reviewers or maintainers
are allowed to merge and push into stable branches. Direct commits to
stable branches are forbidden.

To review we have a shortcut to update the stable branch in git gui
for which the code can be found on my github[1].

> - they optionally get the upstream commit from the specified
> "submodule.<name>.branch" with "--remote". They are still in a
> detached HEAD and can't do "git pull".

Yes, why would you do a git pull in a submodule? Don't you want to do
something like

	git checkout -t -b dev/my-topic origin/master

to start your development?

> Maybe who coded submodules at first was thinking that the best way to
> contribute to a project is to checkout that repository, and not work
> in the submodule. As said, this works well when the submodule
> repository is a full project, and not a bunch of shared code.

Why not work in the submodule? See explanation above.

Cheers Heiko


[1] https://github.com/hvoigt/git/commits/hv/gui-improvements

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 23:39                   ` W. Trevor King
  2014-01-06  0:33                     ` W. Trevor King
@ 2014-01-06 15:47                     ` Heiko Voigt
  2014-01-06 17:22                       ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-06 15:47 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

On Sun, Jan 05, 2014 at 03:39:43PM -0800, W. Trevor King wrote:
> On Sun, Jan 05, 2014 at 11:57:33PM +0100, Heiko Voigt wrote:
> > On Sun, Jan 05, 2014 at 01:24:58PM -0800, W. Trevor King wrote:
> > > If submodule.<name>.branch is set, it *always* creates a new local
> > > branch of that name pointing to the exact sha1.  If
> > > submodule.<name>.branch is not set, we still create a
> > > detached-HEAD checkout of the exact sha1.
> > 
> > Thanks for this clarification. Since the usual usage with --remote
> > is with a remote-tracking branch, I confused this here. I am not
> > sure whether blindly creating a local branch from the recorded sha1
> > is the right thing to do. In what situations would that be helpful?
> 
> In any situation where your going to develop the submodule locally,
> you're going to want a branch to develop in.  Starting local-submodule
> developers off on a branch seems useful, even if we can only use
> submodule.<name>.branch to guess at their preferred local branch name.
> Sometimes (often?) the guess will be right.  However, A detached HEAD
> will never be right for local development, so being right sometimes is
> still an improvement ;).

Starting developers at a local submodule branch makes sense. But lets
think further. What happens after the initial update? Most times the
submodule will already be initialized and cloned. Then developers will
still get a detached HEAD even with your local branch feature.

If there are no changes on it should we advance the local branch
somehow on update? If it does not exist anymore should we recreate it?

> > At $dayjob we usually use feature branches for our work. So if
> > someone wants to work in a submodule you simply create a branch at
> > the current sha1 which you then send out for review.
> 
> I'm all for named feature branches for development, and in this case
> submodule.<name>.branch is likely to be the wrong choice.  However,
> it's still safer to develop in that branch and then rename the branch
> to match your feature than it would be to develop your fix with a
> detached HEAD.  If your developers have enough discipline to always
> checkout their feature branch before starting development, my patch
> won't affect them.  However, I know a number of folks who go into
> fight-or-flight mode when they have a detached HEAD :p.

I agree having an initial branch makes it less likely to loose committed
changes. Thats good. Also starting on some local branch name and then
renaming the branch sounds quite practical. Then we could recreate the
default local branch on update (like described above).

> > The reason why one would set a branch option here is to share the
> > superproject branch with colleagues. He can make sure they can
> > always fetch and checkout the submodule even though the branch there
> > is still under cleanup and thus will be rebased often. The commit
> > referenced by sha1 would not be available to a developer fetching
> > after a rebase.
> 
> Yeah, floating gitlinks are something else.  I'd be happy to have that
> functionality (gitlinks pointing to references) should be built into
> gitlinks themselves, not added as an additional layer in the submodule
> script.  This "gitlinked sha1 rebased out of existence" scenario is
> the first I've heard where I think gitlinked references would be
> useful.

Yeah I have been thinking about this for quite a while now, but have not
yet found the time to really think it through and come up with a good
solution that does not put you in danger of unprecise revisions. The
only solution I can think of is a similar approach as
submodule.<name>.branch gives us now but possibly enabled by some
option (i.e.: submodule.<name>.remote = true).
This way you always get the current tip of development but still see the
differences (which you can choose to commit) in git status.

> > > Thinking through this more, perhaps the logic should be:
> > > 
> > > * If submodule.<name>.update (defaulting to checkout) is checkout,
> > >   create a detached HEAD.
> > > * Otherwise, create a new branch submodule.<name>.branch
> > >   (defaulting to master).
> > 
> > Why not trigger the attached state with the submodule.<name>.branch
> > configuration option? If there is a local branch available use that,
> > if not the tracking branch (as it is currently). Then a developer
> > can start working on the branch with:
> > 
> > 	cd submodule; git checkout -t origin/<branchname>
> > 
> > assuming that submodule update learns some more support for this.
> 
> Isn't that already what 'git update --remote <submodule>' already
> does?

Does it? As far as I understood (not using the branch option yet) it
only does

	git checkout origin/<branchname>

so there is no local branch created that tracks the remote branch (-t).
What I was thinking is that when submodule.<name>.branch is set a

	git submodule update

will:

1. if no local branch with that name exists:

   checkout the remote/<branch>

2. If a local branch with that name exists:

   checkout the local branch and possibly advance it according to its
   setting.

Thinking further: Maybe submodule.<name>.update = pull could denote that
a user wants to have a branch ready for work in a submodule. submodule
update will then

1. if no local branch with that name exists:

   - automatically create the branch based on the referenced sha1
   - set up that its tracking remote/<branch>
   - issue a git pull in the submodule

2. if a local branch with that name exists:

   - issue a git pull in the submodule

The superproject will still show if there are any changes in the
submodule (i.e. the sha1 does not match anymore). Even though the user
can disable it with submodule.<name>.ignore=all I would advise against
it.

> > > > > -				update_module= ;;
> > > > > +				if test -n "$config_branch"; then
> > > > > +					update_module="!git reset --hard -q"
> > > > 
> > > > If we get here the checkout has already been done. Shouldn't
> > > > this rather specify a noop. I.E. like
> > > > 
> > > > 	update_module="!true"
> > > 
> > > We are on a local branch at this point, but not neccessarily
> > > pointing at the gitlinked sha1.  The reset here ensures that the
> > > new local branch does indeed point at the gitlinked sha1.
> > 
> > But isn't this a fresh clone? Why should the branch point at
> > anything else?
> 
> We don't pass $sha1 to module_clone().  Before my patch, we don't even
> pass $branch to module_clone().  That means that module_clone() will
> only checkout the gitlinked sha1 when the upstream HEAD (or $branch
> with my patch) happens to point to the gitlinked sha1.  For example,
> if Alice adds Charie's repo as a submodule (gitlinking his current
> master d2dbd39), then Charlie pushes a new commit d0de817 to his
> master, and then Bob clones Alice's superproject.  Post-clone,
> Charlie's submodule will have checked out Charlie's new d0de817, and
> we need update's additional:
> 
>   git reset --hard -q d2dbd39
> 
> to rewind to Alice's gitlinked sha1.

Ah yeah, sorry I was confusing this with the checkout of remote/<branch>
here again. Since I have done that twice already maybe we should be
careful about not confusing users with this as well...

After wrapping my head around the fact that you want to simply create a
local branch on the referenced sha1 (and hopefully remembering it) I
still would like to think a little more about it and let it settle a
bit.

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-06 14:18               ` Heiko Voigt
@ 2014-01-06 15:58                 ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-06 15:58 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Francesco Pretto, git, Jens Lehmann, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 673 bytes --]

On Mon, Jan 06, 2014 at 03:18:05PM +0100, Heiko Voigt wrote:
> If you simply want to always checkout the development tip of some
> project you could do something like this:
> 
> 	git submodule foreach 'git fetch && git checkout origin/master'

Or (respecting submodule.<name>.branch):

  $ git submodule update --remote

You can even:

  $ git submodule update --remote --recursive

whenever you get an itch to upgrade everything everything in one
sweeping, hard-to-debug move ;).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06  1:12                       ` W. Trevor King
@ 2014-01-06 16:02                         ` Heiko Voigt
  2014-01-06 23:10                           ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-06 16:02 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

On Sun, Jan 05, 2014 at 05:12:56PM -0800, W. Trevor King wrote:
> On Sun, Jan 05, 2014 at 04:33:14PM -0800, W. Trevor King wrote:
> > The only people who would need *automatic* rebase recovery would be
> > superproject devs update-cloning the subproject.  That's a small
> > enough cross-section that I don't think it deserves the ambiguity of
> > gitlink-to-reference.  In that case, all you really need is a way to
> > force a recovery gitlink (i.e. add a 'commit' object to the tree by
> > hand).
> 
> Actually, you recovering by hand is a lot easier.  Setup a
> rebased-away gitlink target:
> 
>   mkdir subproject &&
>   (
>     cd subproject &&
>     git init
>     echo 'Subproject' > README &&
>     git add README &&
>     git commit -m 'Subproject v1' &&
>     echo 'Changes' >> README &&
>     git commit -am 'Subproject v2'
>   ) &&
>   mkdir superproject &&
>   (
>     cd superproject &&
>     git init
>     git submodule add ../subproject &&
>     git commit -m 'Superproject v1'
>   ) &&
>   (
>     cd subproject &&
>     git reset --hard HEAD^ &&
>     git reflog expire --expire=now --all &&
>     git gc --aggressive --prune=now
>   )
> 
> Then a recursive clone of the superproject dies:
> 
>   $ git clone --recursive superproject super2
>   Cloning into 'super2'...
>   done.
>   Submodule 'subproject' (/tmp/x/subproject) registered for path 'subproject'
>   Cloning into 'subproject'...
>   done.
>   fatal: reference is not a tree: f589144d16282d1a80d17a9032c6f1d332e38dd0
>   Unable to checkout 'f589144d16282d1a80d17a9032c6f1d332e38dd0' in submodule path 'subproject'
> 
> But you still have the submodule checkout (up until the $sha1 setup):
> 
>   $ cd super2
>   $ git diff
>   diff --git a/subproject b/subproject
>   index f589144..82d4553 160000
>   --- a/subproject
>   +++ b/subproject
>   @@ -1 +1 @@
>   -Subproject commit f589144d16282d1a80d17a9032c6f1d332e38dd0
>   +Subproject commit 82d4553fe437ae014f22bbc87a082c6d19e5d9f9-dirty
> 
> And you can automatically update to match the upstream remote:
> 
>   $ git submodule update --remote --force
>   Submodule path 'subproject': checked out '82d4553fe437ae014f22bbc87a082c6d19e5d9f9'
>   $ git diff
>   diff --git a/subproject b/subproject
>   index f589144..82d4553 160000
>   --- a/subproject
>   +++ b/subproject
>   @@ -1 +1 @@
>   -Subproject commit f589144d16282d1a80d17a9032c6f1d332e38dd0
>   +Subproject commit 82d4553fe437ae014f22bbc87a082c6d19e5d9f9
> 
> When explicitly updating to the superproject or subproject's
> (--remote) new tip is so easy, I don't see a need for floating the
> gitlinks themselves.

I agree. If we were to support this more easily we could add a
configuration option so you can omit the --remote (i.e.:
submodule.<name>.remote=true, as I also suggested in the other email).

That way the developer checking out a branch in flight does not even
need to know whether (and which) submodules sha1s are still in flight
and temporarily set this configuration in the branches .gitmodules file.

Maybe that could actually be the attach operation Francesco is
suggesting:

	git submodule attach [--pull] <submodule path> <branchname>

will attach the specified submodule to a branch. That means it changes
the .gitmodule file accordingly and stages it. With the --pull switch
one can specify whether a local branch tracking the remote branch should
be automatically created. Names and the command format are just a
suggestion here.

That way we can support the

	fork superproject needing submodule changes and send submodule
	changes upstream first.

workflow. What do you think?

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command
  2014-01-05 20:44         ` W. Trevor King
@ 2014-01-06 16:20           ` Junio C Hamano
  2014-01-06 17:42             ` Junio C Hamano
  0 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-06 16:20 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Francesco Pretto, git, Heiko Voigt

"W. Trevor King" <wking@tremily.us> writes:

> On Sun, Jan 05, 2014 at 03:50:48AM +0100, Francesco Pretto wrote:
>> +			case "$update_module" in
>> +			'')
>> +				;; # Unset update mode
>> +			checkout | rebase | merge | none)
>> +				;; # Known update modes
>> +			!*)
>> +				;; # Custom update command
>> +			*)
>> +				update_module=
>> +				echo >&2 "warning: invalid update mode for submodule '$name'"
>> +				;;
>> +			esac
>
> I'd prefer `die "…"` to `echo >&2 "…"`.  It's hard to know if mapping
> the user's preferred (unknown) update mechanism to 'checkout' is
> serious or not.
>
> This commit also makes me think that --rebase, --merge, and --checkout
> should be replaced with a single --update={rebase|merge|checkout|!…}
> option, but that's probably food for another commit (and a long
> finger-breaking deprecation period).

All of the above points sound sensible to me.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 14:47               ` Heiko Voigt
@ 2014-01-06 16:56                 ` Junio C Hamano
  2014-01-06 17:37                   ` W. Trevor King
  2014-01-07  0:55                   ` Francesco Pretto
  0 siblings, 2 replies; 144+ messages in thread
From: Junio C Hamano @ 2014-01-06 16:56 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Francesco Pretto, W. Trevor King, Git, Jens Lehmann

Heiko Voigt <hvoigt@hvoigt.net> writes:

> On Sun, Jan 05, 2014 at 10:27:19PM +0100, Francesco Pretto wrote:
>> 2014/1/5 W. Trevor King <wking@tremily.us>:
>> > On Sun, Jan 05, 2014 at 04:53:12AM +0100, Francesco Pretto wrote:
>> >> Also it could break some users that rely on the current behavior.
>> >
>> > The current code always has a detached HEAD after an initial-clone
>> > update, regardless of submodule.<name>.update, which doesn't match
>> > those docs either.
>> 
>> I perfectly agree with you that the documentation is a bit
>> contradictory with regard to "update" command and detached HEAD.
>> That's why it's so hard to add a feature and keep the same spirit of
>> those that coded submodules at first. Also, I think that submodules
>> didn't get much feedback with regards to these pitfalls because many
>> people try to setup them, they see that "update" detaches the HEAD and
>> they think "hmmm, maybe submodules are not what I was looking for".
>
> I am not so sure about that. Why should detached HEAD make you think
> like that? For us at $dayjob we have a pre-commit hook that denies you
> to commit on a detached HEAD and asks you to create a branch first.

Perception is irrational ;-)

We long-timers think detached is a perfect starting point for both
users of submodule who merely want to use the specified commit and
developers who want to work on the submodule to match the need of
the superproject.  The former do not have to do anything, and the
latter will have to chdir to the submodule working tree and create a
branch (or update the branch with rebase or pull on top of the
specified commit) as the first thing before doing anything.

Not everybody is a long-timer, but the saving grace is that nobody
stays a newcomer.

BUT.

>> - developers checkout that commit and don't pull (you can't do "git
>> pull" in a detached HEAD);
>
> Exactly. We consider pull evil ;-) Seriously: To update we only do fast
> forward merges of local stable branches. 
> ...
> Yes, why would you do a git pull in a submodule? Don't you want to do
> something like
>
> 	git checkout -t -b dev/my-topic origin/master
>
> to start your development?

As long as origin/master contains the commit specified by the
superproject, that would work, but it may be a good thing to use a
mode of submodule.*.update that does not have to drop the user into
a detached state in the first place.  I somehow thought that was
what rebase (or merge) was about, that is, starting from the state
where a branch is checked out in the submodule working tree, an
update in the superproject would cause that branch checked out in
the submodule brought up to date with respect to the commit
specified in the superproject tree.  If that is not how it is
supposed to work, please correct me---and we may have to add another
mode that does so (or even make rebase/merge do so as a bugfix).

And wouldn't it make it unnecessary to have a new "re-attach" option
if such a mode that never have to detach is used?

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 15:47                     ` Re: " Heiko Voigt
@ 2014-01-06 17:22                       ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-06 17:22 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Git, Francesco Pretto, Junio C Hamano, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 7372 bytes --]

On Mon, Jan 06, 2014 at 04:47:39PM +0100, Heiko Voigt wrote:
> On Sun, Jan 05, 2014 at 03:39:43PM -0800, W. Trevor King wrote:
> > On Sun, Jan 05, 2014 at 11:57:33PM +0100, Heiko Voigt wrote:
> > > On Sun, Jan 05, 2014 at 01:24:58PM -0800, W. Trevor King wrote:
> > > > Thinking through this more, perhaps the logic should be:
> > > > 
> > > > * If submodule.<name>.update (defaulting to checkout) is checkout,
> > > >   create a detached HEAD.
> > > > * Otherwise, create a new branch submodule.<name>.branch
> > > >   (defaulting to master).
> > > 
> > > Why not trigger the attached state with the
> > > submodule.<name>.branch configuration option? If there is a
> > > local branch available use that, if not the tracking branch (as
> > > it is currently). Then a developer can start working on the
> > > branch with:
> > > 
> > > 	cd submodule; git checkout -t origin/<branchname>
> > > 
> > > assuming that submodule update learns some more support for this.
> > 
> > Isn't that already what 'git update --remote <submodule>' already
> > does?
> 
> Does it? As far as I understood (not using the branch option yet) it
> only does
> 
> 	git checkout origin/<branchname>
> 
> so there is no local branch created that tracks the remote branch (-t).

That's right.  Anyone who wants to do local development in a submodule
should probably not be using checkout updates, hence my proposal above
to base local-branch creation on submodule.<name>.update.

> What I was thinking is that when submodule.<name>.branch is set a
> 
> 	git submodule update
> 
> will:
> 
> 1. if no local branch with that name exists:
> 
>    checkout the remote/<branch>
> 
> 2. If a local branch with that name exists:
> 
>    checkout the local branch and possibly advance it according to
>    its setting.

This sounds too complicated to me ;).

> Thinking further: Maybe submodule.<name>.update = pull could denote
> that a user wants to have a branch ready for work in a submodule.

This sounds like my quoted realization above.  We both even preface
the idea with "thinking" ;).  However, I think merge, rebase,
!command, and all other non-checkout update schemes are already
signals that the developer is interested in local developent (and
therefore wants a branch), without the need to add an aditional 'pull'
(and then how to distinguish between rebase/merge?).

> submodule update will then
> 
> 1. if no local branch with that name exists:
> 
>    - automatically create the branch based on the referenced sha1
>    - set up that its tracking remote/<branch>

With my patch this happens with the initial clone-update (as of v2,
only when submodule.<name>.branch is set.  In a hypothetical v3, only
when submodule.<name>.update is not checkout).  I'm not sure we want
to do this if the user switches to non-checkout updates after the
initial cloning update though.  They may actually have work in that
detached HEAD that we'd be clobbering.

>    - issue a git pull in the submodule

I think that updating using the gitlinked sha1 (a local update) and
updating using the upstream origin/$branch (a --remote update) should
always be two distinct events.  Combining them in a single operation
just complicates the situation.

> 2. if a local branch with that name exists:
> 
>    - issue a git pull in the submodule

That's what we already have with submodule.<name>.update as 'merge'.
The merged object is either the gitlinked sha1 (a local update) or a
re-fetched upstream branch tip (a --remote update).

> > > > We are on a local branch at this point, but not neccessarily
> > > > pointing at the gitlinked sha1.  The reset here ensures that
> > > > the new local branch does indeed point at the gitlinked sha1.
> > > 
> > > But isn't this a fresh clone? Why should the branch point at
> > > anything else?
> > 
> > We don't pass $sha1 to module_clone().  Before my patch, we don't
> > even pass $branch to module_clone().  That means that
> > module_clone() will only checkout the gitlinked sha1 when the
> > upstream HEAD (or $branch with my patch) happens to point to the
> > gitlinked sha1.  For example, if Alice adds Charie's repo as a
> > submodule (gitlinking his current master d2dbd39), then Charlie
> > pushes a new commit d0de817 to his master, and then Bob clones
> > Alice's superproject.  Post-clone, Charlie's submodule will have
> > checked out Charlie's new d0de817, and we need update's
> > additional:
> > 
> >   git reset --hard -q d2dbd39
> > 
> > to rewind to Alice's gitlinked sha1.
> 
> Ah yeah, sorry I was confusing this with the checkout of
> remote/<branch> here again. Since I have done that twice already
> maybe we should be careful about not confusing users with this as
> well...
>
> After wrapping my head around the fact that you want to simply create a
> local branch on the referenced sha1 (and hopefully remembering it) I
> still would like to think a little more about it and let it settle a
> bit.

The way I keep this straight is:

1. Submodules are links to Git commits (that's how they're stored in
   the index).
2. There are two places to look if you want to update the linked
   commit:
   a. The superproject's tree (a local updates).
   b. The remote subproject's current submodule.<name>.branch tip (a
      --remote update).
3. There are a number of ways to integrate external updates with your
   local submodule development.
   a. checkout: blow away local development
   b. merge: merge the update into the local branch
   c. rebase: rebase the local branch onto the update
   d. !command: do something fancier

We currently have easy config and command-line switches to select
between 2.a and 2.b, which for me makes extending 1 to support
floating branches unnecessary.  Note that we're always updating to a
referenced sha1, and there are only two places we can look to find
that sha1.

We also have easy config and command-line switches to select between
3.a, 3.b, 3.c, and 3.d.

One thing that's a bit fuzzy is the definition of "local development".
We're currently treating it as "any commits leading up to HEAD that
are not in the update source", which works well until upstream starts
rebasing (or rolling back to an earlier release, etc.).  It's hard for
Git to handle that sort of thing automatically, for all the usual
"recovering from upstream rebase" reasons [1].  I'm fine if we leave
it up to users to resolve this sort of situation by hand.  Folks with
local work should know what was local, and folks without local work
can use a checkout update.

We're also not doing a great job of setting people up for local
development, but that's tricky if they may already have local work.
My "start them on a branch" patch is not saving anyone a lot of work,
but it's a step in that direction.  Doing anything after the initial
cloning update is going to be much harder, because there's not much
that would be unabmiguously helpful.  After all, the current submodule
implementation supports my workflows pretty well.

Cheers,
Trevor

[1]: See "RECOVERING FROM UPSTREAM REBASE" in git-rebase(1).

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 16:56                 ` Junio C Hamano
@ 2014-01-06 17:37                   ` W. Trevor King
  2014-01-06 21:32                     ` Junio C Hamano
  2014-01-07  0:55                   ` Francesco Pretto
  1 sibling, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-06 17:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Heiko Voigt, Francesco Pretto, Git, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 1945 bytes --]

On Mon, Jan 06, 2014 at 08:56:22AM -0800, Junio C Hamano wrote:
> Heiko Voigt <hvoigt@hvoigt.net> writes:
> > Yes, why would you do a git pull in a submodule? Don't you want to do
> > something like
> >
> > 	git checkout -t -b dev/my-topic origin/master
> >
> > to start your development?
> 
> As long as origin/master contains the commit specified by the
> superproject, that would work, but it may be a good thing to use a
> mode of submodule.*.update that does not have to drop the user into
> a detached state in the first place.  I somehow thought that was
> what rebase (or merge) was about, that is, starting from the state
> where a branch is checked out in the submodule working tree, an
> update in the superproject would cause that branch checked out in
> the submodule brought up to date with respect to the commit
> specified in the superproject tree.

That is my understanding as well.  In fact, I don't think the
detached-HEAD-vs-branch distinction is important here, you can still
rebase your detached HEAD onto the superproject's referenced commit
(or origin/$branch with --remote).  This will also work for merge, and
should work for well-crafted !commands.

> And wouldn't it make it unnecessary to have a new "re-attach" option
> if such a mode that never have to detach is used?

I think so, but we currently don't have a "never detached" route for
folks that are cloning submodules via update (instead of via
'submodule add').  Currently, new clone-updates will always leave you
with a detached HEAD (unless you have branch-creation in your update
!command).  My patch aims to close this detached-HEAD gap, for folks
we expect will be doing local development, by creating an initial
branch at clone-update time.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command
  2014-01-06 16:20           ` Junio C Hamano
@ 2014-01-06 17:42             ` Junio C Hamano
  2014-01-06 17:52               ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-06 17:42 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Francesco Pretto, git, Heiko Voigt

Junio C Hamano <gitster@pobox.com> writes:

> "W. Trevor King" <wking@tremily.us> writes:
>
>> On Sun, Jan 05, 2014 at 03:50:48AM +0100, Francesco Pretto wrote:
>>> +			case "$update_module" in
>>> +			'')
>>> +				;; # Unset update mode
>>> +			checkout | rebase | merge | none)
>>> +				;; # Known update modes
>>> +			!*)
>>> +				;; # Custom update command
>>> +			*)
>>> +				update_module=
>>> +				echo >&2 "warning: invalid update mode for submodule '$name'"
>>> +				;;
>>> +			esac
>>
>> I'd prefer `die "…"` to `echo >&2 "…"`.  It's hard to know if mapping
>> the user's preferred (unknown) update mechanism to 'checkout' is
>> serious or not.
>>
>> This commit also makes me think that --rebase, --merge, and --checkout
>> should be replaced with a single --update={rebase|merge|checkout|!…}
>> option, but that's probably food for another commit (and a long
>> finger-breaking deprecation period).
>
> All of the above points sound sensible to me.

I'll tentatively queue this on 'pu' (with the suggested "die"
update), with some rewording of the log message.  The patch needs to
be signed-off, though.

Thanks.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-06 14:06               ` Heiko Voigt
@ 2014-01-06 17:47                 ` Francesco Pretto
  2014-01-06 19:21                   ` David Engster
                                     ` (3 more replies)
  0 siblings, 4 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-06 17:47 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: git, Jens Lehmann, Junio C Hamano, W. Trevor King

Dear Heiko, my replies below. I also take a couple excerpts from other
emails, as I prefer to not flame on different threads :) .

2014/1/6 Heiko Voigt <hvoigt@hvoigt.net>:
> On Sun, Jan 05, 2014 at 10:46:11PM +0100, Francesco Pretto wrote:
>> It means he doesn't need to control other developers commit to be
>> checked out so he sets "submodule.<name>.ignore" to "all". In this way
>> he and the developers can work actively in their submodule copy.
>
> So practically speaking: You mean that the value of
> submodule.<name>.ignore is set to "all" in the master branch of the
> superproject? From your other email referring to svn:externals I figure
> that.
>

Correct, but this works also if the branch of the superproject is a
different branch than "master". I think you are right in a point, see
the next reply.

> The workflow could always be changed to allow recording revisions. Which
> is why you use git in the first place right? If you discard revisions
> for submodules tracking down regression bugs can become a big problem or
> completely impossible. Try using git bisect on such a history.
>

Ok, you are right: setting "submodule.<name>.ignore" to "all" by
default with a switch "--attached" in "git submodule add" is too much.
My point is just make sure users will checkout an attached HEAD.

>> "submodule.<name>.branch" is one setting that is not copied in
>> ".git/config" by "git submodule init". "git submodule update" will use
>> the setting in ".gitmodules" if not overridden voluntarily by the
>> developer in ".git/config". The maintainer can change that setting in
>> ".gitmodules" and commit the change. Modifies will be propagated by
>> the next "git pull && git submodule update" of the developer in the
>> superproject.
>
> I do not understand how does that ensure you get the correct submodule
> revision when checking out a tagged release? To get a precise revision
> the superproject needs to track a sha1 of a submodule commit. I do not
> see how that has anything to do with submodule.<name>.branch?
>

"submodule.<name>.attacched" set to true implies "--remote". sha1 of
the latest commit is taken from "origin/$branch". In this way you get
the latest commit of that branch, and you do a 'merge', 'rebase',
'checkout' or '!command' according to the configured ''. This
mechanism is already in the patch at the current state.

>> >  - In which situations does the developer or maintainer switch between
>> >    your attached/detached mode?
>>
>> The developer/maintainer does so optionally and voluntarily and it
>> effects only its private working tree.
>
> This does not answer my question. I would like to find out the reason
> why one would do the switch.
>

The developer does it voluntarily, at his responsibility, because he
may decide to partecipate more actively to the development of the
submodule and still want to use a simple "git submodule update" to
updates his submodules, overriding its configuration as it can be done
for other properties like, for example, "branch". This ability is of
course already possible reattaching the HEAD manually but you loose
the convenient ability to use "git submodule update".

>> The branch of course must exist prior submodule adding. In this
>> use-case it does not really matter who creates it and who merges into
>> it. Everyone with the right to merge into it has to work in the
>> submodule seamlessly, as it was working on separate clone of the same
>> repository used as the submodule.
> o
> Here is the same. I am searching for a description like:
>
> If the developer works on a feature that needs a submodule change he:
>   - creates a submodule branch
>   - configures that submodule branch in the superproject:
>         git config -f .gitmodules submodule.common.branch dev/some-feature
>         git commit -am "TEMP: track submodule common on branch"
>  - and pushes out his superproject branch
>
> The submodule branch is then posted for review and continued to work on.
>
> Once everyone involved is happy with the submodule change the branch in
> there gets merged to master.
>
> Now the branch in the superproject is modified to drop the change in
> .gitmodules and the sha1 reference in the superproject is updated to the
> current master of the superproject.
>
> The superproject branch is posted for review.
>
> ...
>
> Could you describe something like this for your workflow? A complete
> change lifecycle when a developer works, as you call it, "actively" in a
> submodule?
>

I'm really sorry, I thought this was already clear from the first
patch iteration. I will go more in depth:

Say we have our actual projects "project1" and "project2". Say we have
a project "common". This "common" project is *not* independent: it
exists only to serve "project1" and "project2" and it's tested only in
the scope of "project1" and "project2". Also "common" is very actively
developed and follows the same lifecyle of "project1" and "project2"
on separate branches. I think that it's important that you get this
point: developers of "common" don't clone it separately, as it would
be impossible to test it, they clone "project1" and "project2" and
expect to find it inside one of these.

Let say now how "common" can be shared between "project1" and
"project2" so developers of "project1" don't break "project2" working
on "common" and the other way around. "common" has the following
stable branches:
- master;
- master-project1;
- master-project2;

The maintainer of "project1" at master branch sets "common" as
submodule at branch "master-project1". The maintainer of "project2" at
master branch sets "common" as submodule at branch "master-project2".
Periodically a maintainer of "common" will pull both master-project1
and master-project1 on a branch "next". Maintainers of both "project1"
and "project1", in coordination, are responsible to make next to be
merged in master, so they can both sync their master-project1 and
master-project2 in the "common" submodule.

Let say now how for example {"project1" and "common"} can evolve. As
told, these can't really evolve separately. Maintainer of "project1"
prepares a branch called "staging-featureA". "featureA" is big and
will require more people to work on the same feature for days/weeks.
Maintainer of "project1" also prepares a branch
"project1-staging-featureA" on "common" and set ".gitmodules" of
"project1" to point to "project1-staging-featureA". Developers of
featureA would like to do this:

$ git pull
$ git checkout staging-featureA
$ git submodule update      # clones an attached HEAD of common on the branch
                                        #
'submodule.common.project1.staging-featureA'
$ .... start coding in common seamlessly as they where in project1 ....

Also developers do frequently rebase:
$ git pull --rebase
$ git submodule update

Or maybe a shortcut of this: "git submodule update" should be given
the possibility to go "--remote" by default.  Of course if "common" of
the developer is in a branch different that 'submodule.<name>.branch'
"git submodule update" has not to switch the branch.

>> Maybe who coded submodules at first was thinking that the best way to
>> contribute to a project is to checkout that repository, and not work
>> in the submodule. As said, this works well when the submodule
>> repository is a full project, and not a bunch of shared code.
>
>Why not work in the submodule? See explanation above.
>

Because, as said above, the submodule is not independent. It does not
have proper code that test it and the best test case is using the
submodule in the scope of the superproject.

>> >  - What are these subsequent "merge" or "rebase" update operations? Do
>> >    you mean everyone has submodule.name.update configured to merge or
>> >    rebase?
>> >
>>
>> subsequent "merge" or "rebase" update operations are just the ones
>> after the initial clone/checkout, nothing particular.
>
> To clarify you are talking about issuing "git merge" or "git rebase"
> commands in the superproject?
>

No, I'm talking about "git submoudule update" with "--merge" or
"--rebase switches or "submodule.name.update" configured.

2014/1/6 Heiko Voigt <hvoigt@hvoigt.net>:
> I am not so sure. svn:externals was IMO a hack in SVN to bind projects
> together. It does not record the revision and so has nothing to do
> with version control. If you simply want to always checkout the
> development tip of some project you could do something like this:
>
>        git submodule foreach 'git fetch && git checkout origin/master'

This can be very unconvenient if the reccomended *starting* branch to
where attach the HEAD is not "master":

git submodule foreach 'branch="$(git config -f $toplevel/.gitmodules
submodule.$name.branch)"; git checkout origin/$branch

Of course the developer after they may want to move to a local branch
(or may not: please don't forget shared repositories), but the above
command may difficult to be taught. Also with the comit[1] that blocks
copying of !command to ".git/config" and sets default "none", you made
it harder to offer a mantainer decided default update behavior like
the one I described.

> The demand for this 'missing feature' which we call the 'floating
> submodules' model has been around for some time but until now we could
> convince people that its not a feature but you are actually loosing
> history information.
>

Putting your reasoning to the extreme consequences: why does not "git
clone" clone a dettached HEAD? In your workflow I should probably
never start coding from "master", but people frequently do instead.
Also, as you observed, it's possible to track submodule revision sha1
also on an attached HEAD. If I don't want anyone to track the revision
I can already set 'ignore' property.

My bottom line:
- For what I understand, detached HEAD it's a way to say "hey, you
have to stay on this commit. Also don't even think you can push to the
upstream branch". This sometimes can't be spurious, as in the use case
I wrote above: access control on the remote repositories should be
enough. I think maintainers should have the option to make developers
to clone a repository starting with an attached HEAD on the branch
suggested in submodule.$name.branch;
- "git submodule update" is missing a property to do automatically
"--remote". I think in the use case I wrote it's really handy to have
a "git submodule update" to act like this.

Thank you for reading and sorry for the long email :)

Greetings,
Francesco

[1] http://marc.info/?l=git&m=138610752125816&w=2

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command
  2014-01-06 17:42             ` Junio C Hamano
@ 2014-01-06 17:52               ` Francesco Pretto
  0 siblings, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-06 17:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: W. Trevor King, git, Heiko Voigt

Ok, applying the suggested modifications and resending shortly.

Thank you,
Francesco

2014/1/6 Junio C Hamano <gitster@pobox.com>:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> "W. Trevor King" <wking@tremily.us> writes:
>>
>>> On Sun, Jan 05, 2014 at 03:50:48AM +0100, Francesco Pretto wrote:
>>>> +                   case "$update_module" in
>>>> +                   '')
>>>> +                           ;; # Unset update mode
>>>> +                   checkout | rebase | merge | none)
>>>> +                           ;; # Known update modes
>>>> +                   !*)
>>>> +                           ;; # Custom update command
>>>> +                   *)
>>>> +                           update_module=
>>>> +                           echo >&2 "warning: invalid update mode for submodule '$name'"
>>>> +                           ;;
>>>> +                   esac
>>>
>>> I'd prefer `die "…"` to `echo >&2 "…"`.  It's hard to know if mapping
>>> the user's preferred (unknown) update mechanism to 'checkout' is
>>> serious or not.
>>>
>>> This commit also makes me think that --rebase, --merge, and --checkout
>>> should be replaced with a single --update={rebase|merge|checkout|!…}
>>> option, but that's probably food for another commit (and a long
>>> finger-breaking deprecation period).
>>
>> All of the above points sound sensible to me.
>
> I'll tentatively queue this on 'pu' (with the suggested "die"
> update), with some rewording of the log message.  The patch needs to
> be signed-off, though.
>
> Thanks.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-06 17:47                 ` Francesco Pretto
@ 2014-01-06 19:21                   ` David Engster
  2014-01-07 19:27                     ` W. Trevor King
  2014-01-07  4:10                   ` W. Trevor King
                                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 144+ messages in thread
From: David Engster @ 2014-01-06 19:21 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Heiko Voigt, git, Jens Lehmann, Junio C Hamano, W. Trevor King

Francesco Pretto writes:
> 2014/1/6 Heiko Voigt <hvoigt@hvoigt.net>:
>> Could you describe something like this for your workflow? A complete
>> change lifecycle when a developer works, as you call it, "actively" in a
>> submodule?
>>
>
> I'm really sorry, I thought this was already clear from the first
> patch iteration. I will go more in depth:

While I have some trouble understanding all the details of Francesco's
description, I find the idea of "attaching submodules to branches" very
useful.  I think I could well use that to simplify my merging grunt work
for GNU Emacs (which, in case you're wondering, is probably switching to
git as its VCS). I don't mean to hijack this thread, and I guess my use
case is a bit different than what Francesco has in mind; still, I think
it is similar enough that my use case could help in talking about the
details of his patch; if not, please feel free to ignore it.

GNU Emacs ships with some pretty large packages, namely Gnus, Org and
CEDET, which are also available as "stand-alone" versions for manual
installation, and their development happens in separate upstream
repositories. Since I'm a CEDET developer, I'll use it as an example in
the following.

First off, it is important to note that merges are always
bi-directional: not only is new CEDET code pulled into Emacs, but Emacs
developers also change things which have to be merged back upstream. So
far, merging between the two repositories was done manually by me, which
is error-prone (and boring). I think that by pulling in CEDET directly
as a submodule, this merging could be made easier. Most importantly, my
hope is that more people than me could do it. :-)

Here's how I would like this to work; first the CEDET -> Emacs part,
which is rather straight-forward:

- The CEDET repository has two branches: 'master' and 'stable'.

- The Emacs repository imports CEDET's 'stable' branch as a submodule.

- CEDET's main development happens in 'master', and the CEDET developers
  are responsible for merging stable code to 'stable'. They will then
  make a new commit for the submodule in Emacs accordingly.

The Emacs -> CEDET part is more hairy. Most of the time, the fixes
happening in the Emacs repository for CEDET are very small and/or
trivial and can usually be considered "always stable": fixes for
spelling, compiler warnings, or small refactorings like renames,
etc. This kind of "merging back to CEDET upstream" should hence be as
easy as possible for Emacs developers:

- When an Emacs developer changes something in the CEDET submodule, the
  changes they commit should by default automatically land in CEDET's
  'stable' branch. That means that when they enter the submodule, they
  should be in the branch 'stable' instead of being detached, and a push
  should update the 'stable' branch in CEDET accordingly. The submodule
  must then be committed as well.

- It is then up to the CEDET developers to merge these changes into the
  'master' branch of the CEDET repo.

I know that the "correct" workflow would be to always use feature
branches, but it'd be nice if that could be avoided if one so chooses.

A little picture in the hope that it makes things clearer:

             +-----------+
             |  master   | <--
+-------+    +-----------+    | Merges to/from master
| CEDET |                     | done only by CEDET developers
+-------+                     | 
             +-----------+    |
             |  stable   | <--  <--------
             +-----------+               |
                                         |
                                         |
                                         | Any Emacs developer
                                         | can push and commit
                                         | submodule
+--------+    +----------------------+   |
| Emacs  | -- | lisp/cedet submodule | <-
+--------+    +----------------------+

AFAICS the main problem with this approach is that one always has to
think of committing the new SHA1 of the submodule. If I understand
Francesco correctly, he wants to eliminate the need for that by simply
always taking the head of the attached branch. I also think that would
be a nice feature, since in the above drawing, the lisp/cedet submodule
should always follow the 'stable' branch in CEDET upstream. However, as
Heiko notes, the history must be preserved to be able to go back to
earlier revisions, so there must be some kind of commit for the
submodule when 'stable' changes; maybe that could be automated somehow?

-David

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 17:37                   ` W. Trevor King
@ 2014-01-06 21:32                     ` Junio C Hamano
  0 siblings, 0 replies; 144+ messages in thread
From: Junio C Hamano @ 2014-01-06 21:32 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Heiko Voigt, Francesco Pretto, Git, Jens Lehmann

"W. Trevor King" <wking@tremily.us> writes:

>> And wouldn't it make it unnecessary to have a new "re-attach" option
>> if such a mode that never have to detach is used?
>
> I think so, but we currently don't have a "never detached" route for
> folks that are cloning submodules via update (instead of via
> 'submodule add').  Currently, new clone-updates will always leave you
> with a detached HEAD (unless you have branch-creation in your update
> !command).  My patch aims to close this detached-HEAD gap, for folks
> we expect will be doing local development, by creating an initial
> branch at clone-update time.

I am not a submodule expert so I may be missing some other gaps, but
what your change does sounds sensible to me.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 16:02                         ` Heiko Voigt
@ 2014-01-06 23:10                           ` Francesco Pretto
  2014-01-06 23:32                             ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-06 23:10 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: W. Trevor King, Git, Junio C Hamano, Jens Lehmann

2014/1/6 Heiko Voigt <hvoigt@hvoigt.net>:
>
> I agree. If we were to support this more easily we could add a
> configuration option so you can omit the --remote (i.e.:
> submodule.<name>.remote=true, as I also suggested in the other email).
>
> That way the developer checking out a branch in flight does not even
> need to know whether (and which) submodules sha1s are still in flight
> and temporarily set this configuration in the branches .gitmodules file.
>

"submodule.<name>.remote" can be useful but can be added later to aid
the current use case.

To not break the existing behavior what it's really needed here, IMO,
is a "submodule.<name>.attached" property that says two things:
- at the first clone on "git submodule update" stay attached to
"submodule.<name>.branch";
- implies "--remote", as it's the only thing that makes sense when the
submodules are attached.

My patch at the current unreleased state does exactly this.

> Maybe that could actually be the attach operation Francesco is
> suggesting:
>
>         git submodule attach [--pull] <submodule path> <branchname>
>
> will attach the specified submodule to a branch. That means it changes
> the .gitmodule file accordingly and stages it. With the --pull switch
> one can specify whether a local branch tracking the remote branch should
> be automatically created. Names and the command format are just a
> suggestion here.
>
> That way we can support the
>
>         fork superproject needing submodule changes and send submodule
>         changes upstream first.
>

My patch didn't do this, as the maintainer can do these things quite
easily[1] (maintainer is "cooler" with respect to other devs :) ), but
I think it could be good to also have this feature.

The feature I think that are still needed and you don't mention are:
- an "--attached" switch for the "add" command when the maintainer
create the submodule the first time (DONE in patch);
- a easy way to attach|detach the submodule locally by developer. This should:
    * fix the head state (DONE in patch);
    * fix the local .git/config "submodule.<name>.attached" property
accordingly (DONE in patch, unreleased).

I do the latest in the "update" command but it seems bad to touch
.git/config in the "update" command...

Maybe we should have a "git submodule head" command that does all
these things: --attach (for the maintainer), --attach|--detach (for
the developer).

[1]
$ ( cd submodule && git branch newbranch && git push -u origin HEAD)
$ git config -f .gitmodules submodule.newbranch.branch newbranch
$ git config -f .gitmodules submodule.newbranch.attached true
$ git add . && git commit -m "Forked superproject" && git push

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 23:10                           ` Francesco Pretto
@ 2014-01-06 23:32                             ` Francesco Pretto
  2014-01-07 18:27                               ` Junio C Hamano
  0 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-06 23:32 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: W. Trevor King, Git, Junio C Hamano, Jens Lehmann

2014/1/7 Francesco Pretto <ceztko@gmail.com>:
> To not break the existing behavior what it's really needed here, IMO,
> is a "submodule.<name>.attached" property that says two things:
> - at the first clone on "git submodule update" stay attached to
> "submodule.<name>.branch";
> - implies "--remote", as it's the only thing that makes sense when the
> submodules are attached.
>

Unless you decide to go with the proposed approach of Trevor, where
"submodule.<name>.branch" set means attached (if it's not changed:
this thread is quite hard to follow...). To this end, Junio could sync
with more "long-timers" (Heiko?) submodule users/devs to understand if
this breaks too much or not.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 16:56                 ` Junio C Hamano
  2014-01-06 17:37                   ` W. Trevor King
@ 2014-01-07  0:55                   ` Francesco Pretto
  1 sibling, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-07  0:55 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Heiko Voigt, W. Trevor King, Git, Jens Lehmann

2014/1/6 Junio C Hamano <gitster@pobox.com>:
>
> As long as origin/master contains the commit specified by the
> superproject, that would work, but it may be a good thing to use a
> mode of submodule.*.update that does not have to drop the user into
> a detached state in the first place.  I somehow thought that was
> what rebase (or merge) was about, that is, starting from the state
> where a branch is checked out in the submodule working tree, an
> update in the superproject would cause that branch checked out in
> the submodule brought up to date with respect to the commit
> specified in the superproject tree.  If that is not how it is
> supposed to work, please correct me---and we may have to add another
> mode that does so (or even make rebase/merge do so as a bugfix).
>

I think the mode you are referring to is actually my
"submodule.<name>.attached" property. As I said to Heiko, the
"submodule.<name>.attached" property says two things:
- at the first clone on "git submodule update" stay attached to
"submodule.<name>.branch";
- implies "--remote", as it's the only thing that makes sense when the
submodules are attached.

> And wouldn't it make it unnecessary to have a new "re-attach" option
> if such a mode that never have to detach is used?

I think the reattach|detach option are still needed (it is debatable
if we should have something like "git submodule head" command or we
can keep them in "git submodule update") because the user may want to
do so and doing it requires things should be really atomic:
    * fix the head state;
    * set the local .git/config "submodule.<name>.attached" property.

The "--attach" switch also can add a great bonus: it can reintegrate
orphaned commits when reattaching and having a "update" mode with
"merge" or "rebase". This is already in my patch.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-06 17:47                 ` Francesco Pretto
  2014-01-06 19:21                   ` David Engster
@ 2014-01-07  4:10                   ` W. Trevor King
  2014-01-07 22:36                     ` Preferred local submodule branches (was: Introduce git submodule attached update) W. Trevor King
  2014-01-07 22:51                     ` Re: [PATCH 2/2] Introduce git submodule attached update Heiko Voigt
  2014-01-07 18:56                   ` Junio C Hamano
  2014-01-07 19:07                   ` Junio C Hamano
  3 siblings, 2 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-07  4:10 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Heiko Voigt, git, Jens Lehmann, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 6106 bytes --]

On Mon, Jan 06, 2014 at 06:47:58PM +0100, Francesco Pretto wrote:
> I'm really sorry, I thought this was already clear from the first
> patch iteration. I will go more in depth:

For me anyway, this extra detail is very helpful.  Thanks :).

> Maintainer of "project1" also prepares a branch
> "project1-staging-featureA" on "common" and set ".gitmodules" of
> "project1" to point to "project1-staging-featureA". Developers of
> featureA would like to do this:
> 
> $ git pull
> $ git checkout staging-featureA
> $ git submodule update      # clones an attached HEAD of common on the branch
>                             # 'submodule.common.project1.staging-featureA'
> $ .... start coding in common seamlessly as they where in project1 ....

So the checked-out branch switches depending on the local superproject
branch.  That sounds nice, but I'm not sure where the
superproject-branch-to-local-submodule-branch mapping would be stored.
We currently do this for remote-tracking submodule branches with an
in-tree .gitmodules (which can differ between submodule branches) with
local overides in a single out-of-tree .git/config (which is
independent of the checked out branch).  Ideally we'd have a way to
add local overrides on a per-superproject-branch basis, but I don't
know what that would look like.

> Also developers do frequently rebase:
> $ git pull --rebase
> $ git submodule update
> 
> Or maybe a shortcut of this: "git submodule update" should be given
> the possibility to go "--remote" by default.

Rebasing the superproject and then updating the submodules (to the
superproject's gitlinked commits) is not the same as a --remote update
(to the subproject's upstream branch tip).

> Of course if "common" of the developer is in a branch different that
> 'submodule.<name>.branch' "git submodule update" has not to switch
> the branch.

I don't understand what you're saying here.

> >> Maybe who coded submodules at first was thinking that the best
> >> way to contribute to a project is to checkout that repository,
> >> and not work in the submodule. As said, this works well when the
> >> submodule repository is a full project, and not a bunch of shared
> >> code.
> >
> >Why not work in the submodule? See explanation above.
> 
> Because, as said above, the submodule is not independent. It does
> not have proper code that test it and the best test case is using
> the submodule in the scope of the superproject.

You can cd into the submodule, and develop it as an independent
repository.  When you want to test your changes, just cd back into the
superproject and run your test suite.

> 2014/1/6 Heiko Voigt <hvoigt@hvoigt.net>:
> > I am not so sure. svn:externals was IMO a hack in SVN to bind projects
> > together. It does not record the revision and so has nothing to do
> > with version control. If you simply want to always checkout the
> > development tip of some project you could do something like this:
> >
> >        git submodule foreach 'git fetch && git checkout origin/master'
> 
> This can be very unconvenient if the reccomended *starting* branch to
> where attach the HEAD is not "master":
> git submodule foreach 'branch="$(git config -f $toplevel/.gitmodules
> submodule.$name.branch)"; git checkout origin/$branch

Which is equivalent to:

  $ git submodule update --remote --checkout

except for branch-vs-detached-HEAD.  If you are doing local
development, I'd recommend setting up submodule.<name>.update to a
non-checkout strategy and using:

  $ git submodule update --remote

which will integrate the upstream changes with any local changes
(updating whichever local submodule branch you had checked out).

> Also with the comit[1] that blocks copying of !command to
> ".git/config" and sets default "none", you made it harder to offer a
> mantainer decided default update behavior like the one I described.

The maintainer can still suggest checkout/pull/rebase, and the
developer can still clear remove the none from .git/config after
initializing the submodule.  You only need to do this once per
submodule.

> I think maintainers should have the option to make developers to
> clone a repository starting with an attached HEAD on the branch
> suggested in submodule.$name.branch;

I agree, and want to use a non-checkout submodule.<name>.update mode
to identify developers who would want this.  My v2 patch switches on
submodule.<name>.branch, but I'll update it in v3 to switch on
submodule.<name>.update.  There's no need to confuse this with
additional attach/detach functionality.

> - "git submodule update" is missing a property to do automatically
> "--remote". I think in the use case I wrote it's really handy to have
> a "git submodule update" to act like this.

You can already add aliases, but a remote/local-gitlink config
variable would be nice too.

Here's an attempted summary of our desires, and my ideal route
forward:

* Preferred local submodule branches for each superproject branch.
  * Not currently supported by Git.
  * Requires some sort of per-superproject-branch .git/config.
  * Fall back to the remote-tracking submodule.<name>.branch?

* Auto checkout of the preferred branch
  * Can do this at clone-update time with my patch.
  * For later submodule branch switches, maybe we want:

      git submodule checkout [-b <branch>] [<paths>…]

    Then if a user blows off their detached HEAD, at least they'll
    feel a bit sheepish afterwards.

* Configurable (remote or local) default update source (so folks who
  primarily update --remote don't have to have long command lines).
  * New submodule.<name>.source = {remote|local} config
  * New 'update [--source={local|remote}]' option
  * Deprecate 'update --remote' with a long phase out.
  However:
  * Maybe they should just setup an alias instead?

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-05 16:17           ` [RFC v2] submodule: Respect requested " W. Trevor King
  2014-01-05 19:48             ` Heiko Voigt
  2014-01-05 21:27             ` Francesco Pretto
@ 2014-01-07 18:15             ` Junio C Hamano
  2014-01-07 18:47               ` W. Trevor King
  2 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-07 18:15 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Jens Lehmann, Heiko Voigt

"W. Trevor King" <wking@tremily.us> writes:

> From: "W. Trevor King" <wking@tremily.us>
>
> The previous code only checked out the requested branch in cmd_add.
> This commit moves the branch-checkout logic into module_clone, where
> it can be shared by cmd_add and cmd_update.  I also update the initial
> checkout command to use 'rebase' to preserve branches setup during
> module_clone.

I want to see the log message explain the motivation behind it
(i.e. instead of stopping after saying "We used to do X, now we do
Y", but also explain why we consider that Y is better than X).  Here
is my attempt.

    submodule: respect requested branch on all clones

    The previous code only checked out the requested branch in cmd_add
    but not in cmd_update; this left the user on a detached HEAD after
    an update initially cloned, and subsequent updates using rebase or
    merge mode will kept the HEAD detached, unless the user moved to the
    desired branch himself.

    Move the branch-checkout logic into module_clone, where it can be
    shared by cmd_add and cmd_update.  Also update the initial checkout
    command to use 'rebase' to preserve branches setup during
    module_clone.  This way, unless the user explicitly asks to work on
    a detached HEAD, subsequent updates all happen on the specified
    branch, which matches the end-user expectation much better.

    Signed-off-by: W. Trevor King <wking@tremily.us>
    Signed-off-by: Junio C Hamano <gitster@pobox.com>

Please correct me if I misunderstood the intention.

Having writing all the above and then looking at the patch again, it
is not immediately obvious to me where you use "rebase" when doing
the initial checkout, though.

> The current Documentation/git-submodule.txt has:
>
>   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`.

Side note but doesn't Francesco's "'checkout' is a valid update mode"
need to update this part of the documentation as well?


>  git-submodule.sh | 34 ++++++++++++++++++++--------------
>  1 file changed, 20 insertions(+), 14 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 2979197..167d4fa 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -253,6 +253,7 @@ module_clone()
>  	url=$3
>  	reference="$4"
>  	depth="$5"
> +	branch="$6"
>  	quiet=
>  	if test -n "$GIT_QUIET"
>  	then
> @@ -306,7 +307,15 @@ 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" &&
> +		case "$branch" in
> +		'') git checkout -f -q ;;
> +		?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
> +		esac
> +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
>  }
>  
>  isnumber()
> @@ -469,16 +478,7 @@ 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'")"
> +		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$branch" || exit
>  	fi
>  	git config submodule."$sm_name".url "$realrepo"
>  
> @@ -787,7 +787,8 @@ 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}"
>  		if ! test -z "$update"
>  		then
>  			update_module=$update
> @@ -815,7 +816,7 @@ 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
> +			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$config_branch" || exit
>  			cloned_modules="$cloned_modules;$name"
>  			subsha1=
>  		else
> @@ -861,7 +862,12 @@ Maybe you want to use 'update --init'?")"
>  			case ";$cloned_modules;" in
>  			*";$name;"*)
>  				# then there is no local change to integrate
> -				update_module= ;;
> +				if test -n "$config_branch"; then
> +					update_module="!git reset --hard -q"
> +				else
> +					update_module=
> +				fi
> +				;;
>  			esac
>  
>  			must_die_on_failure=

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-06 23:32                             ` Francesco Pretto
@ 2014-01-07 18:27                               ` Junio C Hamano
  2014-01-07 19:19                                 ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-07 18:27 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Heiko Voigt, W. Trevor King, Git, Jens Lehmann

Francesco Pretto <ceztko@gmail.com> writes:

> 2014/1/7 Francesco Pretto <ceztko@gmail.com>:
>> To not break the existing behavior what it's really needed here, IMO,
>> is a "submodule.<name>.attached" property that says two things:
>> - at the first clone on "git submodule update" stay attached to
>> "submodule.<name>.branch";
>> - implies "--remote", as it's the only thing that makes sense when the
>> submodules are attached.
>>
>
> Unless you decide to go with the proposed approach of Trevor, where
> "submodule.<name>.branch" set means attached (if it's not changed:
> this thread is quite hard to follow...). To this end, Junio could sync
> with more "long-timers" (Heiko?) submodule users/devs to understand if
> this breaks too much or not.

It is not immediately obvious to me why anybody who specifies the
submodule.*.branch variable to say "I want _that_ branch" not to
want to be on that branch but in a detached state, so from that
perspective, submodule.*.attach feels superfluous.

But I'd mostly defer the design discussion to Heiko (and Jens), WTK
and you.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 18:15             ` Junio C Hamano
@ 2014-01-07 18:47               ` W. Trevor King
  2014-01-07 19:21                 ` Junio C Hamano
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 18:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git, Francesco Pretto, Jens Lehmann, Heiko Voigt

[-- Attachment #1: Type: text/plain, Size: 2867 bytes --]

On Tue, Jan 07, 2014 at 10:15:25AM -0800, Junio C Hamano wrote:
>     submodule: respect requested branch on all clones
> 
>     The previous code only checked out the requested branch in cmd_add
>     but not in cmd_update; this left the user on a detached HEAD after
>     an update initially cloned, and subsequent updates using rebase or
>     merge mode will kept the HEAD detached, unless the user moved to the
>     desired branch himself.
> 
>     Move the branch-checkout logic into module_clone, where it can be
>     shared by cmd_add and cmd_update.  Also update the initial checkout
>     command to use 'rebase' to preserve branches setup during
>     module_clone.  This way, unless the user explicitly asks to work on
>     a detached HEAD, subsequent updates all happen on the specified
>     branch, which matches the end-user expectation much better.

This looks reasonable to me, but there are still changes I'd like to
make for a v3 (e.g. using submodule.<name>.update to trigger local
branch checkout).  However, I'm currently leaning towards a new 'git
submodule checkout' command with explicit preferred local submodule
branches (see [1]).  Maybe this should all wait until Jens rolls out
his update implementation [2]?

> Having writing all the above and then looking at the patch again, it
> is not immediately obvious to me where you use "rebase" when doing
> the initial checkout, though.

It's used to shift the local branch reference from from the
(arbitrary) cloned remote branch tip to the explicit submodule $sha1.
Otherwise the default method for that operation is a HEAD-detaching
'checkout'. I tried to explain it here [3].

> "W. Trevor King" <wking@tremily.us> writes:
> > The current Documentation/git-submodule.txt has:
> >
> >   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`.
> 
> Side note but doesn't Francesco's "'checkout' is a valid update mode"
> need to update this part of the documentation as well?

That would be nice.  I don't think his patch changes the docs, and I
don't know if mentioning the --checkout option belongs in that patch
as well, or in a separate fixup ;).

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240097
[2]: http://article.gmane.org/gmane.comp.version-control.git/240117
[3]: http://article.gmane.org/gmane.comp.version-control.git/239953

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-06 17:47                 ` Francesco Pretto
  2014-01-06 19:21                   ` David Engster
  2014-01-07  4:10                   ` W. Trevor King
@ 2014-01-07 18:56                   ` Junio C Hamano
  2014-01-07 19:44                     ` Francesco Pretto
  2014-01-07 19:07                   ` Junio C Hamano
  3 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-07 18:56 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Heiko Voigt, git, Jens Lehmann, W. Trevor King

Francesco Pretto <ceztko@gmail.com> writes:

>>> >  - In which situations does the developer or maintainer switch between
>>> >    your attached/detached mode?
>>>
>>> The developer/maintainer does so optionally and voluntarily and it
>>> effects only its private working tree.
>>
>> This does not answer my question. I would like to find out the reason
>> why one would do the switch.
>
> The developer does it voluntarily, at his responsibility, because he
> may decide to partecipate more actively to the development of the
> submodule and still want to use a simple "git submodule update" to
> updates his submodules, overriding its configuration as it can be done
> for other properties like, for example, "branch".

It is still unclear to me why we need attached/detached mode for
that.  The developer may want to do an exploratory development,
whose result is unknown to deserve to be committed on the specified
branch at the beginning, and choose to build on a detached HEAD,
which is a perfectly normal thing to do.  But the standard way to do
so, whether the developer is working in the top-level superproject
or in a submodule, would be to just do:

	cd $there && git checkout HEAD^0

or use whatever commit the state to be detached is at instead of
"HEAD" in the above example, no?

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-06 17:47                 ` Francesco Pretto
                                     ` (2 preceding siblings ...)
  2014-01-07 18:56                   ` Junio C Hamano
@ 2014-01-07 19:07                   ` Junio C Hamano
  2014-01-07 19:25                     ` Francesco Pretto
  3 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-07 19:07 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Heiko Voigt, git, Jens Lehmann, W. Trevor King

Francesco Pretto <ceztko@gmail.com> writes:

> My bottom line:
> - For what I understand, detached HEAD it's a way to say "hey, you
> have to stay on this commit. Also don't even think you can push to the
> upstream branch". This sometimes can't be spurious, as in the use case
> I wrote above: access control on the remote repositories should be
> enough. I think maintainers should have the option to make developers
> to clone a repository starting with an attached HEAD on the branch
> suggested in submodule.$name.branch;
> - "git submodule update" is missing a property to do automatically
> "--remote". I think in the use case I wrote it's really handy to have
> a "git submodule update" to act like this.

The short version I read in the message is that your workflow, in
which partipants want to work on a branch, gets frustrating with the
current system only because the default update/initial cloning
detaches HEAD and will stay in that state until the user gets out of
the detached state manually. Once that initial detachment is fixed,
there is no more major issue, as update will stay on that branch.

Am I reading you correctly?

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 18:27                               ` Junio C Hamano
@ 2014-01-07 19:19                                 ` Francesco Pretto
  2014-01-07 19:45                                   ` W. Trevor King
  2014-01-07 19:52                                   ` Francesco Pretto
  0 siblings, 2 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-07 19:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Heiko Voigt, W. Trevor King, Git, Jens Lehmann

2014/1/7 Junio C Hamano <gitster@pobox.com>:
>> Unless you decide to go with the proposed approach of Trevor, where
>> "submodule.<name>.branch" set means attached (if it's not changed:
>> this thread is quite hard to follow...). To this end, Junio could sync
>> with more "long-timers" (Heiko?) submodule users/devs to understand if
>> this breaks too much or not.
>
> It is not immediately obvious to me why anybody who specifies the
> submodule.*.branch variable to say "I want _that_ branch" not to
> want to be on that branch but in a detached state, so from that
> perspective, submodule.*.attach feels superfluous.
>

Junio, for what it concerns me I fully support this patch as, IMO, it
makes cleaner the role of the property "submodule.<name>.branch".
Because with my original proposal I decided to go non-breaking Heiko
and Jens could also take position on this because this patch will
represent a small behavior break.

Also, and important feature should be added together with this patch:
a way to go "--remote" by default on an attached HEAD. This can be
done at least in two ways:
- explicit, non breaking way: add a "submodule.<name>.remote"
property. When set to "true" it implies "--remote" when doing "git
submodule update", both on attached and detached HEAD;
- implicit, breaking way: assume "--remote" when doing "git submodule
update" on an attached HEAD. I am quite sure this will break a couple
of submodule tests (I already tried it), probably for marginal
reasons.

I think this is needed because it makes little sense to having an
attached HEAD and "git submodule update" does nothing.

Thank you,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 18:47               ` W. Trevor King
@ 2014-01-07 19:21                 ` Junio C Hamano
  2014-01-07 19:50                   ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-07 19:21 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Git, Francesco Pretto, Jens Lehmann, Heiko Voigt

"W. Trevor King" <wking@tremily.us> writes:

> On Tue, Jan 07, 2014 at 10:15:25AM -0800, Junio C Hamano wrote:
>>     submodule: respect requested branch on all clones
>> 
>>     The previous code only checked out the requested branch in cmd_add
>>     but not in cmd_update; this left the user on a detached HEAD after
>>     an update initially cloned, and subsequent updates using rebase or
>>     merge mode will kept the HEAD detached, unless the user moved to the
>>     desired branch himself.
>> 
>>     Move the branch-checkout logic into module_clone, where it can be
>>     shared by cmd_add and cmd_update.  Also update the initial checkout
>>     command to use 'rebase' to preserve branches setup during
>>     module_clone.  This way, unless the user explicitly asks to work on
>>     a detached HEAD, subsequent updates all happen on the specified
>>     branch, which matches the end-user expectation much better.
>
> This looks reasonable to me, but there are still changes I'd like to
> make for a v3 (e.g. using submodule.<name>.update to trigger local
> branch checkout).  However, I'm currently leaning towards a new 'git
> submodule checkout' command with explicit preferred local submodule
> branches (see [1]).  Maybe this should all wait until Jens rolls out
> his update implementation [2]?

Sounds good.  I'll backburner this one, then.

>> Having writing all the above and then looking at the patch again, it
>> is not immediately obvious to me where you use "rebase" when doing
>> the initial checkout, though.
>
> It's used to shift the local branch reference from from the
> (arbitrary) cloned remote branch tip to the explicit submodule $sha1.

The objective is not what I was questioning. In the patch I see

	git checkout -f -q -B "$branch" "origin/$branch"

used in the module_clone (which I think makes sense), and then
cmd_update uses "git reset --hard -q" to make sure that the working
tree matches the commit $sha1 obtained from the superproject's
gitlink (which may make $branch diverged from origin/$branch, but
still I think it makes sense).

But there is no 'rebase' I can see in the codepath, which was what I
was puzzled about.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-07 19:07                   ` Junio C Hamano
@ 2014-01-07 19:25                     ` Francesco Pretto
  0 siblings, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-07 19:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Heiko Voigt, git, Jens Lehmann, W. Trevor King

2014/1/7 Junio C Hamano <gitster@pobox.com>:
> Francesco Pretto <ceztko@gmail.com> writes:
>
>> My bottom line:
>> - For what I understand, detached HEAD it's a way to say "hey, you
>> have to stay on this commit. Also don't even think you can push to the
>> upstream branch". This sometimes can't be spurious, as in the use case
>> I wrote above: access control on the remote repositories should be
>> enough. I think maintainers should have the option to make developers
>> to clone a repository starting with an attached HEAD on the branch
>> suggested in submodule.$name.branch;
>> - "git submodule update" is missing a property to do automatically
>> "--remote". I think in the use case I wrote it's really handy to have
>> a "git submodule update" to act like this.
>
> The short version I read in the message is that your workflow, in
> which partipants want to work on a branch, gets frustrating with the
> current system only because the default update/initial cloning
> detaches HEAD and will stay in that state until the user gets out of
> the detached state manually. Once that initial detachment is fixed,
> there is no more major issue, as update will stay on that branch.
>
> Am I reading you correctly?
>

Yep, you got it correctly.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-06 19:21                   ` David Engster
@ 2014-01-07 19:27                     ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 19:27 UTC (permalink / raw)
  To: David Engster
  Cc: Francesco Pretto, Heiko Voigt, git, Jens Lehmann, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 2655 bytes --]

On Mon, Jan 06, 2014 at 08:21:24PM +0100, David Engster wrote:
>              +-----------+
>              |  master   | <--
> +-------+    +-----------+    | Merges to/from master
> | CEDET |                     | done only by CEDET developers
> +-------+                     | 
>              +-----------+    |
>              |  stable   | <--  <--------
>              +-----------+               |
>                                          |
>                                          |
>                                          | Any Emacs developer
>                                          | can push and commit
>                                          | submodule
> +--------+    +----------------------+   |
> | Emacs  | -- | lisp/cedet submodule | <-
> +--------+    +----------------------+

This looks reasonable, and except for the detached-HEAD after the
initial update-clone, I think Git already supports everything you
need.  If you set submodule.cedet.update to 'rebase' (or 'merge') you
can easily integrate your local master changes with cedet/master
(e.g. if a CEDET dev updates cedet/master before the Emacs dev has a
chance to push their fix).  With the non-checkout update mode, you'll
also stay on your checked-out master branch during 'submodule update'
calls.

> AFAICS the main problem with this approach is that one always has to
> think of committing the new SHA1 of the submodule.
> …
> However, as Heiko notes, the history must be preserved to be able to
> go back to earlier revisions, so there must be some kind of commit
> for the submodule when 'stable' changes; maybe that could be
> automated somehow?

If an Emacs dev in the submodule makes the CEDET change, you could use
a post-commit hook (in the CEDET submodule) to also commit the change
to the Emacs superproject).  However, commiting only the submodule
bump may not be what you want.  Maybe there are other superproject
changes that should be committed alongside the submodule bump.  Maybe
there is stuff in the superprojects's staging area that should *not*
be committed alongside the submodule bump.  This ambiguity makes it
tricky for Git to automatically do “the right thing”.

If cedet/master is updated independently by the CEDET devs, there's no
way for the local Emacs repo to know about the change, so it's
impossible to automatically update Emacs (without polling for CEDET
updates or some other transgression ;).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-07 18:56                   ` Junio C Hamano
@ 2014-01-07 19:44                     ` Francesco Pretto
  0 siblings, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-07 19:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Heiko Voigt, git, Jens Lehmann, W. Trevor King

2014/1/7 Junio C Hamano <gitster@pobox.com>:
> Francesco Pretto <ceztko@gmail.com> writes:
>> The developer does it voluntarily, at his responsibility, because he
>> may decide to partecipate more actively to the development of the
>> submodule and still want to use a simple "git submodule update" to
>> updates his submodules, overriding its configuration as it can be done
>> for other properties like, for example, "branch".
>
> It is still unclear to me why we need attached/detached mode for
> that.  The developer may want to do an exploratory development,
> whose result is unknown to deserve to be committed on the specified
> branch at the beginning, and choose to build on a detached HEAD,
> which is a perfectly normal thing to do.  But the standard way to do
> so, whether the developer is working in the top-level superproject
> or in a submodule, would be to just do:
>
>         cd $there && git checkout HEAD^0
>
> or use whatever commit the state to be detached is at instead of
> "HEAD" in the above example, no?
>

Because of the overlapping change with the the other patch proposed by
Trevor, and to not generate confusion, I will stop for now pursuing
for an "attach|detach" command/switch specific for submodules, waiting
for Trevors's patch possible acceptance. After that I will see it
still makes sense or not.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 19:19                                 ` Francesco Pretto
@ 2014-01-07 19:45                                   ` W. Trevor King
  2014-01-07 19:48                                     ` Francesco Pretto
  2014-01-07 22:38                                     ` Heiko Voigt
  2014-01-07 19:52                                   ` Francesco Pretto
  1 sibling, 2 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 19:45 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Junio C Hamano, Heiko Voigt, Git, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 1180 bytes --]

On Tue, Jan 07, 2014 at 08:19:49PM +0100, Francesco Pretto wrote:
> 2014/1/7 Junio C Hamano <gitster@pobox.com>:
> > It is not immediately obvious to me why anybody who specifies the
> > submodule.*.branch variable to say "I want _that_ branch" not to
> > want to be on that branch but in a detached state, so from that
> > perspective, submodule.*.attach feels superfluous.
> 
> Junio, for what it concerns me I fully support this patch as, IMO, it
> makes cleaner the role of the property "submodule.<name>.branch".

No, submodule.<name>.branch is the name of the remote-tracking branch
for 'update --remote'.  In this patch, I'm using it as a hint for the
preferred local branch name [1], which I now think was a bad idea.
After [2], I think that we should just define the preferred local
branch name explicitly (submodule.<name>.local-branch?).

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/239980
[2]: http://article.gmane.org/gmane.comp.version-control.git/240097

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 19:45                                   ` W. Trevor King
@ 2014-01-07 19:48                                     ` Francesco Pretto
  2014-01-07 21:37                                       ` W. Trevor King
  2014-01-07 22:38                                     ` Heiko Voigt
  1 sibling, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-07 19:48 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Junio C Hamano, Heiko Voigt, Git, Jens Lehmann

2014/1/7 W. Trevor King <wking@tremily.us>:
>> Junio, for what it concerns me I fully support this patch as, IMO, it
>> makes cleaner the role of the property "submodule.<name>.branch".
>
> No.

Trevor, maybe it was not clear. But I wanted to say:

" I fully support *Trevor's* patch..." :)

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 19:21                 ` Junio C Hamano
@ 2014-01-07 19:50                   ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 19:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git, Francesco Pretto, Jens Lehmann, Heiko Voigt

[-- Attachment #1: Type: text/plain, Size: 1280 bytes --]

On Tue, Jan 07, 2014 at 11:21:28AM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> > On Tue, Jan 07, 2014 at 10:15:25AM -0800, Junio C Hamano wrote:
> >> Having writing all the above and then looking at the patch again, it
> >> is not immediately obvious to me where you use "rebase" when doing
> >> the initial checkout, though.
> >
> > It's used to shift the local branch reference from from the
> > (arbitrary) cloned remote branch tip to the explicit submodule $sha1.
> 
> The objective is not what I was questioning. In the patch I see
> 
> 	git checkout -f -q -B "$branch" "origin/$branch"
> 
> used in the module_clone (which I think makes sense), and then
> cmd_update uses "git reset --hard -q" to make sure that the working
> tree matches the commit $sha1 obtained from the superproject's
> gitlink (which may make $branch diverged from origin/$branch, but
> still I think it makes sense).
> 
> But there is no 'rebase' I can see in the codepath, which was what I
> was puzzled about.

Ah, thanks.  s/rebase/reset/ in the commit message ;).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 19:19                                 ` Francesco Pretto
  2014-01-07 19:45                                   ` W. Trevor King
@ 2014-01-07 19:52                                   ` Francesco Pretto
  1 sibling, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-07 19:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Heiko Voigt, W. Trevor King, Git, Jens Lehmann

2014/1/7 Francesco Pretto <ceztko@gmail.com>:
> 2014/1/7 Junio C Hamano <gitster@pobox.com>:
>> It is not immediately obvious to me why anybody who specifies the
>> submodule.*.branch variable to say "I want _that_ branch" not to
>> want to be on that branch but in a detached state, so from that
>> perspective, submodule.*.attach feels superfluous.
>>
>
> Junio, for what it concerns me I fully support *this* patch as,

Where "this" patch is Trevor's one, don't get me wrong... :)

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 19:48                                     ` Francesco Pretto
@ 2014-01-07 21:37                                       ` W. Trevor King
  2014-01-07 21:51                                         ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 21:37 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Junio C Hamano, Heiko Voigt, Git, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 1262 bytes --]

On Tue, Jan 07, 2014 at 09:09:19PM +0100, Francesco Pretto wrote:
> 2014/1/7 W. Trevor King <wking@tremily.us>:
> >> Trevor, maybe it was not clear. But I wanted to say:
> >>
> >> " I fully support *Trevor's* patch..." :)
> >
> > Which I appreciate ;).  I still though I should point out that my
> > patch *confuses* the role of submodule.<name>.branch :p.
> 
> You are welcome. Also, at your wish, can you please reply also in
> public?

Here you go.

I'd be happy to hear ideas about superproject-branch-specific local
overrides to a hypothetical submodule.<name>.local-branch, in the
event that a developer doesn't like a default set in .gitmodules.  If
I could think of a way to do that, we could avoid this heuristic
approach, and make the local submodule.<name>.local-branch
vs. remote-tracking submodule.<name>.branch distinction more obvious.

It would also be nice if submodule.<name>.branch was just an initial
setup-time and detached-HEAD default.  If the submodule is on a branch
it would make more sense to use the checked-out branch's @{upstream}.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 21:37                                       ` W. Trevor King
@ 2014-01-07 21:51                                         ` Francesco Pretto
  0 siblings, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-07 21:51 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Junio C Hamano, Heiko Voigt, Git, Jens Lehmann

2014/1/7 W. Trevor King <wking@tremily.us>:
>
> I'd be happy to hear ideas about superproject-branch-specific local
> overrides to a hypothetical submodule.<name>.local-branch, in the
> event that a developer doesn't like a default set in .gitmodules.  If
> I could think of a way to do that, we could avoid this heuristic
> approach, and make the local submodule.<name>.local-branch
> vs. remote-tracking submodule.<name>.branch distinction more obvious.
>

Uh, I think you got it wrong in the other thread: I didn't proposed
such feature. I just wanted the attached submodule use case to be
supported and of course "--branch means attached" is even easier to
get this.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Preferred local submodule branches (was: Introduce git submodule attached update)
  2014-01-07  4:10                   ` W. Trevor King
@ 2014-01-07 22:36                     ` W. Trevor King
  2014-01-07 23:52                       ` W. Trevor King
  2014-01-07 22:51                     ` Re: [PATCH 2/2] Introduce git submodule attached update Heiko Voigt
  1 sibling, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 22:36 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Heiko Voigt, git, Jens Lehmann, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 2921 bytes --]

On Tue, Jan 07, 2014 at 10:51:34PM +0100, Francesco Pretto wrote:
> 2014/1/7 W. Trevor King <wking@tremily.us>:
> >
> > I'd be happy to hear ideas about superproject-branch-specific local
> > overrides to a hypothetical submodule.<name>.local-branch, in the
> > event that a developer doesn't like a default set in .gitmodules.  If
> > I could think of a way to do that, we could avoid this heuristic
> > approach, and make the local submodule.<name>.local-branch
> > vs. remote-tracking submodule.<name>.branch distinction more obvious.
> 
> Uh, I think you got it wrong in the other thread:

I'm grafting this discussion back on to the thread where I proposed
submodule.<name>.local-branch.

> I didn't proposed such feature.

Right.  I proposed this feature after reading your proposed workflow.

> I just wanted the attached submodule use case to be supported and of
> course "--branch means attached" is even easier to get this.

As I understood it, the '--branch means attached' stuff was tied up
with automatic --remote updates.

There are three branches that submodule folks usually care about:

1. The linked $sha1 in the superproject (set explicitly for every
   superproject commit, and thus for every superproject branch).
2. The remote-tracking submodule.<name>.branch that lives in the
   upstream submodule.<name>.url repository.
3. The submodule's locally checked out branch, which we currently let
   the developer setup by hand, which is used integrated with one of
   the other two branches during non-checkout updates.

Git is currently a bit weak on conveniently handling type-3 branches.
“Just use what the developer has setup” works well for many basic
workflows, but falls short for:

* Cloning-updates, where we currently always setup a detached HEAD.
* Workflows where the preferred type-3 branch depends on the
  superproject branch.

The former is easy to fix [1] if you accept submodule.<name>.branch as
a guess, but this conflates the type-2 and type-3 branches.

For the latter, you'd want something like:

On Mon, Jan 06, 2014 at 08:10:04PM -0800, W. Trevor King wrote:
> * Auto checkout of the preferred branch
>   * Can do this at clone-update time with my patch.
>   * For later submodule branch switches, maybe we want:
> 
>       git submodule checkout [-b <branch>] [<paths>…]
> 
>     Then if a user blows off their detached HEAD, at least they'll
>     feel a bit sheepish afterwards.

which would likely need some of Jens' new core checkout handling [2].

Cheers,
Trevor

[1]: Using something along the lines of my
     http://article.gmane.org/gmane.comp.version-control.git/239967
[2]: http://article.gmane.org/gmane.comp.version-control.git/240117

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 19:45                                   ` W. Trevor King
  2014-01-07 19:48                                     ` Francesco Pretto
@ 2014-01-07 22:38                                     ` Heiko Voigt
  2014-01-08  0:17                                       ` Francesco Pretto
  1 sibling, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-07 22:38 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Francesco Pretto, Junio C Hamano, Git, Jens Lehmann

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

here my current thoughts in a kind of summary email.

On Tue, Jan 07, 2014 at 11:45:03AM -0800, W. Trevor King wrote:
> On Tue, Jan 07, 2014 at 08:19:49PM +0100, Francesco Pretto wrote:
> > 2014/1/7 Junio C Hamano <gitster@pobox.com>:
> > > It is not immediately obvious to me why anybody who specifies the
> > > submodule.*.branch variable to say "I want _that_ branch" not to
> > > want to be on that branch but in a detached state, so from that
> > > perspective, submodule.*.attach feels superfluous.
> > 
> > Junio, for what it concerns me I fully support this patch as, IMO, it
> > makes cleaner the role of the property "submodule.<name>.branch".
> 
> No, submodule.<name>.branch is the name of the remote-tracking branch
> for 'update --remote'.  In this patch, I'm using it as a hint for the
> preferred local branch name [1], which I now think was a bad idea.
> After [2], I think that we should just define the preferred local
> branch name explicitly (submodule.<name>.local-branch?).

I am not so sure about that. Having an extra value adds more
configuration burden to the user and it also does not help to understand
how this feature is supposed to be used.

Even though I was confused in the first place by the remote/local branch
switch for this option, after thinking a little bit more about it I
think it makes perfect sense to use the branch option as a hint for the
local branch.

Let me explain by an example. Suppose we have the following setup:

1. Fast-forward situation

    superproject      submodule

 master PA--------------->A master
                          |
                          B origin/master

Lets say superproject has submodule.submodule.branch=master and
submodule.submodule.update=merge.

Doing the initial update which clones results in the submodules master
branch being set to the sha1 registered in the superproject.

Now an update to the newest master in submodule is straightforward:

$ git submodule update --remote

2. Direct work situation

The developer start with the same setup as in situation 1 but now
directly starts to work in the submodule and creates commit C.

    superproject      submodule

 master PA--------------->A
                          |\
            origin/master B C master

$ git submodule update --remote
$ git commit -a -m "update submodule"

gets him this:

    superproject      submodule

        PA--------------->A
         |                |\
         |  origin/master B C
         |                |/
 master PB--------------->D master

Where now both the submodule and the superproject can be directly
pushed. If origin/master in the submodule is tracked by master this is
actually one command

$ git push --recurse-submodules=on-demand

So with your (Trevors) patch and reusing submodule.<name>.branch using
this kind of direct work in submodules is made easy. And wasn't that
what people always requested? ;-) Well, at least if you do not use
feature branches this makes it easy. But I think that is a good start
make the simple things easy first. Then we can later discuss the more
complicated ones. It seems to me that is also the case David wants for
his emacs/CEDET workflow: Make it easy for the superproject developers
to directly push out trivial fixes to the submodule.

And it also seems to me that is want Francesco wants.

One thing is missing though (and I think thats where Francesco came
from): What if the developer already has a detached HEAD in the
submodule?

How does he attach to a branch? For this we need something similar to
Francescos attach/detach or Trevors submodule checkout with Junio's checkout
HEAD~0 from here[1].

I am still undecided how we should call it. Because of my

Idea for feature branch support
- -------------------------------

For the branch attaching feature I would also like something that can actually
modify .git/config and for me more importantly .gitmodules.

So e.g. if I want to work on a longer lived feature branch in a submodule which
I need in a feature branch in the superproject I would do something like this:

$ git submodule checkout --gitmodules --merge -b hv/my-cool-feature

Which should create a local feature branch hv/my-cool-feature in the submodule,
checkout that branch and modify .gitmodules (because of --gitmodules) to have
submodule.<name>.update=merge, submodule.<name>.branch=hv/my-cool-feature and
stage that to the index.

This is a temporary setting so everyone who is working together can update
their branches easily. Once finished (with the prove that the big feature in
the superproject works) everyone can go and polish the submodule branches,
get their changes accepted there first, and then the update/branch setting
local for this branch will be dropped. In this workflow these settings never
enter a stable branch but are still very useful to transport this information
while developing.

Just an idea of a future extension we should keep in mind when designing the
command to attach to a branch. But maybe the command to configure this should
be completely independent from checkout. I.e.:

git submodule checkout - syncs to a possible update/branch
git submodule attach   - creates a submodule branch and configures
			 update/branch in .git/config or .gitmodules
git submodule detach?  - reverse attach

or maybe --attach and --detach in this scenario could be options to checkout?

Still unsure...

Cheers Heiko

[1] http://article.gmane.org/gmane.comp.version-control.git/240097
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)

iEYEARECAAYFAlLMggIACgkQjLR3Aoip+rpoMACgpn4XzDD4CvD+HCi8coIlwueP
gQUAn1v1BSJ+k8IJT7S/hwtojT+sUmgP
=GGTX
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-07  4:10                   ` W. Trevor King
  2014-01-07 22:36                     ` Preferred local submodule branches (was: Introduce git submodule attached update) W. Trevor King
@ 2014-01-07 22:51                     ` Heiko Voigt
  2014-01-07 23:14                       ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-07 22:51 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Francesco Pretto, git, Jens Lehmann, Junio C Hamano

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Mon, Jan 06, 2014 at 08:10:04PM -0800, W. Trevor King wrote:
> Here's an attempted summary of our desires, and my ideal route
> forward:
> 
> * Preferred local submodule branches for each superproject branch.
>   * Not currently supported by Git.
>   * Requires some sort of per-superproject-branch .git/config.
>   * Fall back to the remote-tracking submodule.<name>.branch?
> 
> * Auto checkout of the preferred branch
>   * Can do this at clone-update time with my patch.
>   * For later submodule branch switches, maybe we want:
> 
>       git submodule checkout [-b <branch>] [<paths>…]
> 
>     Then if a user blows off their detached HEAD, at least they'll
>     feel a bit sheepish afterwards.

Well, for development on a detached HEAD in a submodule we are currently
not very careful anyway. A simple

	git submodule update

will already blow away any detached HEAD work. But AFAIK it should
trigger the "you are leaving commits from a detached HEAD behind"
warning, so there is some safeguard and recovery.

Cheers Heiko
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)

iEYEARECAAYFAlLMhPAACgkQjLR3Aoip+rqP6wCeIhtpWLJC3XVO3nu2ViQTbHPg
T5wAoLLEZ256GOOjBxoTKo2/FmfvQGLp
=+bqm
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH 2/2] Introduce git submodule attached update
  2014-01-07 22:51                     ` Re: [PATCH 2/2] Introduce git submodule attached update Heiko Voigt
@ 2014-01-07 23:14                       ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 23:14 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Francesco Pretto, git, Jens Lehmann, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 2469 bytes --]

On Tue, Jan 07, 2014 at 11:51:28PM +0100, Heiko Voigt wrote:
> On Mon, Jan 06, 2014 at 08:10:04PM -0800, W. Trevor King wrote:
> > Here's an attempted summary of our desires, and my ideal route
> > forward:
> > 
> > * Preferred local submodule branches for each superproject branch.
> >   * Not currently supported by Git.
> >   * Requires some sort of per-superproject-branch .git/config.
> >   * Fall back to the remote-tracking submodule.<name>.branch?
> > 
> > * Auto checkout of the preferred branch
> >   * Can do this at clone-update time with my patch.
> >   * For later submodule branch switches, maybe we want:
> > 
> >       git submodule checkout [-b <branch>] [<paths>…]
> > 
> >     Then if a user blows off their detached HEAD, at least they'll
> >     feel a bit sheepish afterwards.
> 
> Well, for development on a detached HEAD in a submodule we are currently
> not very careful anyway. A simple
> 
> 	git submodule update
> 
> will already blow away any detached HEAD work.

Only if you use the checkout strategy.  With --merge or --rebase,
you'll have the $sha1 (or upstream remote with --remote) integrated
with your detached HEAD work.  You end up with a new detached HEAD
containing the result of the integration (just confirmed with tests
using Git v1.8.3.2).  That seems reasonable to me, so I'm happy with
the integration logic.

> But AFAIK it should trigger the "you are leaving commits from a
> detached HEAD behind" warning, so there is some safeguard and
> recovery.

I did not see those in testing with Git v1.8.3.2, likely because of
the '-f -q' we pass to 'git checkout' for checkout-mode updates.

Regardless of branch integration issues, I think a
per-superproject-branch preferred submodule branch is important for
'git checkout' to work in the superproject.  If you want:

* submodule branch master for superproject branch master, and
* submodule branch my-feature for superproject branch my-feature,

  $ git checkout my-feature

in the superproject is currently going to leave you with the submodule
on master, which is not convenient ;).  I think we should come up with
a better solution to the superproject checkout problem before adding
in additional complications due to branch integration ;).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Preferred local submodule branches (was: Introduce git submodule attached update)
  2014-01-07 22:36                     ` Preferred local submodule branches (was: Introduce git submodule attached update) W. Trevor King
@ 2014-01-07 23:52                       ` W. Trevor King
  2014-01-08  3:47                         ` Preferred local submodule branches W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-07 23:52 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Heiko Voigt, git, Jens Lehmann, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 2802 bytes --]

On Tue, Jan 07, 2014 at 02:36:25PM -0800, W. Trevor King wrote:
> There are three branches that submodule folks usually care about:
> 
> 1. The linked $sha1 in the superproject (set explicitly for every
>    superproject commit, and thus for every superproject branch).
> 2. The remote-tracking submodule.<name>.branch that lives in the
>    upstream submodule.<name>.url repository.
> 3. The submodule's locally checked out branch, which we currently let
>    the developer setup by hand, which is used integrated with one of
>    the other two branches during non-checkout updates.
> 
> Git is currently a bit weak on conveniently handling type-3 branches.
> “Just use what the developer has setup” works well for many basic
> workflows, but falls short for:
> 
> * Cloning-updates, where we currently always setup a detached HEAD.
> * Workflows where the preferred type-3 branch depends on the
>   superproject branch.
> 
> The former is easy to fix [1] if you accept submodule.<name>.branch as
> a guess, but this conflates the type-2 and type-3 branches.
> 
> For the latter, you'd want something like:
> 
> On Mon, Jan 06, 2014 at 08:10:04PM -0800, W. Trevor King wrote:
> > * Auto checkout of the preferred branch
> >   * Can do this at clone-update time with my patch.
> >   * For later submodule branch switches, maybe we want:
> > 
> >       git submodule checkout [-b <branch>] [<paths>…]
> > 
> >     Then if a user blows off their detached HEAD, at least they'll
> >     feel a bit sheepish afterwards.
> 
> which would likely need some of Jens' new core checkout handling [2].
> 
> [1]: Using something along the lines of my
>      http://article.gmane.org/gmane.comp.version-control.git/239967
> [2]: http://article.gmane.org/gmane.comp.version-control.git/240117

For example, in Jonathan's recent version of Jens' series, the
initial-setup and update functionality are moving into C.  See:

* populate_submodule() [1] for the initial-clone setup (calling
  'read-tree'), and
* update_submodule() [2] for subsequent updates (calling 'checkout -q'
  with an optional '-f')

this is where any submodule.<name>.local-branch would come into play,
if we decide to go down that route.  It doesn't look like the C
updates have the auto-clone functionality that the Bash updates have.
I'm not sure if that's in the pipe or not.  I'm not as familiar with
the C implementation though, so maybe I'm missing the mark here.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/239698
[2]: http://article.gmane.org/gmane.comp.version-control.git/239699

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-07 22:38                                     ` Heiko Voigt
@ 2014-01-08  0:17                                       ` Francesco Pretto
  2014-01-08  1:05                                         ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-08  0:17 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: W. Trevor King, Junio C Hamano, Git, Jens Lehmann

2014/1/7 Heiko Voigt <hvoigt@hvoigt.net>:
> One thing is missing though (and I think thats where Francesco came
> from): What if the developer already has a detached HEAD in the
> submodule?
>
> How does he attach to a branch? For this we need something similar to
> Francescos attach/detach or Trevors submodule checkout with Junio's checkout
> HEAD~0 from here[1].
>
> I am still undecided how we should call it. Because of my
>
> Idea for feature branch support
> - -------------------------------
>
> For the branch attaching feature I would also like something that can actually
> modify .git/config and for me more importantly .gitmodules.
>
> So e.g. if I want to work on a longer lived feature branch in a submodule which
> I need in a feature branch in the superproject I would do something like this:
>
> $ git submodule checkout --gitmodules --merge -b hv/my-cool-feature
>

I said in another thread I said to Junio am not pursuing
--attach|--detach anymore, but seeing that now everybody seem to be
excited about attached HEAD here we are...

Heiko, it's all day I think this syntax: it supports your above "git
submodule checkout" and more. Take attention at the feature branch
part!

NOTE: the following seems to me compatible with Trevor's
"submodule.<module>.branch means attached" patch.

git submodule head
================

The full syntax is the sum of the following ones:
git submodule head [-b <branch>] [--attach] [--] [<path>...]
git submodule head [-b <branch>] [--attach] --index [--] [<path>...]
git submodule head --reset [--] [<path>...]
git submodule head --reset --index [--] [<path>...]

(NOTE: --index should be the same as Heiko's above --gitmodules, it
means -> touch .gitmodules)

All the switches combinations follow, explained:

# Attach the submodule HEAD to <branch>.
# Also set ".git/config" 'submodule.<module>.branch' to <branch>
$ git submodule head -b <branch> --attach <module>

# Attach the submodule HEAD to 'submodule.<module>.branch'.
# If it does not exists defaults to <remote>/master
$ git submodule head --attach <module>

# Unset  ".git/config" 'submodule.<module>.branch'
# Also attach or detach the HEAD according to what is in ".gitmodules":
# with Trevor's patch 'submodule.<module>.branch' set means attached,
# unset means detached
$ git submodule head --reset <module>

NOTE: feature branch part!

# Set ".gitmodules" 'submodule.<module>.branch' to <branch>
$ git submodule head -b <branch> --attach --index <module>

# Unset ".gitmodules" 'submodule.<module>.branch'
$ git submodule head --reset --index <module>
---------------------------------------------------------------------

Also note that a --detach switch is not needed with Trevor's patch. To
resync to a dettached HEAD workflow, when 'submodule.<module>.branch'
is unset in ".gitmodule", --reset (without --index) should be enough.

What do you think? Better?

Thank you,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-08  0:17                                       ` Francesco Pretto
@ 2014-01-08  1:05                                         ` W. Trevor King
  2014-01-08  2:12                                           ` Francesco Pretto
                                                             ` (2 more replies)
  0 siblings, 3 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-08  1:05 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann

[-- Attachment #1: Type: text/plain, Size: 4079 bytes --]

On Wed, Jan 08, 2014 at 01:17:49AM +0100, Francesco Pretto wrote:
> # Attach the submodule HEAD to <branch>.
> # Also set ".git/config" 'submodule.<module>.branch' to <branch>
> $ git submodule head -b <branch> --attach <module>

I prefer submodule.<name>.local-branch for the submodule's local
branch name.  I also prefer 'checkout' to 'head', because 'checkout'
already exists in non-submodule Git for switching between local
branches.

> # Attach the submodule HEAD to 'submodule.<module>.branch'.
> # If it does not exists defaults to <remote>/master
> $ git submodule head --attach <module>

Defaulting to the configured local branch is fine, but I think it
should default to 'master' if no local branch is configured.  This
should not have anything to do with remote-tracking branches (that's
what 'submodule update' already handles).  I don't understand why
remote-tracking-branch integration keeps getting mixed up with
local-branch checkout.

> # Unset  ".git/config" 'submodule.<module>.branch'
> # Also attach or detach the HEAD according to what is in ".gitmodules":
> # with Trevor's patch 'submodule.<module>.branch' set means attached,
> # unset means detached
> $ git submodule head --reset <module>

To me this reads “always detach HEAD” (because it unsets
submodule.<name>.branch, and submodule.<name>.branch unset means
detached).  Note that I've moved away from “submodule.<name>.branch
set means attached” towards “we should set per-superproject-branch
submodule.<name>.local-branch explicitly” [1].

> NOTE: feature branch part!
> 
> # Set ".gitmodules" 'submodule.<module>.branch' to <branch>
> $ git submodule head -b <branch> --attach --index <module>
> 
> # Unset ".gitmodules" 'submodule.<module>.branch'
> $ git submodule head --reset --index <module>
> ---------------------------------------------------------------------

These are just manipulating .gitmodules.  I think we also need
per-superproject-branch configs under the superproject's .git/ for
developer overrides.

> What do you think? Better?

I don't think so.  To elaborate the idea I sketched out here [2], say
you want:

  Superproject branch  Submodule branch  Upstream branch
  ===================  ================  ===============
  master               master            master
  super-feature        master            master
  my-feature           my-feature        master
  other-feature        other-feature     other-feature

That's only going to work with per-superproject-branch configs for
both the local and remote branches.  Using the same name for both
local and remote branches does not work.

Let me motivate each of the combinations in the above table:

* master, master, master: The stable trunk.
* super-feature, master, master: A superproject feature that works
  with the stock submodule.
* my-feature, my-feature, master: A superproject feature that needs an
  improved submodule, but wants to integrate upstream master changes
  during development.
* other-feature, other-feature, other-feature: A superproject feature
  that needs an improved submodule, and wants to integrate
  other-feature changes that are also being developed upstream.

The deal-breaker for recycling submodule.<name>.branch to also mean
the local branch name is the {my-feature, my-feature, master} case.
Do we want to force submodule developers to always match the upstream
name of the feature branch they'd like to integrate with?  What if
there is no upstream my-feature branch (and the superproject developer
pushes submodule branches upstream via email)?  Making the local
branch name independently configurable avoids these issues with a
minimal increase in complexity.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240177
[2]: http://article.gmane.org/gmane.comp.version-control.git/240180

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-08  1:05                                         ` W. Trevor King
@ 2014-01-08  2:12                                           ` Francesco Pretto
  2014-01-08 23:07                                           ` Francesco Pretto
  2014-01-08 23:54                                           ` Re: [RFC v2] submodule: Respect requested branch on all clones Francesco Pretto
  2 siblings, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-08  2:12 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann

2014/1/8 W. Trevor King <wking@tremily.us>:
> Note that I've moved away from “submodule.<name>.branch
> set means attached” towards “we should set per-superproject-branch
> submodule.<name>.local-branch explicitly” [1].
>

Honestly, I'm having an hard time to follow this thread. Also, you
didn't update the patch. If you were endorsed by someone (Junio,
Heiko, ...) for the "submodule.<name>.local-branch" feature please
show me where.

I somehow understand the point of the
"submodule.<name>.local-branch" property, but I can't "see" the the
workflow. Please, show me some hypothetical scripting example with as
much complete as possible workflow (creation, developer update,
mantainers creates feature branch, developer update, developer attach
to another branch). Also, consider I proposed to support the attached
HEAD path to reduce complexity and support a simpler use case for
git submodules. I would be disappointed if the complexity is reduced in a
way and augmented in another.

> On Wed, Jan 08, 2014 at 01:17:49AM +0100, Francesco Pretto wrote:
>> # Attach the submodule HEAD to <branch>.
>> # Also set ".git/config" 'submodule.<module>.branch' to <branch>
>> $ git submodule head -b <branch> --attach <module>
> [...]
> I also prefer 'checkout' to 'head', because 'checkout'
> already exists in non-submodule Git for switching between local
> branches.
>

I can agree with similarity to other git commands, but 'checkout' does
not give me the idea of something that writes to ".git/config" or
".gitmodules".

>> # Attach the submodule HEAD to 'submodule.<module>.branch'.
>> # If it does not exists defaults to <remote>/master
>> $ git submodule head --attach <module>
>
> Defaulting to the configured local branch is fine, but I think it
> should default to 'master' if no local branch is configured.  This
> should not have anything to do with remote-tracking branches (that's
> what 'submodule update' already handles).  I don't understand why
> remote-tracking-branch integration keeps getting mixed up with
> local-branch checkout.
>

Yep, it should default to "master", my fault.

>> # Unset  ".git/config" 'submodule.<module>.branch'
>> # Also attach or detach the HEAD according to what is in ".gitmodules":
>> # with Trevor's patch 'submodule.<module>.branch' set means attached,
>> # unset means detached
>> $ git submodule head --reset <module>
>
> To me this reads “always detach HEAD” (because it unsets
> submodule.<name>.branch, and submodule.<name>.branch unset means
> detached).

I disagree: this would remove only the value in ".git/config". If the
value is till present in ".gitmodules", as I wrote above, the behavior
of what is in the index should be respected as for the other
properties. Also it gives a nice meaning to a switch like --reset :
return to how it was before.

>> NOTE: feature branch part!
>>
>> # Set ".gitmodules" 'submodule.<module>.branch' to <branch>
>> $ git submodule head -b <branch> --attach --index <module>
>>
>> # Unset ".gitmodules" 'submodule.<module>.branch'
>> $ git submodule head --reset --index <module>
>> ---------------------------------------------------------------------
>
> These are just manipulating .gitmodules.  I think we also need
> per-superproject-branch configs under the superproject's .git/ for
> developer overrides.
>

I disagree: in my idea the --index switch is a maintainer only command
to modify the behavior of the developers and touch only indexed files
(.gitmodules, or create a new submodule branch). It expressly don't
touch .git/config.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Preferred local submodule branches
  2014-01-07 23:52                       ` W. Trevor King
@ 2014-01-08  3:47                         ` W. Trevor King
  2014-01-08  4:06                           ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-08  3:47 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Heiko Voigt, git, Jens Lehmann, Jonathan Nieder, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 8904 bytes --]

On Wed, Jan 08, 2014 at 03:12:44AM +0100, Francesco Pretto wrote:
> 2014/1/8 W. Trevor King <wking@tremily.us>:
> > Note that I've moved away from “submodule.<name>.branch
> > set means attached” towards “we should set per-superproject-branch
> > submodule.<name>.local-branch explicitly” [1].
> 
> Honestly, I'm having an hard time to follow this thread.

I tried to refocus things (with a new subject) in this sub-thread.
Hopefully that helps make the discussion more linear ;).

> Also, you didn't update the patch.

I'm waiting [1] to see how the C-level checkout by Jens and Jonathan
progresses [2,3] before writing more code.

> If you were endorsed by someone (Junio, Heiko, ...) for the
> "submodule.<name>.local-branch" feature please show me where.

As far as I know, no-one else has endorsed this idea (yet :).  Heiko
has expressed concern [4], but not convincingly enough (yet :) to win
me over ;).

> I somehow understand the point of the
> "submodule.<name>.local-branch" property, but I can't "see" the the
> workflow. Please, show me some hypothetical scripting example with
> as much complete as possible workflow (creation, developer update,
> mantainers creates feature branch, developer update, developer
> attach to another branch).

I've put this at the bottom of the message to avoid bothering the
tl;dr crowd, although they have probably long since tuned us out ;).

> Also, consider I proposed to support the attached HEAD path to
> reduce complexity and support a simpler use case for git
> submodules. I would be disappointed if the complexity is reduced in
> a way and augmented in another.

Agreed.  I think we're all looking for the least-complex solution that
covers all (or most) reasonable workflows.

> > On Wed, Jan 08, 2014 at 01:17:49AM +0100, Francesco Pretto wrote:
> >> # Attach the submodule HEAD to <branch>.
> >> # Also set ".git/config" 'submodule.<module>.branch' to <branch>
> >> $ git submodule head -b <branch> --attach <module>
> > [...]
> > I also prefer 'checkout' to 'head', because 'checkout'
> > already exists in non-submodule Git for switching between local
> > branches.
> 
> I can agree with similarity to other git commands, but 'checkout'
> does not give me the idea of something that writes to ".git/config"
> or ".gitmodules".

Neither does 'head'.  We have precedence in 'git submodule add' for
embracing and extending a core git command with additional .gitmodules
manipulation.  I think it's easier to pick up the submodule jargon
when we add submodule-specific side-effects to submodule-specific
commands named after their core analogs than it would be if we pick
unique names for the submodule-specific commands.

> >> # Unset  ".git/config" 'submodule.<module>.branch'
> >> # Also attach or detach the HEAD according to what is in ".gitmodules":
> >> # with Trevor's patch 'submodule.<module>.branch' set means attached,
> >> # unset means detached
> >> $ git submodule head --reset <module>
> >
> > To me this reads “always detach HEAD” (because it unsets
> > submodule.<name>.branch, and submodule.<name>.branch unset means
> > detached).
> 
> I disagree: this would remove only the value in ".git/config". If the
> value is till present in ".gitmodules", as I wrote above, the behavior
> of what is in the index should be respected as for the other
> properties. Also it gives a nice meaning to a switch like --reset :
> return to how it was before.

Ah, that makes more sense.  I had confused .git/config with
“.gitmodules and .git/config”.

> >> NOTE: feature branch part!
> >>
> >> # Set ".gitmodules" 'submodule.<module>.branch' to <branch>
> >> $ git submodule head -b <branch> --attach --index <module>
> >>
> >> # Unset ".gitmodules" 'submodule.<module>.branch'
> >> $ git submodule head --reset --index <module>
> >> ---------------------------------------------------------------------
> >
> > These are just manipulating .gitmodules.  I think we also need
> > per-superproject-branch configs under the superproject's .git/ for
> > developer overrides.
> 
> I disagree: in my idea the --index switch is a maintainer only command
> to modify the behavior of the developers and touch only indexed files
> (.gitmodules, or create a new submodule branch). It expressly don't
> touch .git/config.

Something that just touches the config files is syntactic sugar, so I
avoided a more detailed review and moved on to address what I saw as a
more fundamental issue (preferred submodule local branches on a
per-superproject-branch level).

Here's a detailed workflow for the {my-feature, my-feature, master}
example I roughed out before [5].

  # create the subproject
  mkdir subproject &&
  (
    cd subproject &&
    git init &&
    echo 'Hello, world' > README &&
    git add README &&
    git commit -m 'Subproject v1'
  ) &&
  # create the superproject
  mkdir superproject
  (
    cd superproject &&
    git init &&
    git submodule add ../subproject submod &&
    git config -f .gitmodules submodule.submod.update merge &&
    git commit -am 'Superproject v1' &&
    ( # 'submodule update' doesn't look in .gitmodules (yet [6]) for a
      # default update mode.  Copy submodule.submod.update over to
      # .git/config
      git submodule init
    )
  ) &&
  # start a feature branch on the superproject
  (
    cd superproject &&
    #git checkout -b my-feature --recurse-submodules &&
    ( # 'git submodule checkout --recurse-submodules' doesn't exist yet, so...
      git checkout -b my-feature &&
      git config -f .gitmodules submodule.submod.local-branch my-feature &&
      cd submod &&
      git checkout -b my-feature
    ) &&
    (
      cd submod &&
      echo 'Add the subproject side of this feature' > my-feature &&
      git add my-feature &&
      git commit -m 'Add my feature to the subproject'
    ) &&
    echo 'Add the superproject side of this feature' > my-feature &&
    git add my-feature &&
    git commit -m 'Add the feature to the superproject'
  ) &&
  # meanwhile, the subproject has been advancing
  (
    cd subproject &&
    echo 'Goodbye, world' >> README &&
    git commit -am 'Subproject v2'
  ) &&
  # we need to get that critical advance into the superproject quick!
  (
    cd superproject &&
    # update the master branch
    #git checkout --recurse-submodules master
    ( # 'git checkout --recurse-submodules' doesn't exist yet [2,3].
      # Even with that patch, 'git checkout' won't respect
      # submodule.<name>.local-branch without further work.
      git checkout master &&
      cd submod &&
      git checkout master  # don't pull in our my-feature work
    )
    git submodule update --remote &&
    git commit -am 'Catch submod up with Subproject v2' &&
    # update the my-feature branch
    git checkout my-feature
    ( # 'git checkout' doesn't mess with submodules
      cd submod &&
      git checkout my-feature
    )
    git submodule update --remote &&
    git commit -am 'Catch submod up with Subproject v2' &&
    # what does the history look like?
    (
      cd submod &&
      git --no-pager log --graph --date-order --oneline --decorate --all
      # *   3a22cef (HEAD, my-feature) Merge commit 'd53958b18277ce5bd6c734e9597a69bb878b31e1' into my-feature
      # |\  
      # * | 8322dcc Add my feature to the subproject
      # | * d53958b (origin/master, origin/HEAD, master) Subproject v2
      # |/  
      # * 9813010 Subproject v1
    ) &&
    git ls-tree master submod &&
    # 160000 commit d53958b18277ce5bd6c734e9597a69bb878b31e1  submod
    git ls-tree my-feature submod
    # 160000 commit 3a22cef30db57f1b89251f3e434fa0bd0f1b99a2  submod
  )
  git --version
  # git version 1.8.3.2

The currently-ugly bits could be fixed with:

* 'git submodule update' falling back on .gitmodules for
  submodule.<name>.update [6].
* 'git submodule checkout -b my-feature --recurse-submodules' should
  checkout the submodule.<name>.local-branch configured for the
  super-project's my-feature branch (but only if that wouldn't destroy
  some current submodule information).  This would build on work in
  Jens and Jonathans' branch [2,3].

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240127
[2]: http://article.gmane.org/gmane.comp.version-control.git/240117
[3]: http://thread.gmane.org/gmane.comp.version-control.git/239695
[4]: http://article.gmane.org/gmane.comp.version-control.git/240178
[5]: http://article.gmane.org/gmane.comp.version-control.git/240190
[6]: http://article.gmane.org/gmane.comp.version-control.git/239246

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Preferred local submodule branches
  2014-01-08  3:47                         ` Preferred local submodule branches W. Trevor King
@ 2014-01-08  4:06                           ` W. Trevor King
  2014-01-09  6:17                             ` [RFC v3 0/4] " W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-08  4:06 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Heiko Voigt, git, Jens Lehmann, Jonathan Nieder, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 1254 bytes --]

On Tue, Jan 07, 2014 at 07:47:08PM -0800, W. Trevor King wrote:
>     #git checkout --recurse-submodules master
>     ( # 'git checkout --recurse-submodules' doesn't exist yet [2,3].
>       # Even with that patch, 'git checkout' won't respect
>       # submodule.<name>.local-branch without further work.
>       git checkout master &&
>       cd submod &&
>       git checkout master  # don't pull in our my-feature work
>     )
>     git submodule update --remote &&
>     git commit -am 'Catch submod up with Subproject v2' &&
>     # update the my-feature branch
>     git checkout my-feature
>     ( # 'git checkout' doesn't mess with submodules
>       cd submod &&
>       git checkout my-feature
>     )

Oops, the my-feature checkout block should have been:

    #git checkout --recurse-submodules my-feature
    ( # 'git checkout --recurse-submodules' doesn't exist yet...
      git checkout my-feature &&
      cd submod &&
      git checkout my-feature
    )

mirroring the earlier master checkout block.  Sorry for the sloppy
editing.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-08  1:05                                         ` W. Trevor King
  2014-01-08  2:12                                           ` Francesco Pretto
@ 2014-01-08 23:07                                           ` Francesco Pretto
  2014-01-09  0:03                                             ` W. Trevor King
  2014-01-08 23:54                                           ` Re: [RFC v2] submodule: Respect requested branch on all clones Francesco Pretto
  2 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-08 23:07 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann

2014/1/8 W. Trevor King <wking@tremily.us>:
> To elaborate the idea I sketched out here [2], say
> you want:
>
>   Superproject branch  Submodule branch  Upstream branch
>   ===================  ================  ===============
>   master               master            master
>   super-feature        master            master
>   my-feature           my-feature        master
>   other-feature        other-feature     other-feature
>
> That's only going to work with per-superproject-branch configs for
> both the local and remote branches.  Using the same name for both
> local and remote branches does not work.
>

After long thoughts, I think your idea about a local branch with a
differently named remote branch looks interesting but I would be
extremely cautious to add a ' submodule.<name>.local-branch' now. Do
we have a similar mechanism on regular repository clones? We can clone
and switch to a branch other than "master" by default, but can we also
have a different remote by default? If we don't have it, we shouldn't
add it first on submodules, as there's the chance the feature never
get coupled on  the regular clones.

Also, I think you fear too much that this can't be added also later.

I think you should pursue your initial proposal of "--branch means
attached" to get it upstream first. It's alone, IMO, a great
improvement on submodules.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-08  1:05                                         ` W. Trevor King
  2014-01-08  2:12                                           ` Francesco Pretto
  2014-01-08 23:07                                           ` Francesco Pretto
@ 2014-01-08 23:54                                           ` Francesco Pretto
  2014-01-09  0:23                                             ` W. Trevor King
  2 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-08 23:54 UTC (permalink / raw)
  To: W. Trevor King; +Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann

2014/1/8 W. Trevor King <wking@tremily.us>:
> I also prefer 'checkout' to 'head', because 'checkout'
> already exists in non-submodule Git for switching between local
> branches.
>

Reasons I would loosely support 'git submodule checkout'
--------------------------------------------------------------------------------
1)  It's true that 'git submodule checkout' would also often run 'git checkout'.

Reasons, as an user, I seriously would *not* like 'git submodule checkout'
-----------------------------------------------------------------------------------------------------
1) 'git submodule checkout' would also touch '.git/config' and
'.gitmodules', and I don't like much the idea of a 'checkout' command
touching config files. It looks dirty.
2) Having 'git checkout', 'git checkout --recurse-submodules' and
finally 'git submodule checkout' is too much for me.

Also, in my proposal, 'git submodule [tobedecided] --attach' would
also merge orphaned commits by default, and 'checkout' is not about
merge.

Reasons I would fervently support 'git submodule head'
----------------------------------------------------------------------------
1) It tells immediately that this command is about HEAD of the
submodule, and will take care of it. Newcomers would loveit if they
don't like their HEAD state;
2) "head" is unspecific enough to admit it can also touch
'.git/config' and '.gitmodules'.

Said this, it seems Heiko[1] proposed a similar syntax and the only
difference was about names, not behavior of the command to be added
(if we eventually take this path, ofc).

> On Wed, Jan 08, 2014 at 01:17:49AM +0100, Francesco Pretto wrote:
>> # Attach the submodule HEAD to <branch>.
>> # Also set ".git/config" 'submodule.<module>.branch' to <branch>
>> $ git submodule head -b <branch> --attach <module>
>
> I prefer submodule.<name>.local-branch for the submodule's local
> branch name.

I think this was still part of your original misunderstanding about my
"git submodule head". This command would touch 'branch' property
anyway because '-b <branch>' would still be the remote branch, even in
the case you have a 'local-branch' property (maybe to be coupled here
with a --local-branch <local-branch> switch).

Greetings,
Francesco

[1] http://marc.info/?l=git&m=138913435216349&w=2

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-08 23:07                                           ` Francesco Pretto
@ 2014-01-09  0:03                                             ` W. Trevor King
  2014-01-09  1:09                                               ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  0:03 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 3215 bytes --]

On Thu, Jan 09, 2014 at 12:07:56AM +0100, Francesco Pretto wrote:
> After long thoughts, I think your idea about a local branch with a
> differently named remote branch looks interesting but I would be
> extremely cautious to add a ' submodule.<name>.local-branch' now. Do
> we have a similar mechanism on regular repository clones?

The default upstream branch is currently configured with
branch.<name>.merge.  Earlier [1], I suggested we piggyback on this
for the submodule's upstream branches, and only use
submodule.<name>.branch for the initial setup.  That would allow
developers to configure upstreams on a per-submodule-branch basis.  We
should probably fall back to submodule.<name>.branch if the submodule
does not have a branch.<name>.merge configured.

However, submodule.<name>.local-branch has nothing to do with remote
repositories or tracking branches.  It just selects the preferred
submodule branch for the superproject branch.  This will only work for
in-tree .gitmodules configs (since the contents are per-branch).  I
don't have a good idea for where local overrides would live.  We'd
want something like
branch.<superproject-branch>.submodule.<submodule-name>.local-branch:

  [branch "my-feature"]
        remote = origin
        merge = refs/heads/my-feature
        [submodule "submod"]
            local-branch = "my-feature"

and I don't think Git's config supports such nesting.

> We can clone and switch to a branch other than "master" by default,
> but can we also have a different remote by default?

Sure, the existing submodule.<name>.url defines the remote repository,
and the existing submodule.<name>.branch defines the remote branch.
The existing code even sets up remote.origin.url and
branch.<name>.merge (to the matching refs/heads/<name>) in the the
submodule's config.

> Also, I think you fear too much that this can't be added also later.

We can add submodule.<name>.local-branch support later, but I see no
reason not to add it on top of Jens and Jonathan's current submodule
checkout work.  With increasingly robust submodule checkout support in
the core, I expect the amount of update logic stored in
git-submodule.sh will decrease significantly.

> I think you should pursue your initial proposal of "--branch means
> attached" to get it upstream first. It's alone, IMO, a great
> improvement on submodules.

I can resuscitate that if folks want, but Heiko felt that my initial
consolidation didn't go far enough [2].  If it turns out that we're ok
with the current level of consolidation, would you be ok with
"non-checkout submodule.<name>.update" as the trigger [3]?  I think
that adding a halfway step between the current status and full(ish)
submodule.<name>.local-branch support is just going to confuse people
;).

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240164
[2]: http://article.gmane.org/gmane.comp.version-control.git/239968
[3]: http://article.gmane.org/gmane.comp.version-control.git/239973

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-08 23:54                                           ` Re: [RFC v2] submodule: Respect requested branch on all clones Francesco Pretto
@ 2014-01-09  0:23                                             ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  0:23 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 1191 bytes --]

On Thu, Jan 09, 2014 at 12:54:54AM +0100, Francesco Pretto wrote:
> 2) Having 'git checkout', 'git checkout --recurse-submodules' and
> finally 'git submodule checkout' is too much for me.

Agreed.  Since 'git checkout' already exists and 'git checkout
--recurse-submodules' is close [1,2], I think that means we should
drop this and start arguing about adjusting 'git checkout
--recurse-submodules' to checkout branches as well ;).

> Also, in my proposal, 'git submodule [tobedecided] --attach' would
> also merge orphaned commits by default, and 'checkout' is not about
> merge.

And that's good.  Bailing with “you have orphaned commits, which you
should integrate them with $some_integration_command before checking
out a different branch” is better than having overlapping
responsibilities between the checkout command and the integration
command.

Cheers,
Trevor

[1]: http://thread.gmane.org/gmane.comp.version-control.git/239695
[2]: http://article.gmane.org/gmane.comp.version-control.git/240117

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09  0:03                                             ` W. Trevor King
@ 2014-01-09  1:09                                               ` Francesco Pretto
  2014-01-09  2:22                                                 ` W. Trevor King
  2014-01-09  8:31                                                 ` Jens Lehmann
  0 siblings, 2 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-09  1:09 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann, Jonathan Nieder

2014/1/9 W. Trevor King <wking@tremily.us>:
>
> However, submodule.<name>.local-branch has nothing to do with remote
> repositories or tracking branches.

My bad: this means the feature is still not entirely clear to me.

>
>   [branch "my-feature"]
>         remote = origin
>         merge = refs/heads/my-feature
>         [submodule "submod"]
>             local-branch = "my-feature"
>
> and I don't think Git's config supports such nesting.
>

Aesthetically, It doesn't look very nice.

>
> I can resuscitate that if folks want, but Heiko felt that my initial
> consolidation didn't go far enough [2].  If it turns out that we're ok
> with the current level of consolidation, would you be ok with
> "non-checkout submodule.<name>.update" as the trigger [3]?

For me it was ok with what you did:
-------------------------------------------------
if "just_cloned" and "config_branch"
then
     !git reset --hard -q"
fi
-------------------------------------------------

So yes: at the first clone 'checkout' keeps attached HEAD, while
'merge' and 'rebase' attach to the branch.
If it's not the first clone, you should take no action (and your
original patch was ok about this).

>  I think
> that adding a halfway step between the current status and full(ish)
> submodule.<name>.local-branch support is just going to confuse people

Well, for now you got some success in confusing me with this "local-branch" :)

At certain point  you may ask maintainers what are the accepted
features (because all these debates should be about getting, or not
getting, endorsement about something) and finalize a patch so people
can further review.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09  1:09                                               ` Francesco Pretto
@ 2014-01-09  2:22                                                 ` W. Trevor King
  2014-01-09  8:31                                                 ` Jens Lehmann
  1 sibling, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  2:22 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Heiko Voigt, Junio C Hamano, Git, Jens Lehmann, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 1368 bytes --]

On Thu, Jan 09, 2014 at 02:09:37AM +0100, Francesco Pretto wrote:
> 2014/1/9 W. Trevor King <wking@tremily.us>:
> >   [branch "my-feature"]
> >         remote = origin
> >         merge = refs/heads/my-feature
> >         [submodule "submod"]
> >             local-branch = "my-feature"
> >
> > and I don't think Git's config supports such nesting.
> 
> Aesthetically, It doesn't look very nice.

The INI syntax does not lend itself to easy nesting, but I'm pretty
sure some mapping from (<superproject-branch>, <submodule-name>) to
<submodule-local-branch-name> is what we need for submodule checkouts.
I'm just not sure where local overides to the per-branch .gitmodules
should live.  We could turn it around, and store:

  [superproject "<superproject-branch>"]
      local-branch = "<submodule-local-branch-name>"

in .git/modules/<submodule-name>/config, with the UI:

  $ cd submodule
  $ git config superproject.<superproject-branch>.local-branch = <submodule-branch>

Not beautiful, but maybe a bit more palatable, and already supported
by Git's current config parser.  That's enough that I can work up a
patch that will hopefully clarify my position ;).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [RFC v3 0/4] Preferred local submodule branches
  2014-01-08  4:06                           ` W. Trevor King
@ 2014-01-09  6:17                             ` W. Trevor King
  2014-01-09  6:17                               ` [RFC v3 1/4] submodule: Add helpers for configurable local branches W. Trevor King
                                                 ` (4 more replies)
  0 siblings, 5 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  6:17 UTC (permalink / raw)
  To: Git
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jens Lehmann,
	Jonathan Nieder, W. Trevor King

From: "W. Trevor King" <wking@tremily.us>

In another branch of the submodule thread Francesco kicked off, I
mentioned that we could store the preferred local submodule branch on
a per-superbranch level if we used the
.git/modules/<submodule-name>/config for local overrides [1].  Here's
a patch series that greatly extends my v2 "submodule: Respect
requested branch on all clones" series [2] to also support automatic,
recursive submodule checkouts, as I outlined here [3].  After this
series, I can get through:

  # create the subproject
  mkdir subproject &&
  (
    cd subproject &&
    git init &&
    echo 'Hello, world' > README &&
    git add README &&
    git commit -m 'Subproject v1'
  ) &&
  # create the superproject
  mkdir superproject
  (
    cd superproject &&
    git init &&
    git submodule add ../subproject submod &&
    git config -f .gitmodules submodule.submod.update merge &&
    git commit -am 'Superproject v1' &&
    ( # 'submodule update' doesn't look in .gitmodules (yet [4]) for a
      # default update mode.  Copy submodule.submod.update over to
      # .git/config
      git submodule init
    )
  ) &&
  # start a feature branch on the superproject
  (
    cd superproject &&
    #git checkout -b my-feature --recurse-submodules &&
    ( # 'git submodule checkout --recurse-submodules' doesn't exist yet, so...
      git checkout -b my-feature &&
      git submodule checkout -b --gitmodules
    ) &&
    (
      cd submod &&
      echo 'Add the subproject side of this feature' > my-feature &&
      git add my-feature &&
      git commit -m 'Add my feature to the subproject'
    ) &&
    echo 'Add the superproject side of this feature' > my-feature &&
    git add my-feature &&
    git commit -am 'Add the feature to the superproject'
  ) &&
  # meanwhile, the subproject has been advancing
  (
    cd subproject &&
    echo 'Goodbye, world' >> README &&
    git commit -am 'Subproject v2'
  ) &&
  # we need to get that critical advance into the superproject quick!
  (
    cd superproject &&
    # update the master branch
    #git checkout --recurse-submodules master
    ( # 'git checkout --recurse-submodules' doesn't exist yet [5,6].
      # Even with that patch, 'git checkout' won't respect
      # submodule.<name>.local-branch without further work.
      git checkout master &&
      git submodule checkout
    ) &&
    git submodule update --remote &&
    git commit -am 'Catch submod up with Subproject v2' &&
    # update the my-feature branch
    #git checkout --recurse-submodules my-feature &&
    ( # 'git checkout --recurse-submodules' doesn't exist yet [5,6].
      git checkout my-feature &&
      git submodule checkout
    ) &&
    git submodule update --remote &&
    git commit -am 'Catch submod up with Subproject v2' &&
    # what does the history look like?
    (
      cd submod &&
      git --no-pager log --graph --date-order --oneline --decorate --all
      # *   16d9e3e (HEAD, my-feature) Merge commit 'f5e134d5747ee4a206e96d8c017f92f5b29a07f3' into my-feature
      # |\  
      # | * f5e134d (origin/master, origin/HEAD, master) Subproject v2
      # * | 0a1cd07 Add my feature to the subproject
      # |/  
      # * c2d32ba Subproject v1
    ) &&
    printf 'master: ' &&
    git ls-tree master submod &&
    # master: 160000 commit f5e134d5747ee4a206e96d8c017f92f5b29a07f3  submod
    printf 'my-feature: ' &&
    git ls-tree my-feature submod
    # my-feature: 160000 commit 16d9e3ea2fb57e7a166587203abdb328f90895d1  submod
  )
  git --version
  # git version 1.8.5.2.237.g01c62c6

I think the first three patches are fairly solid.  The last one gets
through the above script, but I'd need a more thorough test suite
before I trusted it.  I tried to be detailed in the commit messages,
but of course, we'd want some user-facing documentation if we actually
merged something like this series.  I'm sending it to the list mostly
to explain my current views and re-focus debate [1].

[1]: http://article.gmane.org/gmane.comp.version-control.git/240240
[2]: http://article.gmane.org/gmane.comp.version-control.git/239967
[3]: http://article.gmane.org/gmane.comp.version-control.git/240192
[4]: http://article.gmane.org/gmane.comp.version-control.git/239246
[5]: http://thread.gmane.org/gmane.comp.version-control.git/239695
[6]: http://article.gmane.org/gmane.comp.version-control.git/240117

Cheers,
Trevor

W. Trevor King (4):
  submodule: Add helpers for configurable local branches
  submodule: Teach 'update' to preserve local branches
  submodule: Teach 'add' about a configurable local-branch
  submodule: Add a new 'checkout' command

 git-submodule.sh | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 138 insertions(+), 14 deletions(-)

-- 
1.8.5.2.237.g01c62c6

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [RFC v3 1/4] submodule: Add helpers for configurable local branches
  2014-01-09  6:17                             ` [RFC v3 0/4] " W. Trevor King
@ 2014-01-09  6:17                               ` W. Trevor King
  2014-01-09  6:17                               ` [RFC v3 2/4] submodule: Teach 'update' to preserve " W. Trevor King
                                                 ` (3 subsequent siblings)
  4 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  6:17 UTC (permalink / raw)
  To: Git
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jens Lehmann,
	Jonathan Nieder, W. Trevor King

From: "W. Trevor King" <wking@tremily.us>

There are three branches that submodule folks usually care about:

1. The linked $sha1 in the superproject (set explicitly for every
   superproject commit, and thus for every superproject branch).
2. The remote-tracking submodule.<name>.branch that tracks a branch in
   upstream submodule.<name>.url repository.
3. The submodule's locally checked out branch, which we currently let
   the developer setup by hand, which is integrated with one of the
   other two branches by non-checkout update modes.

Git is currently a bit weak on conveniently handling branch #3.  "Just
use what the developer has setup" works well for many basic workflows,
but falls short for:

* Cloning-updates, where we currently always setup a detached HEAD.
  This is easy to fix if you accept submodule.<name>.branch or the
  branch pointed to by the cloned repository's HEAD as a guess, but
  this conflates branch #2 and branch #3, which may confuse users.

* Workflows where the preferred #3 branch depends on the superproject
  branch.  For example, if the remote subproject has only a master
  branch, but the local superproject needs to develop several
  submodule feature branches simultaneously, you can have a situation
  like this:

    Superproject branch  Submodule branch  Subproject branch
    ===================  ================  =================
    master               master            master
    feature-1            feature-1         master
    feature-2            feature-2         master
    feature-3            feature-2         master

In order to checkout the appropriate submodule branch for a given
superproject branch, we need a way to specify the preferred submodule
branch for a given superproject branch.  This commit adds two helper
functions:

* get_current_branch, to determine which superproject branch you're
  on, and
* get_local_branch, to determine the preferred submodule branch for
  that superproject branch.

The lookup chain for the local-branch is:

1. superproject.<superproject-branch>.local-branch in the submodule's
   config (superproject/.git/modules/<submodule-name>/config).  This
   is where the developer can store local per-superproject-branch
   overrides (e.g. if they wanted to use submodule branch feature-1
   with superproject branch feature-3).
2. submodule.<submodule-name>.local-branch in the superproject's
   config.  This is where the developer can store local
   cross-superproject-branch overrides (e.g. if they wanted to use
   submodule branch master for any superproject branch that didn't
   have a per-superproject-branch override).
3. submodule.<submodule-name>.local-branch in the superproject's
   .gitmodules file.  Because the gitmodules file is stored in the
   superproject's versioned tree, it is automatically
   superproject-branch-specific.  For example:

     $ git cat-file -p feature-1:.gitmodules
     ...
     [submodule "submod"]
         ...
         local-branch = feature-1
     $ git cat-file -p feature-3:.gitmodules
     ...
     [submodule "submod"]
         ...
         local-branch = feature-2

   this is where the project-wide defaults are setup and shared
   between developers.
4. The default local-branch is 'master'.

The new get_local_branch function handles the first step in this
chain.  The next two steps are already covered by the existing
get_submodule_config.
---
 git-submodule.sh | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/git-submodule.sh b/git-submodule.sh
index 2677f2e..56fc3f1 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -220,6 +220,39 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
+#
+# Print a submodule's configured local branch name
+#
+# $1 = superproject branch
+# $2 = default (from the superproject's .gitmodules)
+#
+# To be called from the submodule root directory.
+#
+get_local_branch ()
+{
+	superproject_branch="$1"
+	default="${2:-master}"
+	if test -z "${superproject_branch}"
+	then
+		value=""
+	else
+		value=$(git config superproject."$superproject_branch".local-branch)
+	fi
+	printf '%s' "${value:-$default}"
+}
+
+#
+# Print the currently checked out branch of the current repository
+#
+# $1 = default
+#
+get_current_branch ()
+{
+	default="$1"
+	branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) ||
+	branch=""
+	printf '%s' "${branch:-$default}"
+}
 
 #
 # Map submodule path to submodule name
-- 
1.8.5.2.237.g01c62c6

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [RFC v3 2/4] submodule: Teach 'update' to preserve local branches
  2014-01-09  6:17                             ` [RFC v3 0/4] " W. Trevor King
  2014-01-09  6:17                               ` [RFC v3 1/4] submodule: Add helpers for configurable local branches W. Trevor King
@ 2014-01-09  6:17                               ` W. Trevor King
  2014-01-09  6:17                               ` [RFC v3 3/4] submodule: Teach 'add' about a configurable local-branch W. Trevor King
                                                 ` (2 subsequent siblings)
  4 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  6:17 UTC (permalink / raw)
  To: Git
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jens Lehmann,
	Jonathan Nieder, W. Trevor King

From: "W. Trevor King" <wking@tremily.us>

There's no sense in setting up a local branch if we're just going to
go back to a detached HEAD with every checkout-mode update.  This
commit replaces the checkout with a reset, updating whatever the
locally checked out branch (or detached HEAD) happens to be.  While it
is tempting to checkout a new local-branch here (as we did after the
clone), it's more consistent to follow the lead of the other update
modes and just use the currently checked out branch.
---
 git-submodule.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 56fc3f1..c5ea7bd 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -930,9 +930,9 @@ 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'")"
+				command="git reset --hard -q"
+				die_msg="$(eval_gettext "Unable to reset branch to '\$sha1' in submodule path '\$displaypath'")"
+				say_msg="$(eval_gettext "Submodule path '\$displaypath': reset branch to '\$sha1'")"
 				;;
 			esac
 
-- 
1.8.5.2.237.g01c62c6

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [RFC v3 3/4] submodule: Teach 'add' about a configurable local-branch
  2014-01-09  6:17                             ` [RFC v3 0/4] " W. Trevor King
  2014-01-09  6:17                               ` [RFC v3 1/4] submodule: Add helpers for configurable local branches W. Trevor King
  2014-01-09  6:17                               ` [RFC v3 2/4] submodule: Teach 'update' to preserve " W. Trevor King
@ 2014-01-09  6:17                               ` W. Trevor King
  2014-01-15  0:18                                 ` Francesco Pretto
  2014-01-09  6:17                               ` [RFC v3 4/4] submodule: Add a new 'checkout' command W. Trevor King
  2014-01-12  1:08                               ` Tight submodule bindings (was: Preferred local submodule branches) W. Trevor King
  4 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  6:17 UTC (permalink / raw)
  To: Git
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jens Lehmann,
	Jonathan Nieder, W. Trevor King

From: "W. Trevor King" <wking@tremily.us>

This patch teaches 'git submodule add' to look for a preferred
local-branch, and to checkout that branch after the initial clone.
The local branch will always point at the commit checked out by the
internal 'git clone' operation.  For example:

  $ git submodule add git://example.com/subproject.git submod

will checkout the branch pointed to by the cloned repository's HEAD,
and call the local branch 'master'.

  $ git submodule add -b my-feature git://example.com/subproject.git submod

will checkout the branch pointed to by the cloned repository's
my-feature, and *still* call the local branch 'master'.

'git submodule add' does not always make an initial clone (e.g. if a
git repository already exists at the target path).  In cases where
'git submodule add' does not clone a repository, we just leave the
local branch alone.

This commit also shifts the post-clone branch checkout logic from
cmd_add to module_clone, so it can be shared with cmd_update.  The
previous code only checked out the requested branch in cmd_add but not
in cmd_update; this left the user on a detached HEAD after an update
initially cloned, and subsequent updates kept the HEAD detached,
unless the user moved to the desired branch himself.  Now, unless the
user explicitly asks to work on a detached HEAD, subsequent updates
all happen on the specified branch, which matches the end-user
expectation much better.
---
 git-submodule.sh | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index c5ea7bd..7cee0bf 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -339,7 +339,19 @@ 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")
+	superproject_branch=$(get_current_branch)
+	default_local_branch=$(get_submodule_config "$sm_name" local-branch)
+	(
+		clear_local_git_env
+		cd "$sm_path" &&
+		GIT_WORK_TREE=. git config core.worktree "$rel/$b" &&
+		local_branch=$(get_local_branch "${superproject_branch}" "${default_local_branch}") &&
+		# ash fails to wordsplit ${branch:+-b "$branch"...}
+		case "$branch" in
+		'') git checkout -f -q -B "$local_branch" ;;
+		?*) git checkout -f -q -B "$local_branch" "origin/$branch" ;;
+		esac
+	) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
 }
 
 isnumber()
@@ -503,15 +515,6 @@ Use -f if you really want to add it." >&2
 			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'")"
 	fi
 	git config submodule."$sm_name".url "$realrepo"
 
-- 
1.8.5.2.237.g01c62c6

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [RFC v3 4/4] submodule: Add a new 'checkout' command
  2014-01-09  6:17                             ` [RFC v3 0/4] " W. Trevor King
                                                 ` (2 preceding siblings ...)
  2014-01-09  6:17                               ` [RFC v3 3/4] submodule: Teach 'add' about a configurable local-branch W. Trevor King
@ 2014-01-09  6:17                               ` W. Trevor King
  2014-01-12  1:08                               ` Tight submodule bindings (was: Preferred local submodule branches) W. Trevor King
  4 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-09  6:17 UTC (permalink / raw)
  To: Git
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jens Lehmann,
	Jonathan Nieder, W. Trevor King

From: "W. Trevor King" <wking@tremily.us>

This borrows a good deal of the cmd_foreach logic to iterate through
submodules (potentially recursively), checking out the preferred local
branch for each submodule (as appropriate for the current superproject
branch).  Ideally, this logic would be bundled into the forthcoming:

  $ git checkout --recurse-submodules

logic that Jens Lehmann and Jonathan Nieder are working up in C.
Until that happens, you can simulate that checkout behaviour with:

  $ git checkout some-branch
  $ git submodule checkout --recursive

The relevant superproject branch used to determine the preferred
submodule branch is the submodules immediate parent, not the top-level
superproject.  For example, with the following submodule inheritance:

  superproject (branch super-1)
  `-- midproject (branch mid-1)
      `-- subproject (branch sub-1)

The .gitmodules configs should look like (assuming there are no local
overrides):

  $ git cat-file -p super-1:.gitmodules
  ...
  [submodule "midproject"]
       ...
       local-branch = mid-1
  $ cd midproject
  $ git cat-file -p mid-1:.gitmodules
  ...
  [submodule "subproject"]
       ...
       local-branch = sub-1

The super-1 branch need not even exist in the midproject repository.

This commit handles branch switches inside existing submodules.
Handling (or even detecting) submodules that are created and destroyed
or moving submodules that change path between the initial and final
superproject branch is put off to future patches.

I also added minimal support for initial branch creation.  Create your
initial branch with:

  $ git checkout -b my-feature
  $ git submodule checkout --recursive -b --gitmodules

which will create new 'my-feature' branches in each submodule (or die
trying).  It will also save 'my-feature' to the superproject's
.gitmodules' submodule.<name>.local-branch for future checkouts.
After setting up a branch like this, future checkouts (from some other
branch) will look like:

  $ git checkout my-feature
  $ git submodule checkout --recursive
---
 git-submodule.sh | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 7cee0bf..16cebb1 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -6,6 +6,7 @@
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
+   or: $dashless [--quiet] checkout [--recursive] [-b|-B] [--gitmodules] [--] [<path>...]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
@@ -36,6 +37,10 @@ update=
 prefix=
 custom_name=
 depth=
+create_new_branch=
+checkout_options=
+save_in_gitmodules=
+default_local_branch="master"
 
 # The function takes at most 2 arguments. The first argument is the
 # URL that navigates to the submodule origin repo. When relative, this URL
@@ -532,6 +537,89 @@ Use -f if you really want to add it." >&2
 }
 
 #
+# Checkout the appropriate local branch for each submodule
+#
+cmd_checkout()
+{
+	# parse $args after "submodule ... checkout".
+	while test $# -ne 0
+	do
+		case "$1" in
+		-q|--quiet)
+			GIT_QUIET=1
+			;;
+		--recursive)
+			recursive=1
+			;;
+		-b|-B)
+			checkout_options="${checkout_options} $1"
+			create_new_branch=1
+			;;
+		--gitmodules)
+			save_in_gitmodules=1
+			;;
+		--)
+			shift
+			break
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
+	toplevel=$(pwd)
+
+	superproject_branch=$(get_current_branch)
+	if test -n "$create_new_branch"
+	then
+		default_local_branch="${superproject_branch}"
+	fi
+
+	# dup stdin so that it can be restored when running the external
+	# command in the subshell (and a recursive call to this function)
+	exec 3<&0
+
+	module_list "$@" |
+	while read mode sha1 stage sm_path
+	do
+		die_if_unmatched "$mode"
+		name=$(module_name "$sm_path") || exit
+		displaypath=$(relative_path "$prefix$sm_path")
+		if test -e "$sm_path"/.git
+		then
+			say "$(eval_gettext "Entering '\$displaypath'")"
+			name=$(module_name "$sm_path")
+			super_local_branch=$(get_submodule_config "$name" local-branch "${default_local_branch}")
+			(
+				prefix="$prefix$sm_path/"
+				clear_local_git_env
+				cd "$sm_path" &&
+				local_branch=$(get_local_branch "${superproject_branch}" "${super_local_branch}") &&
+				git checkout ${checkout_options} "${local_branch}" &&
+				if test -n "$recursive"
+				then
+					cmd_checkout
+				fi
+			) <&3 3<&- ||
+			die "$(eval_gettext "Stopping at '\$displaypath'; script returned non-zero status.")"
+			if test -n "${save_in_gitmodules}"
+			then
+				(
+					local_branch=$(clear_local_git_env && cd "$sm_path" && get_current_branch) &&
+					git config -f .gitmodules submodule."${name}".local-branch "${local_branch}"
+				) ||
+				die "$(eval_gettext "Could not save local-branch for '\$displaypath'")"
+			fi
+		fi
+	done
+}
+
+#
 # Execute an arbitrary command sequence in each checked out
 # submodule
 #
@@ -1378,7 +1466,7 @@ cmd_sync()
 while test $# != 0 && test -z "$command"
 do
 	case "$1" in
-	add | foreach | init | deinit | update | status | summary | sync)
+	add | checkout | foreach | init | deinit | update | status | summary | sync)
 		command=$1
 		;;
 	-q|--quiet)
-- 
1.8.5.2.237.g01c62c6

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09  1:09                                               ` Francesco Pretto
  2014-01-09  2:22                                                 ` W. Trevor King
@ 2014-01-09  8:31                                                 ` Jens Lehmann
  2014-01-09 17:32                                                   ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Jens Lehmann @ 2014-01-09  8:31 UTC (permalink / raw)
  To: Francesco Pretto, W. Trevor King
  Cc: Heiko Voigt, Junio C Hamano, Git, Jonathan Nieder

Am 09.01.2014 02:09, schrieb Francesco Pretto:
> 2014/1/9 W. Trevor King <wking@tremily.us>:
>>
>> However, submodule.<name>.local-branch has nothing to do with remote
>> repositories or tracking branches.
> 
> My bad: this means the feature is still not entirely clear to me.
> 
>>
>>   [branch "my-feature"]
>>         remote = origin
>>         merge = refs/heads/my-feature
>>         [submodule "submod"]
>>             local-branch = "my-feature"
>>
>> and I don't think Git's config supports such nesting.
>>
> 
> Aesthetically, It doesn't look very nice.

And I'm not sure we even need that. What's wrong with having the
branch setting in the .gitmodules file of the my-feature branch?
The only problem I can imagine is accidentally merging that into
a branch where that isn't set, but that could be solved by a merge
helper for the .gitmodules file.

>> I can resuscitate that if folks want, but Heiko felt that my initial
>> consolidation didn't go far enough [2].  If it turns out that we're ok
>> with the current level of consolidation, would you be ok with
>> "non-checkout submodule.<name>.update" as the trigger [3]?
> 
> For me it was ok with what you did:
> -------------------------------------------------
> if "just_cloned" and "config_branch"
> then
>      !git reset --hard -q"
> fi
> -------------------------------------------------
> 
> So yes: at the first clone 'checkout' keeps attached HEAD, while
> 'merge' and 'rebase' attach to the branch.

It have the impression that attaching the head to the given branch
for merge and rebase might be the sensible thing to do, but it
would be great to hear from users of merge and rebase if that
would break anything for them in their current use cases for these
settings.

> If it's not the first clone, you should take no action (and your
> original patch was ok about this).

I'm not sure this is the right thing to do, after all you
configured git to follow that branch so I'd expect it to be
updated later too, no? Otherwise you might end up with an old
version of your branch while upstream is a zillion commits
ahead.

>>  I think
>> that adding a halfway step between the current status and full(ish)
>> submodule.<name>.local-branch support is just going to confuse people
> 
> Well, for now you got some success in confusing me with this "local-branch" :)
> 
> At certain point  you may ask maintainers what are the accepted
> features (because all these debates should be about getting, or not
> getting, endorsement about something) and finalize a patch so people
> can further review.

First I'd like to see a real consensus about what exactly should
happen when a branch is configured to be checked out (and if I
missed such a summary in this thread, please point me to it ;-).
And we should contrast that to the exact checkout and floating
branch use cases.

So what should happen on initial clone, later updates, updates
where the local and the remote branch diverged, when superproject
branches are merged (with and without conflicts), on a rebase in
the superproject and so on.

After that we can discuss about how to implement them (even though I
believe we won't need a new submodule command at the end of this
process, simply because if it isn't configurable we cannot teach git
checkout and friends to do that automatically for us later).

And from reading this discussion I believe we need another value for
the ignore option which only ignores changes to the SHA-1 but not to
work tree modifications of a submodule work tree relative to its HEAD
(or make that two: another one which ignores untracked files too and
only shows modification of tracked files). Otherwise users of the
floating or attached model can easily miss submodule modifications.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09  8:31                                                 ` Jens Lehmann
@ 2014-01-09 17:32                                                   ` W. Trevor King
  2014-01-09 19:23                                                     ` Jens Lehmann
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-09 17:32 UTC (permalink / raw)
  To: Jens Lehmann
  Cc: Francesco Pretto, Heiko Voigt, Junio C Hamano, Git, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 8016 bytes --]

On Thu, Jan 09, 2014 at 09:31:13AM +0100, Jens Lehmann wrote:
> Am 09.01.2014 02:09, schrieb Francesco Pretto:
> > 2014/1/9 W. Trevor King <wking@tremily.us>:
> >>
> >> However, submodule.<name>.local-branch has nothing to do with remote
> >> repositories or tracking branches.
> > 
> > My bad: this means the feature is still not entirely clear to me.
> > 
> >>
> >>   [branch "my-feature"]
> >>         remote = origin
> >>         merge = refs/heads/my-feature
> >>         [submodule "submod"]
> >>             local-branch = "my-feature"
> >>
> >> and I don't think Git's config supports such nesting.
> >>
> > 
> > Aesthetically, It doesn't look very nice.
> 
> And I'm not sure we even need that. What's wrong with having the
> branch setting in the .gitmodules file of the my-feature branch?
> The only problem I can imagine is accidentally merging that into
> a branch where that isn't set, but that could be solved by a merge
> helper for the .gitmodules file.

.gitmodules is fine so long as the config can live in the versioned
tree.  Many (all?) .gitmodules settings can be overridden in
.git/config.  However, the local-branch setting needs to be both
per-submodule and per-superproject-branch, so .git/config doesn't work
very well.  I think it's better to use something like my
.git/modules/<submodule-name>/config implementation [1] to set this
override.

This lack of per-superproject-branch overrides applies to all of the
submodule.<name>.* settings, but you're unlikely to want an
out-of-tree override for 'path' or a per-superproject-branch override
for 'url', 'ignore', 'update', or 'chRecurseSubmodules'.  Maybe folks
would want per-superproject-branch overrides to 'branch', although I'd
prefer we reuse branch.<name>.merge in the submodule's config for
that [2].

On the other hand, maybe an in-tree .gitmodules is good enough, and
folks who want a local override can just edit .gitmodules in their
local branch?  I've never felt the need to override .gitmodules myself
(for any setting), so feedback from someone who has would be useful.

> >> I can resuscitate that if folks want, but Heiko felt that my initial
> >> consolidation didn't go far enough [2].  If it turns out that we're ok
> >> with the current level of consolidation, would you be ok with
> >> "non-checkout submodule.<name>.update" as the trigger [3]?
> > 
> > For me it was ok with what you did:
> > -------------------------------------------------
> > if "just_cloned" and "config_branch"
> > then
> >      !git reset --hard -q"
> > fi
> > -------------------------------------------------
> > 
> > So yes: at the first clone 'checkout' keeps attached HEAD, while
> > 'merge' and 'rebase' attach to the branch.
> 
> It have the impression that attaching the head to the given branch
> for merge and rebase might be the sensible thing to do, but it
> would be great to hear from users of merge and rebase if that
> would break anything for them in their current use cases for these
> settings.

Which local branch would you attach to before merging?  I think 'git
submodule update' should always use the current submodule state
(attached branch or detached HEAD) [3], and we should have a separate
call that explicitly checked out the desired submodule branch [4].

> > If it's not the first clone, you should take no action (and your
> > original patch was ok about this).
> 
> I'm not sure this is the right thing to do, after all you
> configured git to follow that branch so I'd expect it to be
> updated later too, no? Otherwise you might end up with an old
> version of your branch while upstream is a zillion commits
> ahead.

Non-clone updates should not change the submodule's *local* branch
*name*.  They should change the commit that that branch references,
otherwise 'git submodule update' would be a no-op ;).

> First I'd like to see a real consensus about what exactly should
> happen when a branch is configured to be checked out (and if I
> missed such a summary in this thread, please point me to it ;-).

I don't think we have a consensus yet.  A stand-alone outline of my
current position is in my v3 RFC [5], but I don't have any buy-in yet
;).

> And we should contrast that to the exact checkout and floating
> branch use cases.

With my v3 series, there are no more detached HEADs.  Folks using
checkout updates get a local master branch.  I do not change any of
the exact checkout (superproject gitlinked sha1) vs. floating
(subproject's remote submodule.<name>.branch via 'update --remote')
logic, because that already works well.  The problem is the local
branch handling, not the update/integration logic.

> So what should happen on initial clone,

For 'add', clone the command line URL and create a new branch 'master'
pointing at the commit referenced by the remote's HEAD (or other
branch with --branch).

For 'update', do the same, except use a local-branch setting to
determine the name for the local branch, falling back to 'master' if
it is not set.

> later updates,

The same thing that currently happens, with the exception that
checkout-style updates should use reset to update the
currently-checked out branch (or detached-HEAD), instead of always
detaching the HEAD.

> updates where the local and the remote branch diverged,

The same thing that currently happens.  For local (non --remote)
updates, the integrated branch is the superproject's gitlinked sha1.
For --remote updates, the integrated branch is the remote subproject's
submodule.<name>.branch.  We integrate that with the
currently-checked-out local branch (or detached HEAD) using the user's
preferred submodule.<name>.update strategy.

> when superproject branches are merged (with and without conflicts),

I don't think this currently does anything to the submodule itself,
and that makes sense to me (use 'submodule update' or my 'submodule
checkout' if you want such effects).  We should keep the current logic
for updating the gitlinked $sha.  In the case that the
.gitmodule-configured local-branches disagree, we should give the
usual conflict warning (and <<<===>>> markup) and let the user resolve
the conflict in the usual way.

> on a rebase in the superproject and so on.

Same as the merge case.  Why would configuring a preferred
local-branch that only affects checkout (and the initial clone) have
anything to do with rebases and merges?

> After that we can discuss about how to implement them (even though I
> believe we won't need a new submodule command at the end of this
> process, simply because if it isn't configurable we cannot teach git
> checkout and friends to do that automatically for us later).

I think it is configurable, and I have an implementation that works
(modulo bugs) [5].  I think we should teach 'git checkout
--recurse-submodules' this logic, and then we can drop my 'git
submodule checkout' entirely.

> And from reading this discussion I believe we need another value for
> the ignore option which only ignores changes to the SHA-1 but not to
> work tree modifications of a submodule work tree relative to its HEAD
> (or make that two: another one which ignores untracked files too and
> only shows modification of tracked files). Otherwise users of the
> floating or attached model can easily miss submodule modifications.

I am ignore-agnostic ;).  Do whatever you like here.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240251
[2]: http://article.gmane.org/gmane.comp.version-control.git/240164
[3]: http://article.gmane.org/gmane.comp.version-control.git/240250
[4]: http://article.gmane.org/gmane.comp.version-control.git/240249
[5]: http://article.gmane.org/gmane.comp.version-control.git/240248

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09 17:32                                                   ` W. Trevor King
@ 2014-01-09 19:23                                                     ` Jens Lehmann
  2014-01-09 19:55                                                       ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Jens Lehmann @ 2014-01-09 19:23 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Francesco Pretto, Heiko Voigt, Junio C Hamano, Git, Jonathan Nieder

Am 09.01.2014 18:32, schrieb W. Trevor King:
> On Thu, Jan 09, 2014 at 09:31:13AM +0100, Jens Lehmann wrote:
>> Am 09.01.2014 02:09, schrieb Francesco Pretto:
>>> 2014/1/9 W. Trevor King <wking@tremily.us>:
>>>>
>>>> However, submodule.<name>.local-branch has nothing to do with remote
>>>> repositories or tracking branches.
>>>
>>> My bad: this means the feature is still not entirely clear to me.
>>>
>>>>
>>>>   [branch "my-feature"]
>>>>         remote = origin
>>>>         merge = refs/heads/my-feature
>>>>         [submodule "submod"]
>>>>             local-branch = "my-feature"
>>>>
>>>> and I don't think Git's config supports such nesting.
>>>>
>>>
>>> Aesthetically, It doesn't look very nice.
>>
>> And I'm not sure we even need that. What's wrong with having the
>> branch setting in the .gitmodules file of the my-feature branch?
>> The only problem I can imagine is accidentally merging that into
>> a branch where that isn't set, but that could be solved by a merge
>> helper for the .gitmodules file.
> 
> .gitmodules is fine so long as the config can live in the versioned
> tree.  Many (all?) .gitmodules settings can be overridden in
> .git/config.

With the exception of path, as that would make no sense at all.

>  However, the local-branch setting needs to be both
> per-submodule and per-superproject-branch, so .git/config doesn't work
> very well.  I think it's better to use something like my
> .git/modules/<submodule-name>/config implementation [1] to set this
> override.

Yes, the local branch should be set in the submodule's .git/config
to make operations done inside the submodule work seamlessly.

> This lack of per-superproject-branch overrides applies to all of the
> submodule.<name>.* settings, but you're unlikely to want an
> out-of-tree override for 'path' or a per-superproject-branch override
> for 'url', 'ignore', 'update', or 'chRecurseSubmodules'.

Unlikely it is not ;-) We do have people who set update=none in
the .git/config of the superproject for submodules they don't have
access to (and which is not necessary for their work). And it isn't
a "per-superproject-branch override" but a "per-superproject-branch
default" which can be overridden in .git/config (except for 'update',
but I intend to fix that).

>  Maybe folks
> would want per-superproject-branch overrides to 'branch', although I'd
> prefer we reuse branch.<name>.merge in the submodule's config for
> that [2].

But that might still have to be synced with what the superproject
wants. Maybe manually, maybe automatically on checkout. Dunno yet.

> On the other hand, maybe an in-tree .gitmodules is good enough, and
> folks who want a local override can just edit .gitmodules in their
> local branch?  I've never felt the need to override .gitmodules myself
> (for any setting), so feedback from someone who has would be useful.

That way these changes would propagate to others working on the same
branch when pushing, which I believe is a feature.

>>>> I can resuscitate that if folks want, but Heiko felt that my initial
>>>> consolidation didn't go far enough [2].  If it turns out that we're ok
>>>> with the current level of consolidation, would you be ok with
>>>> "non-checkout submodule.<name>.update" as the trigger [3]?
>>>
>>> For me it was ok with what you did:
>>> -------------------------------------------------
>>> if "just_cloned" and "config_branch"
>>> then
>>>      !git reset --hard -q"
>>> fi
>>> -------------------------------------------------
>>>
>>> So yes: at the first clone 'checkout' keeps attached HEAD, while
>>> 'merge' and 'rebase' attach to the branch.
>>
>> It have the impression that attaching the head to the given branch
>> for merge and rebase might be the sensible thing to do, but it
>> would be great to hear from users of merge and rebase if that
>> would break anything for them in their current use cases for these
>> settings.
> 
> Which local branch would you attach to before merging?  I think 'git
> submodule update' should always use the current submodule state
> (attached branch or detached HEAD) [3], and we should have a separate
> call that explicitly checked out the desired submodule branch [4].

Like we currently do with "git submodule update --remote" (where you
have to have an explicit command telling git when to advance the
branch)? Having a separate call that does something *after* a git
command is exactly the problem I'm trying to fix with recursive
update, so I'm not terribly excited ;-)

>>> If it's not the first clone, you should take no action (and your
>>> original patch was ok about this).
>>
>> I'm not sure this is the right thing to do, after all you
>> configured git to follow that branch so I'd expect it to be
>> updated later too, no? Otherwise you might end up with an old
>> version of your branch while upstream is a zillion commits
>> ahead.
> 
> Non-clone updates should not change the submodule's *local* branch
> *name*.  They should change the commit that that branch references,
> otherwise 'git submodule update' would be a no-op ;).

Okay, I seem to have misunderstood that. But what happens when the
branch setting in .gitmodules changes, shouldn't that be updated?

>> First I'd like to see a real consensus about what exactly should
>> happen when a branch is configured to be checked out (and if I
>> missed such a summary in this thread, please point me to it ;-).
> 
> I don't think we have a consensus yet.  A stand-alone outline of my
> current position is in my v3 RFC [5], but I don't have any buy-in yet
> ;).

I'll volunteer to prepare a table explaining the different modes
in my github wiki. Will scan this thread and your pointers for input
and will come back soon when I have something ready.

>> And we should contrast that to the exact checkout and floating
>> branch use cases.
> 
> With my v3 series, there are no more detached HEADs.  Folks using
> checkout updates get a local master branch.  I do not change any of
> the exact checkout (superproject gitlinked sha1) vs. floating
> (subproject's remote submodule.<name>.branch via 'update --remote')
> logic, because that already works well.  The problem is the local
> branch handling, not the update/integration logic.

Ok. Maybe we could use the "<remote>:<local>" notation to store both
remote and local branch in a single setting?

>> So what should happen on initial clone,
> 
> For 'add', clone the command line URL and create a new branch 'master'
> pointing at the commit referenced by the remote's HEAD (or other
> branch with --branch).
> 
> For 'update', do the same, except use a local-branch setting to
> determine the name for the local branch, falling back to 'master' if
> it is not set.

Good.

>> later updates,
> 
> The same thing that currently happens, with the exception that
> checkout-style updates should use reset to update the
> currently-checked out branch (or detached-HEAD), instead of always
> detaching the HEAD.

Won't the user loose any modifications to his local branch here?

>> updates where the local and the remote branch diverged,
> 
> The same thing that currently happens.  For local (non --remote)
> updates, the integrated branch is the superproject's gitlinked sha1.
> For --remote updates, the integrated branch is the remote subproject's
> submodule.<name>.branch.  We integrate that with the
> currently-checked-out local branch (or detached HEAD) using the user's
> preferred submodule.<name>.update strategy.

And for checkout I can easily overwrite the upstream branch with
my local changes?

>> when superproject branches are merged (with and without conflicts),
> 
> I don't think this currently does anything to the submodule itself,
> and that makes sense to me (use 'submodule update' or my 'submodule
> checkout' if you want such effects).  We should keep the current logic
> for updating the gitlinked $sha.  In the case that the
> .gitmodule-configured local-branches disagree, we should give the
> usual conflict warning (and <<<===>>> markup) and let the user resolve
> the conflict in the usual way.

For me it makes lots of sense that in recursive checkout mode the
merged submodules are already checked out (if possible) right after
a superproject merge, making another "submodule update" unnecessary
(the whole point of recursive update is to make "submodule update"
obsolete, except for "--remote").

>> on a rebase in the superproject and so on.
> 
> Same as the merge case.  Why would configuring a preferred
> local-branch that only affects checkout (and the initial clone) have
> anything to do with rebases and merges?

Because teaching --recurse-submodules to checkout is only one part,
in the full recursive update series every work tree manipulating
command (like rebase and merge) will update submodules. So it is
not only affecting checkout, but a lot of other commands too.

>> After that we can discuss about how to implement them (even though I
>> believe we won't need a new submodule command at the end of this
>> process, simply because if it isn't configurable we cannot teach git
>> checkout and friends to do that automatically for us later).
> 
> I think it is configurable, and I have an implementation that works
> (modulo bugs) [5].  I think we should teach 'git checkout
> --recurse-submodules' this logic, and then we can drop my 'git
> submodule checkout' entirely.

Okay, I have no problem with a proof of concept implementation to
play around with.

>> And from reading this discussion I believe we need another value for
>> the ignore option which only ignores changes to the SHA-1 but not to
>> work tree modifications of a submodule work tree relative to its HEAD
>> (or make that two: another one which ignores untracked files too and
>> only shows modification of tracked files). Otherwise users of the
>> floating or attached model can easily miss submodule modifications.
> 
> I am ignore-agnostic ;).  Do whatever you like here.

I was hoping someone else would jump in to do that, as I'm rather
busy with the recursive checkout topic ;-)

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09 19:23                                                     ` Jens Lehmann
@ 2014-01-09 19:55                                                       ` W. Trevor King
  2014-01-09 21:40                                                         ` Jens Lehmann
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-09 19:55 UTC (permalink / raw)
  To: Jens Lehmann
  Cc: Francesco Pretto, Heiko Voigt, Junio C Hamano, Git, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 9386 bytes --]

On Thu, Jan 09, 2014 at 08:23:07PM +0100, Jens Lehmann wrote:
> Am 09.01.2014 18:32, schrieb W. Trevor King:
> >  However, the local-branch setting needs to be both
> > per-submodule and per-superproject-branch, so .git/config doesn't work
> > very well.  I think it's better to use something like my
> > .git/modules/<submodule-name>/config implementation [1] to set this
> > override.
> 
> Yes, the local branch should be set in the submodule's .git/config
> to make operations done inside the submodule work seamlessly.

Once you're inside the submodule my local-branch setting shouldn't
matter, because it just connects superproject branches with submodule
branches.  The submodule's config is just a convenient out-of-tree
place to store per-submodule overrides.

> > This lack of per-superproject-branch overrides applies to all of the
> > submodule.<name>.* settings, but you're unlikely to want an
> > out-of-tree override for 'path' or a per-superproject-branch override
> > for 'url', 'ignore', 'update', or 'chRecurseSubmodules'.
> 
> Unlikely it is not ;-) We do have people who set update=none in
> the .git/config of the superproject for submodules they don't have
> access to (and which is not necessary for their work).

That is not a per-superproject-branch override.  local-branch is the
only per-submodule config I can think of where I can imagine a sane
person actually wanting an out-of-tree per-superproject-branch
override.

> And it isn't a "per-superproject-branch override" but a
> "per-superproject-branch default" which can be overridden in
> .git/config (except for 'update', but I intend to fix that).

You're talking about .gitmodules vs. .git/config here, but for
local-branch, I'm talking about a fallback chain like [1]:

1. superproject.<superproject-branch>.local-branch in the submodule's
   config (superproject/.git/modules/≤submodule-name>/config).
2. submodule.<submodule-name>.local-branch in the superproject's
   config (.git/config).
3. submodule.<submodule-name>.local-branch in the superproject's
   .gitmodules file.
4. default to 'master'

Only #1 is a new idea.

> > On the other hand, maybe an in-tree .gitmodules is good enough,
> > and folks who want a local override can just edit .gitmodules in
> > their local branch?  I've never felt the need to override
> > .gitmodules myself (for any setting), so feedback from someone who
> > has would be useful.
> 
> That way these changes would propagate to others working on the same
> branch when pushing, which I believe is a feature.

Sure.  Unless they don't want to propagate them, at which point they
use an out-of-tree override masking the .gitmodules value.  The
question is, would folks want local overrides for local-branch (like
they do for submodule.<name>.update), or not?  Since it's easy to do
[1], I don't see the point of *not* supporting per-superproject-branch
overrides.

> >> It have the impression that attaching the head to the given
> >> branch for merge and rebase might be the sensible thing to do,
> >> but it would be great to hear from users of merge and rebase if
> >> that would break anything for them in their current use cases for
> >> these settings.
> > 
> > Which local branch would you attach to before merging?  I think
> > 'git submodule update' should always use the current submodule
> > state (attached branch or detached HEAD) [3], and we should have a
> > separate call that explicitly checked out the desired submodule
> > branch [4].
> 
> Like we currently do with "git submodule update --remote" (where you
> have to have an explicit command telling git when to advance the
> branch)? Having a separate call that does something *after* a git
> command is exactly the problem I'm trying to fix with recursive
> update, so I'm not terribly excited ;-)

I'm all for rolling my 'git submodule checkout' into 'git checkout
--recurse-submodules' [2].  It was just faster to mock up in shell
while we decide how it should work.

> >>> If it's not the first clone, you should take no action (and your
> >>> original patch was ok about this).
> >>
> >> I'm not sure this is the right thing to do, after all you
> >> configured git to follow that branch so I'd expect it to be
> >> updated later too, no? Otherwise you might end up with an old
> >> version of your branch while upstream is a zillion commits
> >> ahead.
> > 
> > Non-clone updates should not change the submodule's *local* branch
> > *name*.  They should change the commit that that branch references,
> > otherwise 'git submodule update' would be a no-op ;).
> 
> Okay, I seem to have misunderstood that. But what happens when the
> branch setting in .gitmodules changes, shouldn't that be updated?

Not by 'git submodule update'.  If there are no out-of-tree overrides
and the user calls 'git submodule checkout' with a new local-branch in
.gitmodules, *that* should checkout a new submodule branch.

> >> First I'd like to see a real consensus about what exactly should
> >> happen when a branch is configured to be checked out (and if I
> >> missed such a summary in this thread, please point me to it ;-).
> > 
> > I don't think we have a consensus yet.  A stand-alone outline of my
> > current position is in my v3 RFC [5], but I don't have any buy-in yet
> > ;).
> 
> I'll volunteer to prepare a table explaining the different modes
> in my github wiki. Will scan this thread and your pointers for input
> and will come back soon when I have something ready.

Thanks :).

> >> And we should contrast that to the exact checkout and floating
> >> branch use cases.
> > 
> > With my v3 series, there are no more detached HEADs.  Folks using
> > checkout updates get a local master branch.  I do not change any of
> > the exact checkout (superproject gitlinked sha1) vs. floating
> > (subproject's remote submodule.<name>.branch via 'update --remote')
> > logic, because that already works well.  The problem is the local
> > branch handling, not the update/integration logic.
> 
> Ok. Maybe we could use the "<remote>:<local>" notation to store both
> remote and local branch in a single setting?

Meh :p.  I'm fine with (remote-)branch and local-branch as separate
settings, or a single combined '<remote>:<local>' setting.  However, I
think the local branch name is going to be more closely associated
with the superproject branch than with the subproject's remote branch,
and expect folks to want to override the local-branch on a
per-superproject-branch basis much more often then they'll override
the latter.

> >> later updates,
> > 
> > The same thing that currently happens, with the exception that
> > checkout-style updates should use reset to update the
> > currently-checked out branch (or detached-HEAD), instead of always
> > detaching the HEAD.
> 
> Won't the user loose any modifications to his local branch here?

They just called for a checkout-style update, so yes.  If they want to
keep local modifications, chose an integration mode that preserves
local changes.

> >> updates where the local and the remote branch diverged,
> > 
> > The same thing that currently happens.  For local (non --remote)
> > updates, the integrated branch is the superproject's gitlinked sha1.
> > For --remote updates, the integrated branch is the remote subproject's
> > submodule.<name>.branch.  We integrate that with the
> > currently-checked-out local branch (or detached HEAD) using the user's
> > preferred submodule.<name>.update strategy.
> 
> And for checkout I can easily overwrite the upstream branch with
> my local changes?

?  I don't understand.  How would you overwrite something in the
upstream repository?  Maybe you meant "for checkout I can easily
overwrite the local changes with the upstream branch", which is what I
understand checkout to do.

> >> when superproject branches are merged (with and without conflicts),
> > 
> > I don't think this currently does anything to the submodule itself,
> > and that makes sense to me (use 'submodule update' or my 'submodule
> > checkout' if you want such effects).  We should keep the current logic
> > for updating the gitlinked $sha.  In the case that the
> > .gitmodule-configured local-branches disagree, we should give the
> > usual conflict warning (and <<<===>>> markup) and let the user resolve
> > the conflict in the usual way.
> 
> For me it makes lots of sense that in recursive checkout mode the
> merged submodules are already checked out (if possible) right after
> a superproject merge, making another "submodule update" unnecessary
> (the whole point of recursive update is to make "submodule update"
> obsolete, except for "--remote").

If you force the user to have the configured local-branch checked out
before a non-checkout operations with checkout side-effects (as we
currently do for other kinds of dirty trees), I think you'll avoid
most (all?) of the branch-clobbering problems.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240251
[2]: http://article.gmane.org/gmane.comp.version-control.git/240249

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09 19:55                                                       ` W. Trevor King
@ 2014-01-09 21:40                                                         ` Jens Lehmann
  2014-01-09 22:18                                                           ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Jens Lehmann @ 2014-01-09 21:40 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Francesco Pretto, Heiko Voigt, Junio C Hamano, Git, Jonathan Nieder

Am 09.01.2014 20:55, schrieb W. Trevor King:
> On Thu, Jan 09, 2014 at 08:23:07PM +0100, Jens Lehmann wrote:
>> Am 09.01.2014 18:32, schrieb W. Trevor King:
>>>  However, the local-branch setting needs to be both
>>> per-submodule and per-superproject-branch, so .git/config doesn't work
>>> very well.  I think it's better to use something like my
>>> .git/modules/<submodule-name>/config implementation [1] to set this
>>> override.
>>
>> Yes, the local branch should be set in the submodule's .git/config
>> to make operations done inside the submodule work seamlessly.
> 
> Once you're inside the submodule my local-branch setting shouldn't
> matter, because it just connects superproject branches with submodule
> branches. The submodule's config is just a convenient out-of-tree
> place to store per-submodule overrides.

Now I get it, you want to be able to override a submodule branch for
every superproject branch. I'm not sure I'd add that in the first
iteration though, as it seems to add quite some complexity and I'm
not convinced yet users really need it (but I won't object when we
find real world use cases for that).

>>> This lack of per-superproject-branch overrides applies to all of the
>>> submodule.<name>.* settings, but you're unlikely to want an
>>> out-of-tree override for 'path' or a per-superproject-branch override
>>> for 'url', 'ignore', 'update', or 'chRecurseSubmodules'.
>>
>> Unlikely it is not ;-) We do have people who set update=none in
>> the .git/config of the superproject for submodules they don't have
>> access to (and which is not necessary for their work).
> 
> That is not a per-superproject-branch override.  local-branch is the
> only per-submodule config I can think of where I can imagine a sane
> person actually wanting an out-of-tree per-superproject-branch
> override.

Oops, again I managed to miss the per-superproject*-branch* part.

>> And it isn't a "per-superproject-branch override" but a
>> "per-superproject-branch default" which can be overridden in
>> .git/config (except for 'update', but I intend to fix that).
> 
> You're talking about .gitmodules vs. .git/config here, but for
> local-branch, I'm talking about a fallback chain like [1]:
> 
> 1. superproject.<superproject-branch>.local-branch in the submodule's
>    config (superproject/.git/modules/≤submodule-name>/config).
> 2. submodule.<submodule-name>.local-branch in the superproject's
>    config (.git/config).
> 3. submodule.<submodule-name>.local-branch in the superproject's
>    .gitmodules file.
> 4. default to 'master'
> 
> Only #1 is a new idea.

Thanks for the explanation, now I understand what you're aiming at.

>>> On the other hand, maybe an in-tree .gitmodules is good enough,
>>> and folks who want a local override can just edit .gitmodules in
>>> their local branch?  I've never felt the need to override
>>> .gitmodules myself (for any setting), so feedback from someone who
>>> has would be useful.
>>
>> That way these changes would propagate to others working on the same
>> branch when pushing, which I believe is a feature.
> 
> Sure.  Unless they don't want to propagate them, at which point they
> use an out-of-tree override masking the .gitmodules value.  The
> question is, would folks want local overrides for local-branch (like
> they do for submodule.<name>.update), or not?  Since it's easy to do
> [1], I don't see the point of *not* supporting per-superproject-branch
> overrides.

Unless actual use cases are shown I'd vote for YAGNI here. A new
config option means considerable maintenance burden, no matter how
easy it is to implement in the first place.

>>>> It have the impression that attaching the head to the given
>>>> branch for merge and rebase might be the sensible thing to do,
>>>> but it would be great to hear from users of merge and rebase if
>>>> that would break anything for them in their current use cases for
>>>> these settings.
>>>
>>> Which local branch would you attach to before merging?  I think
>>> 'git submodule update' should always use the current submodule
>>> state (attached branch or detached HEAD) [3], and we should have a
>>> separate call that explicitly checked out the desired submodule
>>> branch [4].
>>
>> Like we currently do with "git submodule update --remote" (where you
>> have to have an explicit command telling git when to advance the
>> branch)? Having a separate call that does something *after* a git
>> command is exactly the problem I'm trying to fix with recursive
>> update, so I'm not terribly excited ;-)
> 
> I'm all for rolling my 'git submodule checkout' into 'git checkout
> --recurse-submodules' [2].  It was just faster to mock up in shell
> while we decide how it should work.

Sure. As I said that's perfectly fine for testing this approach,
but we should do that right in "git checkout" and friends and not
add yet another submodule command.

>>>>> If it's not the first clone, you should take no action (and your
>>>>> original patch was ok about this).
>>>>
>>>> I'm not sure this is the right thing to do, after all you
>>>> configured git to follow that branch so I'd expect it to be
>>>> updated later too, no? Otherwise you might end up with an old
>>>> version of your branch while upstream is a zillion commits
>>>> ahead.
>>>
>>> Non-clone updates should not change the submodule's *local* branch
>>> *name*.  They should change the commit that that branch references,
>>> otherwise 'git submodule update' would be a no-op ;).
>>
>> Okay, I seem to have misunderstood that. But what happens when the
>> branch setting in .gitmodules changes, shouldn't that be updated?
> 
> Not by 'git submodule update'.  If there are no out-of-tree overrides
> and the user calls 'git submodule checkout' with a new local-branch in
> .gitmodules, *that* should checkout a new submodule branch.

Hmm, but isn't "submodule sync" the command that copies changed
upstream config values (currently only the url) into the local config?
Then a subsequent "submodule update" could do the actual checkout.

>>>> First I'd like to see a real consensus about what exactly should
>>>> happen when a branch is configured to be checked out (and if I
>>>> missed such a summary in this thread, please point me to it ;-).
>>>
>>> I don't think we have a consensus yet.  A stand-alone outline of my
>>> current position is in my v3 RFC [5], but I don't have any buy-in yet
>>> ;).
>>
>> I'll volunteer to prepare a table explaining the different modes
>> in my github wiki. Will scan this thread and your pointers for input
>> and will come back soon when I have something ready.
> 
> Thanks :).

A first - rather basic - attempt can be seen at:

   https://github.com/jlehmann/git-submod-enhancements/wiki/Submodule-modes

Input of any kind is very welcome!

>>>> And we should contrast that to the exact checkout and floating
>>>> branch use cases.
>>>
>>> With my v3 series, there are no more detached HEADs.  Folks using
>>> checkout updates get a local master branch.  I do not change any of
>>> the exact checkout (superproject gitlinked sha1) vs. floating
>>> (subproject's remote submodule.<name>.branch via 'update --remote')
>>> logic, because that already works well.  The problem is the local
>>> branch handling, not the update/integration logic.
>>
>> Ok. Maybe we could use the "<remote>:<local>" notation to store both
>> remote and local branch in a single setting?
> 
> Meh :p.  I'm fine with (remote-)branch and local-branch as separate
> settings, or a single combined '<remote>:<local>' setting.  However, I
> think the local branch name is going to be more closely associated
> with the superproject branch than with the subproject's remote branch,
> and expect folks to want to override the local-branch on a
> per-superproject-branch basis much more often then they'll override
> the latter.

Okay. This is a detail we can decide later.

>>>> later updates,
>>>
>>> The same thing that currently happens, with the exception that
>>> checkout-style updates should use reset to update the
>>> currently-checked out branch (or detached-HEAD), instead of always
>>> detaching the HEAD.
>>
>> Won't the user loose any modifications to his local branch here?
> 
> They just called for a checkout-style update, so yes.  If they want to
> keep local modifications, chose an integration mode that preserves
> local changes.

Hmm, as current "submodule updates" already makes it too easy to
loose commits, this does not look right to me. I'd prefer to stop
at that point and tell the user what he can do to solve the conflict.

>>>> updates where the local and the remote branch diverged,
>>>
>>> The same thing that currently happens.  For local (non --remote)
>>> updates, the integrated branch is the superproject's gitlinked sha1.
>>> For --remote updates, the integrated branch is the remote subproject's
>>> submodule.<name>.branch.  We integrate that with the
>>> currently-checked-out local branch (or detached HEAD) using the user's
>>> preferred submodule.<name>.update strategy.
>>
>> And for checkout I can easily overwrite the upstream branch with
>> my local changes?
> 
> ?  I don't understand.  How would you overwrite something in the
> upstream repository?

If the update doesn't overwrite the user-updated local branch (what
I assumed it would do to protect his changes) and he pushes that.

> Maybe you meant "for checkout I can easily
> overwrite the local changes with the upstream branch", which is what I
> understand checkout to do.

But which I find really unfriendly and would not like to see in a new
feature. We should protect the user from loosing any local changes,
not simply throw them away. Recursive update makes sure it won't
overwrite any local modification before it checks out anything and
will abort before doing so (unless forced of course).

>>>> when superproject branches are merged (with and without conflicts),
>>>
>>> I don't think this currently does anything to the submodule itself,
>>> and that makes sense to me (use 'submodule update' or my 'submodule
>>> checkout' if you want such effects).  We should keep the current logic
>>> for updating the gitlinked $sha.  In the case that the
>>> .gitmodule-configured local-branches disagree, we should give the
>>> usual conflict warning (and <<<===>>> markup) and let the user resolve
>>> the conflict in the usual way.
>>
>> For me it makes lots of sense that in recursive checkout mode the
>> merged submodules are already checked out (if possible) right after
>> a superproject merge, making another "submodule update" unnecessary
>> (the whole point of recursive update is to make "submodule update"
>> obsolete, except for "--remote").
> 
> If you force the user to have the configured local-branch checked out
> before a non-checkout operations with checkout side-effects (as we
> currently do for other kinds of dirty trees), I think you'll avoid
> most (all?) of the branch-clobbering problems.

I'm thinking that a local branch works in two directions: It should
make it easy to follow an upstream branch and also make changes to it
(and publish those) if necessary. But neither local nor upstream
changes take precedence, so the user should either use "merge" or
"rebase" as update strategy or be asked to resolve the conflict
manually when "checkout" is configured and the branches diverged.
Does that make sense?

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09 21:40                                                         ` Jens Lehmann
@ 2014-01-09 22:18                                                           ` W. Trevor King
  2014-01-14 10:24                                                             ` Heiko Voigt
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-09 22:18 UTC (permalink / raw)
  To: Jens Lehmann
  Cc: Francesco Pretto, Heiko Voigt, Junio C Hamano, Git, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 11062 bytes --]

On Thu, Jan 09, 2014 at 10:40:52PM +0100, Jens Lehmann wrote:
> Am 09.01.2014 20:55, schrieb W. Trevor King:
> > On Thu, Jan 09, 2014 at 08:23:07PM +0100, Jens Lehmann wrote:
> >> Am 09.01.2014 18:32, schrieb W. Trevor King:
> >>>  However, the local-branch setting needs to be both
> >>> per-submodule and per-superproject-branch, so .git/config doesn't work
> >>> very well.  I think it's better to use something like my
> >>> .git/modules/<submodule-name>/config implementation [1] to set this
> >>> override.
> >>
> >> Yes, the local branch should be set in the submodule's .git/config
> >> to make operations done inside the submodule work seamlessly.
> > 
> > Once you're inside the submodule my local-branch setting shouldn't
> > matter, because it just connects superproject branches with submodule
> > branches. The submodule's config is just a convenient out-of-tree
> > place to store per-submodule overrides.
> 
> Now I get it, you want to be able to override a submodule branch for
> every superproject branch. I'm not sure I'd add that in the first
> iteration though, as it seems to add quite some complexity and I'm
> not convinced yet users really need it (but I won't object when we
> find real world use cases for that).

Not much complexity in the code, it's all in the first patch of my v3
series [1].  Adding a new override location doesn't seem that
complicated to me, but I haven't been very successful at getting this
idea across, so maybe it's weirder than I think ;).  Clearer
explanations welcome ;).

> >> And it isn't a "per-superproject-branch override" but a
> >> "per-superproject-branch default" which can be overridden in
> >> .git/config (except for 'update', but I intend to fix that).
> > 
> > You're talking about .gitmodules vs. .git/config here, but for
> > local-branch, I'm talking about a fallback chain like [1]:
> > 
> > 1. superproject.<superproject-branch>.local-branch in the submodule's
> >    config (superproject/.git/modules/≤submodule-name>/config).
> > 2. submodule.<submodule-name>.local-branch in the superproject's
> >    config (.git/config).
> > 3. submodule.<submodule-name>.local-branch in the superproject's
> >    .gitmodules file.
> > 4. default to 'master'
> > 
> > Only #1 is a new idea.
> 
> Thanks for the explanation, now I understand what you're aiming at.

For additional clarity, my whole v3 series is not super long [2]… ;)

> >>> On the other hand, maybe an in-tree .gitmodules is good enough,
> >>> and folks who want a local override can just edit .gitmodules in
> >>> their local branch?  I've never felt the need to override
> >>> .gitmodules myself (for any setting), so feedback from someone
> >>> who has would be useful.
> >>
> >> That way these changes would propagate to others working on the
> >> same branch when pushing, which I believe is a feature.
> > 
> > Sure.  Unless they don't want to propagate them, at which point
> > they use an out-of-tree override masking the .gitmodules value.
> > The question is, would folks want local overrides for local-branch
> > (like they do for submodule.<name>.update), or not?  Since it's
> > easy to do [1], I don't see the point of *not* supporting
> > per-superproject-branch overrides.
> 
> Unless actual use cases are shown I'd vote for YAGNI here. A new
> config option means considerable maintenance burden, no matter how
> easy it is to implement in the first place.

Automatically checking out the preferred submodule branch for a given
superproject branch already requires a new config option.  The
per-superproject-branch out-of-tree override just renames it (from
submodule.<submodule-name>.local-branch to
superproject.<superproject-branch>.local-branch).  So different names
depending on superproject-level or submodule-level config, but still
the same option.  That doesn't sound like it's adding that much of a
maintenance burden.

On the other hand, I, personally, have no need for out-of-tree
overrides for *any* submodule-related config, so I'm fine if we drop
the submodule-level lookup location ;).

> > I'm all for rolling my 'git submodule checkout' into 'git checkout
> > --recurse-submodules' [2].  It was just faster to mock up in shell
> > while we decide how it should work.
> 
> Sure. As I said that's perfectly fine for testing this approach,
> but we should do that right in "git checkout" and friends and not
> add yet another submodule command.

The current C code looked fairly focused on detached HEAD sha1
checkouts, which was so far away from what I think should happen that
I didn't know where to start ;).  If we like the logic layed out in my
v3 series, I'll take another look at the C series and see if I can
come up with something.

> >>>>> If it's not the first clone, you should take no action (and your
> >>>>> original patch was ok about this).
> >>>>
> >>>> I'm not sure this is the right thing to do, after all you
> >>>> configured git to follow that branch so I'd expect it to be
> >>>> updated later too, no? Otherwise you might end up with an old
> >>>> version of your branch while upstream is a zillion commits
> >>>> ahead.
> >>>
> >>> Non-clone updates should not change the submodule's *local* branch
> >>> *name*.  They should change the commit that that branch references,
> >>> otherwise 'git submodule update' would be a no-op ;).
> >>
> >> Okay, I seem to have misunderstood that. But what happens when the
> >> branch setting in .gitmodules changes, shouldn't that be updated?
> > 
> > Not by 'git submodule update'.  If there are no out-of-tree overrides
> > and the user calls 'git submodule checkout' with a new local-branch in
> > .gitmodules, *that* should checkout a new submodule branch.
> 
> Hmm, but isn't "submodule sync" the command that copies changed
> upstream config values (currently only the url) into the local config?
> Then a subsequent "submodule update" could do the actual checkout.

'submodule update' currently only checks out detached HEADs with the
'checkout' update mode.  I got rid of that in my v3 series, so now all
'submodule update' does is integrate some branch (the gitlinked sha1
or the upstream --remote).  It has nothing to do with changing the
locally-checked-out branch.

> >>>> later updates,
> >>>
> >>> The same thing that currently happens, with the exception that
> >>> checkout-style updates should use reset to update the
> >>> currently-checked out branch (or detached-HEAD), instead of
> >>> always detaching the HEAD.
> >>
> >> Won't the user loose any modifications to his local branch here?
> > 
> > They just called for a checkout-style update, so yes.  If they
> > want to keep local modifications, chose an integration mode that
> > preserves local changes.
> 
> Hmm, as current "submodule updates" already makes it too easy to
> loose commits, this does not look right to me. I'd prefer to stop at
> that point and tell the user what he can do to solve the conflict.

Users who are worried about loosing local updates should not be using
a checkout-style updates.  If they are using a checkout-style update,
and they ask for an update, they're specifically requesting that we
blow away their local work and checkout/reset to the new sha1.
Solving update conflicts is the whole point of the non-checkout update
modes.

> > Maybe you meant "for checkout I can easily overwrite the local
> > changes with the upstream branch", which is what I understand
> > checkout to do.
> 
> But which I find really unfriendly and would not like to see in a
> new feature. We should protect the user from loosing any local
> changes, not simply throw them away. Recursive update makes sure it
> won't overwrite any local modification before it checks out anything
> and will abort before doing so (unless forced of course).

If you want to get rid of checkout-mode updates, I'm fine with that.
However, I don't think it supports use-cases like Heiko's (implied) “I
don't care what's happening upstream, I never touch that submodule,
just checkout what the superproject maintainer says should be checked
out for this branch.  Even if they have been rebasing or whatever”
[3].

> >>>> when superproject branches are merged (with and without conflicts),
> >>>
> >>> I don't think this currently does anything to the submodule itself,
> >>> and that makes sense to me (use 'submodule update' or my 'submodule
> >>> checkout' if you want such effects).  We should keep the current logic
> >>> for updating the gitlinked $sha.  In the case that the
> >>> .gitmodule-configured local-branches disagree, we should give the
> >>> usual conflict warning (and <<<===>>> markup) and let the user resolve
> >>> the conflict in the usual way.
> >>
> >> For me it makes lots of sense that in recursive checkout mode the
> >> merged submodules are already checked out (if possible) right after
> >> a superproject merge, making another "submodule update" unnecessary
> >> (the whole point of recursive update is to make "submodule update"
> >> obsolete, except for "--remote").
> > 
> > If you force the user to have the configured local-branch checked out
> > before a non-checkout operations with checkout side-effects (as we
> > currently do for other kinds of dirty trees), I think you'll avoid
> > most (all?) of the branch-clobbering problems.
> 
> I'm thinking that a local branch works in two directions: It should
> make it easy to follow an upstream branch and also make changes to it
> (and publish those) if necessary.

Those both sound like “integration with the remote submodule” issues
to me.  I'm more worried about what happens purely locally as the
developer checks out different superproject branches and wants the
submodules to follow along automatically (without detaching HEADs).
Once we have something that works there, I expect it will be easier to
add recursive superproject branch integration cleanly.  For example,
all of the usual branch-level config options (branch.<name>.*) come
along for free.

> But neither local nor upstream changes take precedence, so the user
> should either use "merge" or "rebase" as update strategy

That sounds good to me.

> or be asked to resolve the conflict manually when "checkout" is
> configured and the branches diverged.

I still think that checkout-mode updates should be destructive.  See
my paraphrased-version of Heiko's use case above.  How are they going
to resolve this manually?  Merge or rebase?  Why weren't they using
that update mode in the first place?

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240251
[2]: http://article.gmane.org/gmane.comp.version-control.git/240248
[3]: http://article.gmane.org/gmane.comp.version-control.git/240013

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Tight submodule bindings (was: Preferred local submodule branches)
  2014-01-09  6:17                             ` [RFC v3 0/4] " W. Trevor King
                                                 ` (3 preceding siblings ...)
  2014-01-09  6:17                               ` [RFC v3 4/4] submodule: Add a new 'checkout' command W. Trevor King
@ 2014-01-12  1:08                               ` W. Trevor King
  2014-01-13 19:37                                 ` Tight submodule bindings Jens Lehmann
  2014-01-13 22:13                                 ` Junio C Hamano
  4 siblings, 2 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-12  1:08 UTC (permalink / raw)
  To: Jens Lehmann
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jonathan Nieder, Git

[-- Attachment #1: Type: text/plain, Size: 13861 bytes --]

On Wed, Jan 08, 2014 at 10:17:51PM -0800, W. Trevor King wrote:
> In another branch of the submodule thread Francesco kicked off, I
> mentioned that we could store the preferred local submodule branch on
> a per-superbranch level if we used the
> .git/modules/<submodule-name>/config for local overrides [1].  Here's
> a patch series that greatly extends my v2 "submodule: Respect
> requested branch on all clones" series [2] to also support automatic,
> recursive submodule checkouts, as I outlined here [3].
> 
> [1]: http://article.gmane.org/gmane.comp.version-control.git/240240
> [2]: http://article.gmane.org/gmane.comp.version-control.git/239967
> [3]: http://article.gmane.org/gmane.comp.version-control.git/240192

While mulling over better ways to explain my local-branch idea, I've
come up with a more tightly bound model that may help break the
silence that has greeted the “Preferred local submodule branches”
series ;).  That series doesn't have strong options on update
mechanics, which leads to wishy-washy exchanges where nobody has a
clear mental picture:

On Thu, Jan 09, 2014 at 10:40:52PM +0100, Jens Lehmann wrote:
> Am 09.01.2014 20:55, schrieb W. Trevor King:
> > On Thu, Jan 09, 2014 at 08:23:07PM +0100, Jens Lehmann wrote:
> >> Am 09.01.2014 18:32, schrieb W. Trevor King:
> >>>> when superproject branches are merged (with and without conflicts),
> >>>
> >>> I don't think this currently does anything to the submodule itself,
> >>> and that makes sense to me (use 'submodule update' or my 'submodule
> >>> checkout' if you want such effects).  We should keep the current logic
> >>> for updating the gitlinked $sha.  In the case that the
> >>> .gitmodule-configured local-branches disagree, we should give the
> >>> usual conflict warning (and <<<===>>> markup) and let the user resolve
> >>> the conflict in the usual way.
> >>
> >> For me it makes lots of sense that in recursive checkout mode the
> >> merged submodules are already checked out (if possible) right after
> >> a superproject merge, making another "submodule update" unnecessary
> >> (the whole point of recursive update is to make "submodule update"
> >> obsolete, except for "--remote").
> > 
> > If you force the user to have the configured local-branch checked out
> > before a non-checkout operations with checkout side-effects (as we
> > currently do for other kinds of dirty trees), I think you'll avoid
> > most (all?) of the branch-clobbering problems.
> 
> I'm thinking that a local branch works in two directions: It should
> make it easy to follow an upstream branch and also make changes to it
> (and publish those) if necessary. But neither local nor upstream
> changes take precedence, so the user should either use "merge" or
> "rebase" as update strategy or be asked to resolve the conflict
> manually when "checkout" is configured and the branches diverged.
> Does that make sense?

The current series is only weakly bound (you can explicitly call git
submodule checkout' to change to the preferred local submodule
branch), and the current Git is extremely weakly bound (you have to cd
into the submodule and change branches by hand).  The following
extrapolates the “Preferred local submodule branches” series to a
tightly-bound ideal.

Gitlinked commit hash
---------------------

The submodule model revolves around links to commits (“gitlinks”):

  $ git ls-tree HEAD
  100644 blob 189fc359d3dc1ed5019b9834b93f0dfb49c5851f    .gitmodules
  160000 commit fbfa124c29362f180026bf0074630e8bd0ff4550  submod

These are effectively switchable trees.  The tree referenced by commit
fbfa124 is 492781c:

  $ (cd submod/ && git cat-file commit fbfa124)
  tree 492781c581d4dec380a61ef5ec69a104de448a74
  …

If you init the submodule, subsequent checkouts will check out that
tree, just like 'git checkout' would do if you'd had a superproject
tree like:

  $ git ls-tree HEAD
  100644 blob 189fc359d3dc1ed5019b9834b93f0dfb49c5851f    .gitmodules
  040000 tree 492781c581d4dec380a61ef5ec69a104de448a74    submod

For folks who treat the submodule as a black box (and do no local
development), switchable trees are all they care about.  They can
easily checkout (or not, with deinit), the submodule tree at a
gitlinked hash, and everything is nice and reproducible.  The fact
that 'submod' is stored as a commit object and not a tree, is just a
convenient marker for optional init/deinit/remote-update-integration
functionality.

Additional metadata, the initial checkout, and syncing down
-----------------------------------------------------------

However, folks who do local submodule development will care about
which submodule commit is responsible for that tree, because that's
going to be the base of their local development.  They also care about
additional out-of-tree information, including the branch that commit
is on.  For already-initialized submodules, there are existing places
in the submodule config to store this configuration:

1. HEAD for the checked-out branch,
2. branch.<name>.remote → remote.<name>.url for the upstream
   subproject URL,
4. branch.<name>.rebase (or pull.rebase) to prefer rebase over merge
   for integration,
5. …

You need somewhere in-tree to store this destined-to-be-out-of-tree
information, so that superproject developers that have not yet
initialized the submodule will know what values are suggested by the
superproject maintainers.  That's where .gitmodules comes in, because
storing all of this fairly static, locally overridable information in
the gitlink itself would be nonsensical (said Linus in 2007 [1]).
When you checkout a submodule for the first time, Git should take the
default information from .gitmodules and file it away in the
submodule's appropriate out-of-tree config locations.  The out-of-tree
data listed above should be stored in:

1. submodule.<name>.local-branch
2. submodule.<name>.url
4. submodule.<name>.update
5. …

Once you have an in-tree way to specify defaults for this out-of-tree
information, you're going to have developers like me that just want to
stick with the defaults, following them through changes.  That means
you'd like to have the “copy .gitmodules defaults into your
submodule's config” functionality that usually happens on the initial
submodule checkout happen on *every superproject-initiated checkout*.
In fact, I think life is easier for everyone if this is the default,
and we add a new option (submodule.<name>.sync = false) that says
“don't overwrite optional settings in my submodule's out-of-tree
config on checkout” for for folks who want to opt out.  Don't worry,
this is not going to clobber people, because we'll be syncing the
other way too.

Syncing up
----------

In the previous section I explained how data should flow from
.gitmodules into out-of-tree configs.  What about the other direction?
We currently let folks handle this by hand, but I'd prefer a tighter
integration between the submodule config and the superproject tree to
avoid losing work.  That means changes to tracked submodule status
(checked-out hash, checked-out branch, upstream URL, upstream branch,
default integration strategy, …) should trigger dirty-tree status just
like uncommitted changes to in-tree files.  'git add' (or stash) on
the dirty submodule would store changed commit hashes in the index,
pull changed out-of-tree configs back into the in-tree .gitmodules,
and add the new .gitmodules to the index.  If the working .gitmodules
was already dirty (vs. the index), the add/stash should die without
making any changes.  If the user has disabled syncing between
.gitmodules and the submodule's out-of-tree configs, then don't worry
about optional settings.  Always sync the required settings, which at
this point would just be submodule.<name>.local-branch.

Purely local metadata
---------------------

Some metadata does not make sense in the superproject tree.  For
example, whether a submodule is interesting enough to checkout
(init/deinit) or whether you want to auto-sync optional metadata
.gitmodules defaults.  This metadata should live in the superproject's
out-of-tree config, and should not be stored in the in-tree
.gitmodules.  Since you *will* want to share the upstream URL, I
proposed using an explicit submodule.<name>.active setting to store
the “do I care” information [2], instead of overloading
submodule.<name>.url (I'd auto-sync the .gitmodule's
submodule.<name>.url with the subproject's remote.origin.url unless
the user opted out of .gitmodules syncing).

Subsequent checkouts
--------------------

Now that we have strict linking between the submodule state (both
in-tree and out-of-tree configs) and the superproject tree (gitlink
and .gitmodules), changing between superproject branches is really
easy:

1. Make sure the working tree is not dirty.  If it is, ask the user to
   either add-and-commit or stash, and then die to let them do so.

2. Checkout the new superproject branch.

   2.1. For each old submodule that doesn't exist in the new branch,
        blow away the submodule directory (assuming a new-style
        .git/modules/… layout, and not an old-style submod/.git/…
        layout).

   2.2. For each gitlinked submodule that didn't exist in the old
        branch, setup the submodule as if you were doing the initial
        cloning checkout (forcing a new local-branch to point at the
        gitlinked commit).  If you find local out-of-tree
        *superproject* configs that conflict with the .gitmodules
        values, prefer the superproject configs.  Clobber submodule
        configs and local branches at will (modulo
        submodule.<name>.sync), because any submodule configs that the
        user wanted to keep should have been added to the superproject
        branch earlier (or stashed).

Integrating other branches
--------------------------

Merges and rebases can alter the submodule's in-tree configs (and
create and remove submodules).  The existing logic for merging
.gitmodules and gitlinks works well, so stick with that.  In the event
that there are unresolvable conflicts, bail out and let the user
resolve the conflicts and use 'git commit' to finish checking out the
resolved state.

Issues
------

I like the current submodule integration configuration:

* submodule.<name>.branch (specify the remote branch to integrate, but
  I'd prefer submodule.<name>.integration-ref for clarity).
* submodule.<name>.update (specify how to integrate it, but I'd prefer
  submodule.<name>.integration-mode for clarity).

more than the current core integration configuration:

* branch.<name>.merge (with branch.<name>.remote, the branch to remote
  branch to integrate via merging).
* branch.<name>.rebase (override branch.<name>.merge to integrate via
  rebasing).

These seem to mix the orthogonal concepts of integration target and
integration mode, and the divergence from the .gitmodules
representation makes syncing awkward.

Summary
-------

New .gitmodules options:

* submodule.<name>.local-branch, store the submodule's HEAD, must stay
  in sync for checkouts.

New .git/config options:

* submodule.<name>.active, for init/deinit.

* submodule.<name>.sync, for whether you want to automatically sync
  the submodule's out-of-tree configs up to .gitmodules before
  checkout operations, and sync back from .gitmodules (possibly
  altered on the new branch) into the submodule's out-of-tree configs
  during checkout.

With this tighter binding, submodule information is either tracked in
the superproject, or explicitly not touched by the superproject.  That
makes it much harder to break things or clobber a user's work, and
also much easier to keep submodules up to date with superproject
changes.  Users shouldn't have to explicitly manage their submodules
to carry out routine core tasks like checking out other branches.

I see no reason to add --recurse-submodule flags to 'git checkout'
(and merge, …).  Anything that happens post-clone should recurse
through submodules automatically, and use the submodule.<name>.active
setting to decide when recursion is desired.

I think the ideal submodule-specific interface would be just:

* git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
                [--reference <repository>] [--] <repository> [<path>]
* git submodule [--quiet] init [--] [<path>...]
* git submodule [--quiet] deinit [-f|--force] [--] <path>...
* git submodule [--quiet] foreach [--recursive] <command>

The current 'git submodule update --remote' would just be:

  $ git submodule foreach 'git pull'

because all of the local-branch checkouts would have already been
handled.  Similarly, a global push would be just:

  $ git submodule foreach 'git push'

You get all the per-submodule configuration (for triangular workflows,
etc.) for free, with no submodule-specific confusion.

So, is this:

* Interesting enough to be worth pursuing?
* Simple enough to be easily understood?

I'd be happy to mock this up in shell, but only if anyone else would
be interested enough to review the implementation ;).  Then I'll look
into integrating the preferred model (this tightly bound proposal, or
v3's looser bindings, or <your idea here>) in C, building on Jens and
Jonathan's work.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/44162
[2]: http://article.gmane.org/gmane.comp.version-control.git/211042

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH/RFC] Introduce git submodule add|update --attach
  2014-01-02 18:48   ` Francesco Pretto
@ 2014-01-13 17:31     ` Junio C Hamano
  0 siblings, 0 replies; 144+ messages in thread
From: Junio C Hamano @ 2014-01-13 17:31 UTC (permalink / raw)
  To: Francesco Pretto; +Cc: Phil Hord, git

Francesco Pretto <ceztko@gmail.com> writes:

> Thanks for the comments, my replies below. Before, a couple of general
> questions:
> - I'm also writing some tests, should I commit them together with the
> feature patch?
> - to determine the attached/detached state I did this:
>
> head_detached=
> if test "$(rev-parse --abbrev-ref HEAD)" = "HEAD"
> then
>     head_detached="true"
> fi

Use "git symbolic-ref HEAD" to read off of it.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Tight submodule bindings
  2014-01-12  1:08                               ` Tight submodule bindings (was: Preferred local submodule branches) W. Trevor King
@ 2014-01-13 19:37                                 ` Jens Lehmann
  2014-01-13 20:07                                   ` W. Trevor King
  2014-01-13 22:13                                 ` Junio C Hamano
  1 sibling, 1 reply; 144+ messages in thread
From: Jens Lehmann @ 2014-01-13 19:37 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jonathan Nieder, Git

Thanks for the writeup, comments below.

Am 12.01.2014 02:08, schrieb W. Trevor King:
> Gitlinked commit hash
> ---------------------
> 
> The submodule model revolves around links to commits (“gitlinks”):
> 
>   $ git ls-tree HEAD
>   100644 blob 189fc359d3dc1ed5019b9834b93f0dfb49c5851f    .gitmodules
>   160000 commit fbfa124c29362f180026bf0074630e8bd0ff4550  submod
> 
> These are effectively switchable trees.  The tree referenced by commit
> fbfa124 is 492781c:
> 
>   $ (cd submod/ && git cat-file commit fbfa124)
>   tree 492781c581d4dec380a61ef5ec69a104de448a74
>   …
> 
> If you init the submodule, subsequent checkouts will check out that
> tree, just like 'git checkout' would do if you'd had a superproject
> tree like:
> 
>   $ git ls-tree HEAD
>   100644 blob 189fc359d3dc1ed5019b9834b93f0dfb49c5851f    .gitmodules
>   040000 tree 492781c581d4dec380a61ef5ec69a104de448a74    submod
> 
> For folks who treat the submodule as a black box (and do no local
> development), switchable trees are all they care about.  They can
> easily checkout (or not, with deinit), the submodule tree at a
> gitlinked hash, and everything is nice and reproducible.  The fact
> that 'submod' is stored as a commit object and not a tree, is just a
> convenient marker for optional init/deinit/remote-update-integration
> functionality.

But there are users (like me) who do not treat submodules as
black boxes and nonetheless do development in them with update
set to checkout (after creating a feature branch of course ;-).

> Additional metadata, the initial checkout, and syncing down
> -----------------------------------------------------------
> 
> However, folks who do local submodule development will care about
> which submodule commit is responsible for that tree, because that's
> going to be the base of their local development.  They also care about
> additional out-of-tree information, including the branch that commit
> is on.  For already-initialized submodules, there are existing places
> in the submodule config to store this configuration:
> 
> 1. HEAD for the checked-out branch,
> 2. branch.<name>.remote → remote.<name>.url for the upstream
>    subproject URL,
> 4. branch.<name>.rebase (or pull.rebase) to prefer rebase over merge
>    for integration,
> 5. …
> 
> You need somewhere in-tree to store this destined-to-be-out-of-tree
> information, so that superproject developers that have not yet
> initialized the submodule will know what values are suggested by the
> superproject maintainers.  That's where .gitmodules comes in, because
> storing all of this fairly static, locally overridable information in
> the gitlink itself would be nonsensical (said Linus in 2007 [1]).
> When you checkout a submodule for the first time, Git should take the
> default information from .gitmodules and file it away in the
> submodule's appropriate out-of-tree config locations.

I disagree, that only makes sense for the URL setting (and this
currently only happens with the update setting, which I intend to
change). Everything else should be taken from .gitmodules unless
the user wants to override it. The only setting I'm not so sure
about is the local branch setting, as that might have to propagate
into the submodule.

>  The out-of-tree
> data listed above should be stored in:
> 
> 1. submodule.<name>.local-branch
> 2. submodule.<name>.url
> 4. submodule.<name>.update
> 5. …
> 
> Once you have an in-tree way to specify defaults for this out-of-tree
> information, you're going to have developers like me that just want to
> stick with the defaults, following them through changes.  That means
> you'd like to have the “copy .gitmodules defaults into your
> submodule's config” functionality that usually happens on the initial
> submodule checkout happen on *every superproject-initiated checkout*.

You don't need to copy it every time when you simply use the
.gitmodules file as fallback, no?

> In fact, I think life is easier for everyone if this is the default,
> and we add a new option (submodule.<name>.sync = false) that says
> “don't overwrite optional settings in my submodule's out-of-tree
> config on checkout” for for folks who want to opt out.  Don't worry,
> this is not going to clobber people, because we'll be syncing the
> other way too.

Yet another flag to make peoples life easier? I don't think so ;-)

> Syncing up
> ----------
> 
> In the previous section I explained how data should flow from
> .gitmodules into out-of-tree configs.  What about the other direction?
> We currently let folks handle this by hand, but I'd prefer a tighter
> integration between the submodule config and the superproject tree to
> avoid losing work.  That means changes to tracked submodule status
> (checked-out hash, checked-out branch, upstream URL, upstream branch,
> default integration strategy, …) should trigger dirty-tree status just
> like uncommitted changes to in-tree files.  'git add' (or stash) on
> the dirty submodule would store changed commit hashes in the index,
> pull changed out-of-tree configs back into the in-tree .gitmodules,
> and add the new .gitmodules to the index.  If the working .gitmodules
> was already dirty (vs. the index), the add/stash should die without
> making any changes.  If the user has disabled syncing between
> .gitmodules and the submodule's out-of-tree configs, then don't worry
> about optional settings.  Always sync the required settings, which at
> this point would just be submodule.<name>.local-branch.

Such a logic might make sense. And without copying stuff from
.gitmodules someplace else it becomes even easier ;-)

> Purely local metadata
> ---------------------
> 
> Some metadata does not make sense in the superproject tree.  For
> example, whether a submodule is interesting enough to checkout
> (init/deinit) or whether you want to auto-sync optional metadata
> .gitmodules defaults.  This metadata should live in the superproject's
> out-of-tree config, and should not be stored in the in-tree
> .gitmodules.

Not always. It makes a lot of sense to let upstream mark a
submodule as "too big and you won't need it anyway" in the
.gitmodules file.

>  Since you *will* want to share the upstream URL, I
> proposed using an explicit submodule.<name>.active setting to store
> the “do I care” information [2], instead of overloading
> submodule.<name>.url (I'd auto-sync the .gitmodule's
> submodule.<name>.url with the subproject's remote.origin.url unless
> the user opted out of .gitmodules syncing).

That is wrong as it would break horribly when you check out an
old commit with a now dead submodule URL and that gets automatically
synced.

> Subsequent checkouts
> --------------------
> 
> Now that we have strict linking between the submodule state (both
> in-tree and out-of-tree configs) and the superproject tree (gitlink
> and .gitmodules), changing between superproject branches is really
> easy:
> 
> 1. Make sure the working tree is not dirty.  If it is, ask the user to
>    either add-and-commit or stash, and then die to let them do so.

This condition is too hard, relax that to "a trivial merge can
switch from current state to target state" and make it behave just
like branch switching in the superproject. After all submodules
should behave as much as possible like content of the superproject.

> 2. Checkout the new superproject branch.
> 
>    2.1. For each old submodule that doesn't exist in the new branch,
>         blow away the submodule directory (assuming a new-style
>         .git/modules/… layout, and not an old-style submod/.git/…
>         layout).

Yep.

>    2.2. For each gitlinked submodule that didn't exist in the old
>         branch, setup the submodule as if you were doing the initial
>         cloning checkout (forcing a new local-branch to point at the
>         gitlinked commit).  If you find local out-of-tree
>         *superproject* configs that conflict with the .gitmodules
>         values, prefer the superproject configs.

Yup, our working title for that is "autoinit".

>  Clobber submodule
>         configs and local branches at will (modulo
>         submodule.<name>.sync), because any submodule configs that the
>         user wanted to keep should have been added to the superproject
>         branch earlier (or stashed).

I don't think I like this part, but I admit I do not fully understand
what you mean here. Clobbering stuff the user did doesn't sound very
nice.

> Integrating other branches
> --------------------------
> 
> Merges and rebases can alter the submodule's in-tree configs (and
> create and remove submodules).  The existing logic for merging
> .gitmodules and gitlinks works well, so stick with that.  In the event
> that there are unresolvable conflicts, bail out and let the user
> resolve the conflicts and use 'git commit' to finish checking out the
> resolved state.

Agreed.

> Issues
> ------
> 
> I like the current submodule integration configuration:
> 
> * submodule.<name>.branch (specify the remote branch to integrate, but
>   I'd prefer submodule.<name>.integration-ref for clarity).
> * submodule.<name>.update (specify how to integrate it, but I'd prefer
>   submodule.<name>.integration-mode for clarity).

But we won't rename those now.

> more than the current core integration configuration:
> 
> * branch.<name>.merge (with branch.<name>.remote, the branch to remote
>   branch to integrate via merging).
> * branch.<name>.rebase (override branch.<name>.merge to integrate via
>   rebasing).
> 
> These seem to mix the orthogonal concepts of integration target and
> integration mode, and the divergence from the .gitmodules
> representation makes syncing awkward.

I'm still hoping we might come up with a solution that doesn't need
the syncing.

> Summary
> -------
> 
> New .gitmodules options:
> 
> * submodule.<name>.local-branch, store the submodule's HEAD, must stay
>   in sync for checkouts.

I'm still not convinced that the current branch setting couldn't be
extended to carry that information, but no objections against
configuring such a branch. But what do you mean with "must stay in
sync for checkouts"?

> New .git/config options:
> 
> * submodule.<name>.active, for init/deinit.

I understand an option for automatic init (autoinit), but not for
automatic deinit. Is the latter really useful?

> * submodule.<name>.sync, for whether you want to automatically sync
>   the submodule's out-of-tree configs up to .gitmodules before
>   checkout operations, and sync back from .gitmodules (possibly
>   altered on the new branch) into the submodule's out-of-tree configs
>   during checkout.

Not needed if you use .gitmodules as fallback.

> With this tighter binding, submodule information is either tracked in
> the superproject, or explicitly not touched by the superproject.  That
> makes it much harder to break things or clobber a user's work, and
> also much easier to keep submodules up to date with superproject
> changes.  Users shouldn't have to explicitly manage their submodules
> to carry out routine core tasks like checking out other branches.

Agreed.

> I see no reason to add --recurse-submodule flags to 'git checkout'
> (and merge, …).  Anything that happens post-clone should recurse
> through submodules automatically, and use the submodule.<name>.active
> setting to decide when recursion is desired.

Backwards compatibility and testing. Let's first implement that and
provide a config option to enable it for real world testing, and then
let's discuss changing the default later.

> I think the ideal submodule-specific interface would be just:
> 
> * git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
>                 [--reference <repository>] [--] <repository> [<path>]
> * git submodule [--quiet] init [--] [<path>...]
> * git submodule [--quiet] deinit [-f|--force] [--] <path>...
> * git submodule [--quiet] foreach [--recursive] <command>

Ok.

> The current 'git submodule update --remote' would just be:
> 
>   $ git submodule foreach 'git pull'
> 
> because all of the local-branch checkouts would have already been
> handled.

Nope, that does different things to submodules where "branch" isn't
configured, right?

>  Similarly, a global push would be just:
> 
>   $ git submodule foreach 'git push'

What's wrong with:

$ git push --recurse-submodules=on-demand

And it'll push the superproject at the same time. Extra points for
already being implemented ;-)

> You get all the per-submodule configuration (for triangular workflows,
> etc.) for free, with no submodule-specific confusion.
> 
> So, is this:
> 
> * Interesting enough to be worth pursuing?
> * Simple enough to be easily understood?

The thoughts about the branch workflow are really interesting. Some
other proposals overshoot a bit in my opinion ;-)

> I'd be happy to mock this up in shell, but only if anyone else would
> be interested enough to review the implementation ;).  Then I'll look
> into integrating the preferred model (this tightly bound proposal, or
> v3's looser bindings, or <your idea here>) in C, building on Jens and
> Jonathan's work.

The update modes (cleaning removed submodules and creating new ones)
are better handled in my recursive checkout series. But I believe we
can at least prototype the branch handling in shell.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Tight submodule bindings
  2014-01-13 19:37                                 ` Tight submodule bindings Jens Lehmann
@ 2014-01-13 20:07                                   ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-13 20:07 UTC (permalink / raw)
  To: Jens Lehmann
  Cc: Francesco Pretto, Junio C Hamano, Heiko Voigt, Jonathan Nieder, Git

[-- Attachment #1: Type: text/plain, Size: 8694 bytes --]

On Mon, Jan 13, 2014 at 08:37:37PM +0100, Jens Lehmann wrote:
> Am 12.01.2014 02:08, schrieb W. Trevor King:
> > For folks who treat the submodule as a black box (and do no local
> > development), switchable trees are all they care about.  They can
> > easily checkout (or not, with deinit), the submodule tree at a
> > gitlinked hash, and everything is nice and reproducible.  The fact
> > that 'submod' is stored as a commit object and not a tree, is just
> > a convenient marker for optional
> > init/deinit/remote-update-integration functionality.
> 
> But there are users (like me) who do not treat submodules as
> black boxes and nonetheless do development in them with update
> set to checkout (after creating a feature branch of course ;-).

I'm still not clear on how this works for you ;).  Can you sketch out
an example shell history showing how you use checkout updates to do
this?

> > When you checkout a submodule for the first time, Git should take
> > the default information from .gitmodules and file it away in the
> > submodule's appropriate out-of-tree config locations.
> 
> I disagree, that only makes sense for the URL setting (and this
> currently only happens with the update setting, which I intend to
> change). Everything else should be taken from .gitmodules unless
> the user wants to override it. The only setting I'm not so sure
> about is the local branch setting, as that might have to propagate
> into the submodule.

I think copying into the submodule's out-of-tree config is the way to
go, because users won't always be driving the submodule from the
superproject.  If the settings are in the submodule's out-of-tree
config, everything will be consistent betwee stuff run from the
superproject and stuff run from submodule itself.  It also allows us
to use familiar configuration commands inside the submodule, and have
those automatically mapped back into the .gitmodules file for us.

> > In fact, I think life is easier for everyone if this is the
> > default, and we add a new option (submodule.<name>.sync = false)
> > that says “don't overwrite optional settings in my submodule's
> > out-of-tree config on checkout” for for folks who want to opt out.
> > Don't worry, this is not going to clobber people, because we'll be
> > syncing the other way too.
> 
> Yet another flag to make peoples life easier? I don't think so ;-)

I'm fine if there is no opt-out, and the syncing is mandatory, but I
imagine that folks who want a local (unshared, not in .gitmodules) URL
would complain.

> > Purely local metadata
> > ---------------------
> > 
> > Some metadata does not make sense in the superproject tree.  For
> > example, whether a submodule is interesting enough to checkout
> > (init/deinit) or whether you want to auto-sync optional metadata
> > .gitmodules defaults.  This metadata should live in the
> > superproject's out-of-tree config, and should not be stored in the
> > in-tree .gitmodules.
> 
> Not always. It makes a lot of sense to let upstream mark a
> submodule as "too big and you won't need it anyway" in the
> .gitmodules file.

Good.  Then there's no need for this special class of settings.

> > Since you *will* want to share the upstream URL, I proposed using
> > an explicit submodule.<name>.active setting to store the “do I
> > care” information [2], instead of overloading submodule.<name>.url
> > (I'd auto-sync the .gitmodule's submodule.<name>.url with the
> > subproject's remote.origin.url unless the user opted out of
> > .gitmodules syncing).
> 
> That is wrong as it would break horribly when you check out an old
> commit with a now dead submodule URL and that gets automatically
> synced.

If you've already checked out the submodule with a current URL, you
should already have the old commit locally, and Git will use it
without trying to re-fetch from the broken old URL.

> > Subsequent checkouts
> > --------------------
> > 
> > Now that we have strict linking between the submodule state (both
> > in-tree and out-of-tree configs) and the superproject tree (gitlink
> > and .gitmodules), changing between superproject branches is really
> > easy:
> > 
> > 1. Make sure the working tree is not dirty.  If it is, ask the user to
> >    either add-and-commit or stash, and then die to let them do so.
> 
> This condition is too hard, relax that to "a trivial merge can
> switch from current state to target state" and make it behave just
> like branch switching in the superproject. After all submodules
> should behave as much as possible like content of the superproject.

Sounds good to me.

> >  Clobber submodule
> >         configs and local branches at will (modulo
> >         submodule.<name>.sync), because any submodule configs that
> >         the user wanted to keep should have been added to the
> >         superproject branch earlier (or stashed).
> 
> I don't think I like this part, but I admit I do not fully
> understand what you mean here. Clobbering stuff the user did doesn't
> sound very nice.

It's fine because we forced them to commit or stash any (not trivially
mergable) changes before starting the checkout command.

> > Summary
> > -------
> > 
> > New .gitmodules options:
> > 
> > * submodule.<name>.local-branch, store the submodule's HEAD, must
> >   stay in sync for checkouts.
> 
> I'm still not convinced that the current branch setting couldn't be
> extended to carry that information, but no objections against
> configuring such a branch. But what do you mean with "must stay in
> sync for checkouts"?

That checkout-inducing commands should die if the .gitmodule's
local-branch and the submodule's HEAD don't match.

> > New .git/config options:
> > 
> > * submodule.<name>.active, for init/deinit.
> 
> I understand an option for automatic init (autoinit), but not for
> automatic deinit. Is the latter really useful?

This isn't auto-anything.  This is just “I think the submodule is
interesting, please turn it on” (i.e. I ran “git submodule init
<submod>”).

Only active submodules should get all the syncing, setup, and teardown
logic that goes along with submodule checkout.  Inactive submodules
are ignored.

> > I see no reason to add --recurse-submodule flags to 'git checkout'
> > (and merge, …).  Anything that happens post-clone should recurse
> > through submodules automatically, and use the
> > submodule.<name>.active setting to decide when recursion is
> > desired.
> 
> Backwards compatibility and testing. Let's first implement that and
> provide a config option to enable it for real world testing, and
> then let's discuss changing the default later.

Ok.

> > The current 'git submodule update --remote' would just be:
> > 
> >   $ git submodule foreach 'git pull'
> > 
> > because all of the local-branch checkouts would have already been
> > handled.
> 
> Nope, that does different things to submodules where "branch" isn't
> configured, right?

It does the same thing.  Without submodule.<name>.branch configured,
you just integrate the subproject's master.

> >  Similarly, a global push would be just:
> > 
> >   $ git submodule foreach 'git push'
> 
> What's wrong with:
> 
> $ git push --recurse-submodules=on-demand
> 
> And it'll push the superproject at the same time. Extra points for
> already being implemented ;-)

That's a strong argument ;).  I still don't think the new-in-1.7.4 UI
change will add value.  The new-in-1.7.7 --recurse-submodules=check
would still be useful.

> > I'd be happy to mock this up in shell, but only if anyone else
> > would be interested enough to review the implementation ;).  Then
> > I'll look into integrating the preferred model (this tightly bound
> > proposal, or v3's looser bindings, or <your idea here>) in C,
> > building on Jens and Jonathan's work.
> 
> The update modes (cleaning removed submodules and creating new ones)
> are better handled in my recursive checkout series. But I believe we
> can at least prototype the branch handling in shell.

I'll prototype it, and keep trying to convince you about the syncing
;).  I think the main arguments for syncing are:

* No divergent configs between superproject-initiated actions and
  submodule-initiated actions.
* No work clobbered, or accidentally uncommitted, due to syncing
  submodule -> superproject before checkout-inducing commands.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Tight submodule bindings
  2014-01-12  1:08                               ` Tight submodule bindings (was: Preferred local submodule branches) W. Trevor King
  2014-01-13 19:37                                 ` Tight submodule bindings Jens Lehmann
@ 2014-01-13 22:13                                 ` Junio C Hamano
  2014-01-14  2:44                                   ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-13 22:13 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder, Git

"W. Trevor King" <wking@tremily.us> writes:

> Additional metadata, the initial checkout, and syncing down
> -----------------------------------------------------------
>
> However, folks who do local submodule development will care about
> which submodule commit is responsible for that tree, because that's
> going to be the base of their local development.  They also care about
> additional out-of-tree information, including the branch that commit
> is on.

Well, please step back a bit.

They do not have to care about what local branch they use to build
follow-up work based on that commit.  In fact, they would want to be
able to develop more than one histories on top, which means more
than one branches they can name themselves.

The only thing they care about is where the result of their
development _goes_, that is the URL and the branch of the remote
they are pushing back to.

I have a feeling that this is not specific for submodules---if you
did this:

	git init here
        cd here
        git fetch $there master
        git reset --hard FETCH_HEAD

and are given the resulting working tree to start hacking on, you
would not know where the history came from, or where your result
wants to go.  

So "the branch that commit is on" is a wrong thing to focus on.
"The branch the history built on top of the commit wants to go" may
be closer and these two are different.

>  For already-initialized submodules, there are existing places
> in the submodule config to store this configuration:
>
> 1. HEAD for the checked-out branch,
> 2. branch.<name>.remote → remote.<name>.url for the upstream
>    subproject URL,
> 4. branch.<name>.rebase (or pull.rebase) to prefer rebase over merge
>    for integration,
> 5. …

What happened to 3 ;-)?

And also branch.<name>.merge may say on which of _their_ branch the
commit you learn in the superproject tree would be found.  If you
are using centralized workflow, that would be the branch at your
central repository to update with your push, too.

In any case, "local-branch" is wrong from two aspects:

 1. (obvious) It does not follow our naming convention not to use
    dashed-names for configuration variables.

 2. You do not care about the names you use locally.  The only thing
    you care about is where people meet at the central repository,
    i.e. where your result is pushed to.


> Syncing up
> ----------
>
> In the previous section I explained how data should flow from
> .gitmodules into out-of-tree configs.

s/should/you think should/, I think, but another way may be not to
copy and read from there, which may be a lot simpler.  Then upon
switching branches of top-level superproject (which would update
.gitmodules to the version on the new branch), you may get different
settings automatically.  But see below.

> ...  Since you *will* want to share the upstream URL, I
> proposed using an explicit submodule.<name>.active setting to store
> the “do I care” information [2], instead of overloading
> submodule.<name>.url (I'd auto-sync the .gitmodule's
> submodule.<name>.url with the subproject's remote.origin.url unless
> the user opted out of .gitmodules syncing).

It may not be a good idea to blindly update to whatever happens to
be in .gitmodules, especially once submodule.*.url is initialized.

I think we would need a bit more sophisticated mechanism than "use
from .git/config if set, otherwise use from .gitmodules", at least
for the URL.  It may not be limited to the URL, and other pieces
of metainformation about submodules may need similar handling, but
I'd refrain from extending the scope of discussion needlessly at
this point.

Imagine that your embedded appliance project used to use a submodule
from git://k.org/linux-2.6 as its kernel component and now the
upstream of it is instead called just git://k.org/linux; the URL
specified by submodule.kernel.url in .gitmodules for the entry
submodule.kernel.path=kernel would have changed from the former to
the latter sometime in the superproject's history.  Switching back
to an old version in the superproject to fix an old bug in the
maintenance track of the superproject would still want to push
associated fixes to the kernel to k.org/linux, not linux-2.6, the
latter of which may now be defunct [*1*].  One way to make it work
semi-automatically is to keep track of what the user has seen in
.gitmodules and offer chances to update entries in .git/config.  If
you cloned the superproject recently, you would only know about the
new git://k.org/linux URL and that would be copied to .git/config
(which the current code does).  In addition, you would remember that
we saw git://k.org/linux URL (which the current code does not).
Upon switching back to an old version, we could notice that the URL
in .gitmodules, which is git://k.org/linux-2.6, is not something the
user has seen, and at that point we could ask the user to tell us
what URL should be used, record the answer _and_ the fact that we
saw that old URL as well.  Then until the superproject updates the
URL the next time to a value that we have never seen, the user can
keep using the right URL without being asked [*2*].


> 2. Checkout the new superproject branch.
>
>    2.1. For each old submodule that doesn't exist in the new branch,
>         blow away the submodule directory (assuming a new-style
>         .git/modules/… layout, and not an old-style submod/.git/…
>         layout).

Sure.

>    2.2. For each gitlinked submodule that didn't exist in the old
>         branch, setup the submodule as if you were doing the initial
>         cloning checkout (forcing a new local-branch to point at the
>         gitlinked commit).  If you find local out-of-tree
>         *superproject* configs that conflict with the .gitmodules
>         values, prefer the superproject configs.  Clobber submodule
>         configs and local branches at will (modulo
>         submodule.<name>.sync), because any submodule configs that the
>         user wanted to keep should have been added to the superproject
>         branch earlier (or stashed).

See above.


[Footnote]

*1* On the other hand, the switch of the submodule URL in the
superproject may have been between two separate projects (e.g. you
used to build your embedded appliance using BSD kernel but recent
versions use Linux kernel)---in such a project, you would want the
submodule URL to follow what is in .gitmodules when you switch
between old and new versions in the superproject.  But our
recommendation in such a case is to use different names for
submodules that is bound at the same path in the superproject so
that we can keep them as two separate repositories in .git/mdoules/
of the superproject.  So at least for the URL, there is no reason to
use the old version that appears in .gitmodules of the superproject
even when you checkout an old version of it.

*2* This "remembering" may have to be more than "have we seen this"
one-bit per different values. For URL, I think the one-bit is
enough, but for other things, it might make sense to keep track of
"In the version of superproject with X in .gitmodules, the user
wants to use value Y" for each values X the user has seen.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Tight submodule bindings
  2014-01-13 22:13                                 ` Junio C Hamano
@ 2014-01-14  2:44                                   ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-14  2:44 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder, Git

[-- Attachment #1: Type: text/plain, Size: 6868 bytes --]

On Mon, Jan 13, 2014 at 02:13:46PM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> 
> > Additional metadata, the initial checkout, and syncing down
> > -----------------------------------------------------------
> >
> > However, folks who do local submodule development will care about
> > which submodule commit is responsible for that tree, because
> > that's going to be the base of their local development.  They also
> > care about additional out-of-tree information, including the
> > branch that commit is on.
> 
> Well, please step back a bit.
> 
> They do not have to care about what local branch they use to build
> follow-up work based on that commit.

They do if they want to checkout the banch out again later, before
pushing it somewhere public.

> In fact, they would want to be able to develop more than one
> histories on top, which means more than one branches they can name
> themselves.

Agreed, bug for each superproject branch they will still have a single
submodule branch that should be checked out by default when they
checkout that superproject branch.

> The only thing they care about is where the result of their
> development _goes_, that is the URL and the branch of the remote
> they are pushing back to.

Maybe they're just doing local development?  I think the remote
branch(es) you pull from and push to are important, but not the only
thing you might care about.

> I have a feeling that this is not specific for submodules---if you
> did this:
> 
> 	git init here
>         cd here
>         git fetch $there master
>         git reset --hard FETCH_HEAD
> 
> and are given the resulting working tree to start hacking on, you
> would not know where the history came from, or where your result
> wants to go.  
> 
> So "the branch that commit is on" is a wrong thing to focus on.
> "The branch the history built on top of the commit wants to go" may
> be closer and these two are different.

That makes sense.  I don't think the former (as distinct from the
latter) is of any interest to anybody.  I don't care what the branch
name was when the past history was developed.  I don't even really
care about the new branch name.  I do care that checking out a
superproject branch gives me the same branch (with pull/push configs,
etc.) that I had the last time I was on that superproject branch.

> >  For already-initialized submodules, there are existing places
> > in the submodule config to store this configuration:
> >
> > 1. HEAD for the checked-out branch,
> > 2. branch.<name>.remote → remote.<name>.url for the upstream
> >    subproject URL,
> > 4. branch.<name>.rebase (or pull.rebase) to prefer rebase over merge
> >    for integration,
> > 5. …
> 
> What happened to 3 ;-)?

I can't count? :p

> In any case, "local-branch" is wrong from two aspects:
> 
>  1. (obvious) It does not follow our naming convention not to use
>     dashed-names for configuration variables.

I'll use localBranch in my mockup ;).  Although skimming through
config.txt shows a number of alllowercase settings as well as
camelCase.

>  2. You do not care about the names you use locally.  The only thing
>     you care about is where people meet at the central repository,
>     i.e. where your result is pushed to.

I also care about local-checkout consistency, as described above.

> > Syncing up
> > ----------
> >
> > In the previous section I explained how data should flow from
> > .gitmodules into out-of-tree configs.
> 
> s/should/you think should/, I think, but another way may be not to
> copy and read from there, which may be a lot simpler.  Then upon
> switching branches of top-level superproject (which would update
> .gitmodules to the version on the new branch), you may get different
> settings automatically.

That only works for superproject-level commands that know about the
.gitmodules file.  If you cd into the submodule and work there
directly, your actions will be using the submodule's out-of-tree
config.  I think most of the time folks will want those out-of-tree
configs to match the settings in the superproject's .gitmodules, hence
the submodule.<name>.sync defaulting to true.

> > ...  Since you *will* want to share the upstream URL, I proposed
> > using an explicit submodule.<name>.active setting to store the “do
> > I care” information [2], instead of overloading
> > submodule.<name>.url (I'd auto-sync the .gitmodule's
> > submodule.<name>.url with the subproject's remote.origin.url
> > unless the user opted out of .gitmodules syncing).
> 
> It may not be a good idea to blindly update to whatever happens to
> be in .gitmodules, especially once submodule.*.url is initialized.

Why not?  We're blindly updating it to the value that was previously
pulled out of the submodule's out-of-tree config.  If the user doesn't
like what's happening to .gitmodules upstream and doesn't want to keep
a patched version locally, they can always turn off
submodule.<name>.sync.

> Imagine that your embedded appliance project used to use a submodule
> from git://k.org/linux-2.6 as its kernel component and now the
> upstream of it is instead called just git://k.org/linux; the URL
> specified by submodule.kernel.url in .gitmodules for the entry
> submodule.kernel.path=kernel would have changed from the former to
> the latter sometime in the superproject's history.  Switching back
> to an old version in the superproject to fix an old bug in the
> maintenance track of the superproject would still want to push
> associated fixes to the kernel to k.org/linux, not linux-2.6, the
> latter of which may now be defunct [*1*].

The checkout would work (because the old gitlinked commit is already
in the local repository), but the push would not.  I don't think it
would be difficult to recover from that manually (and just specify the
full URL when pushing).  You could also:

1. Commit your fix.
2. Checkout a more modern superproject branch (which will load the
   current URL into the submodule's config).
3. Push the fix.
4. Continue to work on the modern branch.

That doesn't sound much more difficult than the ideal:

1. Commit your fix.
2. Push the fix.
3. Checkout a more modern superproject branch (which will load the
   current URL into the submodule's config).
4. Continue to work on the modern branch.

If you expect to be back making more superproject/subproject joint
bugfixes in future, I think it makes sense to start a maintenance
branch of the superproject that updates the .gitmodules URL to point
at the modern location.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-09 22:18                                                           ` W. Trevor King
@ 2014-01-14 10:24                                                             ` Heiko Voigt
  2014-01-14 16:57                                                               ` W. Trevor King
  2014-01-14 21:46                                                               ` Re: " Heiko Voigt
  0 siblings, 2 replies; 144+ messages in thread
From: Heiko Voigt @ 2014-01-14 10:24 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

Hi,

On Thu, Jan 09, 2014 at 02:18:40PM -0800, W. Trevor King wrote:
> On Thu, Jan 09, 2014 at 10:40:52PM +0100, Jens Lehmann wrote:
> > Am 09.01.2014 20:55, schrieb W. Trevor King:
> > > On Thu, Jan 09, 2014 at 08:23:07PM +0100, Jens Lehmann wrote:
> > >> Am 09.01.2014 18:32, schrieb W. Trevor King:
> > >>>> later updates,
> > >>>
> > >>> The same thing that currently happens, with the exception that
> > >>> checkout-style updates should use reset to update the
> > >>> currently-checked out branch (or detached-HEAD), instead of
> > >>> always detaching the HEAD.
> > >>
> > >> Won't the user loose any modifications to his local branch here?
> > > 
> > > They just called for a checkout-style update, so yes.  If they
> > > want to keep local modifications, chose an integration mode that
> > > preserves local changes.
> > 
> > Hmm, as current "submodule updates" already makes it too easy to
> > loose commits, this does not look right to me. I'd prefer to stop at
> > that point and tell the user what he can do to solve the conflict.
> 
> Users who are worried about loosing local updates should not be using
> a checkout-style updates.  If they are using a checkout-style update,
> and they ask for an update, they're specifically requesting that we
> blow away their local work and checkout/reset to the new sha1.
> Solving update conflicts is the whole point of the non-checkout update
> modes.

But checkout is different from reset --hard in that it does not blow
away local uncommitted changes. Please see below.

> > > Maybe you meant "for checkout I can easily overwrite the local
> > > changes with the upstream branch", which is what I understand
> > > checkout to do.
> > 
> > But which I find really unfriendly and would not like to see in a
> > new feature. We should protect the user from loosing any local
> > changes, not simply throw them away. Recursive update makes sure it
> > won't overwrite any local modification before it checks out anything
> > and will abort before doing so (unless forced of course).
> 
> If you want to get rid of checkout-mode updates, I'm fine with that.
> However, I don't think it supports use-cases like Heiko's (implied) “I
> don't care what's happening upstream, I never touch that submodule,
> just checkout what the superproject maintainer says should be checked
> out for this branch.  Even if they have been rebasing or whatever”
> [3].

I never stated that in that post. Even with the current checkout-mode
updates you'll never loose local modifications (without force) that are
not committed. I think you have to distinguish between local
modifications in the worktree and the ones that are committed.

The recursive checkout Jens is working on is simply implementing the
current checkout-mode to the places where the superproject checks out
its files. That way submodules get checked out when the superproject is
checked out. If the submodule does not match the sha1 registered in the
superproject it either stays there (if the checkout would not need to
update the submodule) or (if checkout would need to update) git will not
do the checkout and bail out with "you have local modifications to ... .

I think the whole recursive checkout topic is already complicated enough
as it is so we should currently not add anything from this discussion to
it until it is cleaned up and merged. We also need recursive fetch for
that which I am planning to work on as soon as we settle this
discussion. I will write another post about how I think we should/can
proceed.

> > or be asked to resolve the conflict manually when "checkout" is
> > configured and the branches diverged.
> 
> I still think that checkout-mode updates should be destructive.  See
> my paraphrased-version of Heiko's use case above.  How are they going
> to resolve this manually?  Merge or rebase?  Why weren't they using
> that update mode in the first place?

I strongly disagree. They should only be destructive in the sense that
another commit get checked out but never loose local modifications.

> [1]: http://article.gmane.org/gmane.comp.version-control.git/240251
> [2]: http://article.gmane.org/gmane.comp.version-control.git/240248
> [3]: http://article.gmane.org/gmane.comp.version-control.git/240013

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 10:24                                                             ` Heiko Voigt
@ 2014-01-14 16:57                                                               ` W. Trevor King
  2014-01-14 20:58                                                                 ` Heiko Voigt
  2014-01-14 21:46                                                               ` Re: " Heiko Voigt
  1 sibling, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-14 16:57 UTC (permalink / raw)
  To: Heiko Voigt
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 3556 bytes --]

On Tue, Jan 14, 2014 at 11:24:45AM +0100, Heiko Voigt wrote:
> On Thu, Jan 09, 2014 at 02:18:40PM -0800, W. Trevor King wrote:
> > Users who are worried about loosing local updates should not be
> > using a checkout-style updates.  If they are using a
> > checkout-style update, and they ask for an update, they're
> > specifically requesting that we blow away their local work and
> > checkout/reset to the new sha1.  Solving update conflicts is the
> > whole point of the non-checkout update modes.
> 
> But checkout is different from reset --hard in that it does not blow
> away local uncommitted changes. Please see below.

Ah, good point.  We should definately die if there are local
uncommitted changes.

> > On Thu, Jan 09, 2014 at 10:40:52PM +0100, Jens Lehmann wrote:
> > > Am 09.01.2014 20:55, schrieb W. Trevor King:
> > > > Maybe you meant "for checkout I can easily overwrite the local
> > > > changes with the upstream branch", which is what I understand
> > > > checkout to do.
> > > 
> > > But which I find really unfriendly and would not like to see in
> > > a new feature. We should protect the user from loosing any local
> > > changes, not simply throw them away. Recursive update makes sure
> > > it won't overwrite any local modification before it checks out
> > > anything and will abort before doing so (unless forced of
> > > course).
> > 
> > If you want to get rid of checkout-mode updates, I'm fine with
> > that.  However, I don't think it supports use-cases like Heiko's
> > (implied) “I don't care what's happening upstream, I never touch
> > that submodule, just checkout what the superproject maintainer
> > says should be checked out for this branch.  Even if they have
> > been rebasing or whatever” [3].
> 
> I never stated that in that post.

Sorry for misunderstanding.  I think I'm just unclear on your
workflow?

> The recursive checkout Jens is working on is simply implementing the
> current checkout-mode to the places where the superproject checks
> out its files. That way submodules get checked out when the
> superproject is checked out. If the submodule does not match the
> sha1 registered in the superproject it either stays there (if the
> checkout would not need to update the submodule) or (if checkout
> would need to update) git will not do the checkout and bail out with
> "you have local modifications to ... .

Sounds good to me as far as it goes.  I think it misses the “what
should we do if the gitlinked hashes are different” case, because the
checkout will always leave you with a detached HEAD.

> > > or be asked to resolve the conflict manually when "checkout" is
> > > configured and the branches diverged.
> > 
> > I still think that checkout-mode updates should be destructive.
> > See my paraphrased-version of Heiko's use case above.  How are
> > they going to resolve this manually?  Merge or rebase?  Why
> > weren't they using that update mode in the first place?
> 
> I strongly disagree. They should only be destructive in the sense
> that another commit get checked out but never loose local
> modifications.

I think the key I'm missing is an example workflow where a developer
wants to make local submodule changes, but also wants to use
checkout-mode updates instead of merge/rebase updates.  Can you sketch
one out for me?

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 16:57                                                               ` W. Trevor King
@ 2014-01-14 20:58                                                                 ` Heiko Voigt
  2014-01-14 21:42                                                                   ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-14 20:58 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

On Tue, Jan 14, 2014 at 08:57:09AM -0800, W. Trevor King wrote:
> > > On Thu, Jan 09, 2014 at 10:40:52PM +0100, Jens Lehmann wrote:
> > > > Am 09.01.2014 20:55, schrieb W. Trevor King:
> > > > > Maybe you meant "for checkout I can easily overwrite the local
> > > > > changes with the upstream branch", which is what I understand
> > > > > checkout to do.
> > > > 
> > > > But which I find really unfriendly and would not like to see in
> > > > a new feature. We should protect the user from loosing any local
> > > > changes, not simply throw them away. Recursive update makes sure
> > > > it won't overwrite any local modification before it checks out
> > > > anything and will abort before doing so (unless forced of
> > > > course).
> > > 
> > > If you want to get rid of checkout-mode updates, I'm fine with
> > > that.  However, I don't think it supports use-cases like Heiko's
> > > (implied) “I don't care what's happening upstream, I never touch
> > > that submodule, just checkout what the superproject maintainer
> > > says should be checked out for this branch.  Even if they have
> > > been rebasing or whatever” [3].
> > 
> > I never stated that in that post.
> 
> Sorry for misunderstanding.  I think I'm just unclear on your
> workflow?

Yes probably. We mostly use submodules for shared code and for tracking
external libraries. For the shared code we want to make sure that
the changes that come from one project do not break anything in another
project that also uses that code so the submodules are maintained and
reviewed separately and ideally contain tests for the expected
functionality.

A typical workflow where a feature in a project needs some extension or
change in a submodule goes like this:

1. The developer does his changes locally implementing everything
   needed. To commit he creates a local branch in the submodule and in
   the superproject (most of the times from the current HEAD that is
   checked out).

2. For convenience I usually commit the resulting commit sha1 of the
   submodule in the commit that needs the change. That way when I switch
   to a different branch and back I can simply say: git submodule update
   and get the correct code everywhere.

3. Once done with the whole feature I first do the review process
   (adding any missing tests to ensure my change does not break, ...)
   for the submodule to get the feature branch merged into a stable one.
   In our superproject only commits sha1 from a stable branch are
   allowed so the submodule change needs to be reviewed first.

4. Once the change is in a stable branch in the submodule I then update
   the commit sha1 link in the superproject that needs the change. That
   is usually done by rebasing the branch in the superproject and
   registering the new stable branch (typically master).

5. Then I proceed with the review process in the superproject as if it
   was a normal change without a submodule.

Thats our main use case.

> > The recursive checkout Jens is working on is simply implementing the
> > current checkout-mode to the places where the superproject checks
> > out its files. That way submodules get checked out when the
> > superproject is checked out. If the submodule does not match the
> > sha1 registered in the superproject it either stays there (if the
> > checkout would not need to update the submodule) or (if checkout
> > would need to update) git will not do the checkout and bail out with
> > "you have local modifications to ... .
> 
> Sounds good to me as far as it goes.  I think it misses the “what
> should we do if the gitlinked hashes are different” case, because the
> checkout will always leave you with a detached HEAD.
> 
> > > > or be asked to resolve the conflict manually when "checkout" is
> > > > configured and the branches diverged.
> > > 
> > > I still think that checkout-mode updates should be destructive.
> > > See my paraphrased-version of Heiko's use case above.  How are
> > > they going to resolve this manually?  Merge or rebase?  Why
> > > weren't they using that update mode in the first place?
> > 
> > I strongly disagree. They should only be destructive in the sense
> > that another commit get checked out but never loose local
> > modifications.
> 
> I think the key I'm missing is an example workflow where a developer
> wants to make local submodule changes, but also wants to use
> checkout-mode updates instead of merge/rebase updates.  Can you sketch
> one out for me?

How about the use-case I sketched above? Is that what you are searching
for? In that use-case we have to update to the new master after a
submodule change was merged. That could be achieved by

	git submodule update --remote <submodule>

with the wanted stable branch configured. But in practise something
along the lines of

	(cd <submodule> && git checkout origin/<stable>)

is usually used and simple enough.

We have a tool in our git gui configuration that does

	git submodule foreach 'git fetch && git checkout origin/master'

which can be used by the maintainer before a release to ensure that all
submodules are up-to-date. But in practise it turn out that all
submodules are fairly current since everyone is adding features to the
quite frequently and thus pulling in the current version automatically.

I hope that draws a clear picture of how we use submodules.

Cheers Heiko

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 20:58                                                                 ` Heiko Voigt
@ 2014-01-14 21:42                                                                   ` W. Trevor King
  2014-01-14 22:19                                                                     ` Heiko Voigt
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-14 21:42 UTC (permalink / raw)
  To: Heiko Voigt
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 2962 bytes --]

On Tue, Jan 14, 2014 at 09:58:30PM +0100, Heiko Voigt wrote:
> A typical workflow where a feature in a project needs some extension or
> change in a submodule goes like this:
> 
> 1. The developer does his changes locally implementing everything
>    needed. To commit he creates a local branch in the submodule and in
>    the superproject (most of the times from the current HEAD that is
>    checked out).
> 
> 2. For convenience I usually commit the resulting commit sha1 of the
>    submodule in the commit that needs the change. That way when I switch
>    to a different branch and back I can simply say: git submodule update
>    and get the correct code everywhere.

This checkout functionality is exactly what my
submodule.<name>.localBranch is designed to automate [1].  I think
that should be different from integrating local and external changes,
which is what 'git submodule update' is about.  For example, after you
run 'git submodule update' here, you'll have your original commit
checked out, but you'll be on a detached HEAD instead of your original
branch.  If you want to further develop the submodule feature branch,
you currently have to cd into the submodule and check the branch out
by hand.

> How about the use-case I sketched above? Is that what you are searching
> for? In that use-case we have to update to the new master after a
> submodule change was merged. That could be achieved by
> 
> 	git submodule update --remote <submodule>
> 
> with the wanted stable branch configured. But in practise something
> along the lines of
> 
> 	(cd <submodule> && git checkout origin/<stable>)
> 
> is usually used and simple enough.

The “gitlinked commits must be in the subproject's master” rule
protects you from blowing stuff away here.  You could use rebase- or
merge-style integration as well, assuming the maintainer didn't have
dirty local work in their submodule.

> We have a tool in our git gui configuration that does
> 
> 	git submodule foreach 'git fetch && git checkout origin/master'

I agree that with 'submodule update' seems superfluous.  With proper
out-of-tree submodule configs specifying remote URLs and upstream
branches,

  git submodule foreach 'git fetch && git checkout @{upstream}'

(or merge/rebase/…) should cover this case more generically and with
less mental overhead.

> I hope that draws a clear picture of how we use submodules.

It's certainly clearer, thanks :).  I'm not sure where checkout-mode
is specifically important, though.  In your step-2, it doesn't restore
your original branch.  In your “update the superproject's master”
step, you aren't even using 'submodule update' :p.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240336

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 10:24                                                             ` Heiko Voigt
  2014-01-14 16:57                                                               ` W. Trevor King
@ 2014-01-14 21:46                                                               ` Heiko Voigt
  2014-01-14 22:22                                                                 ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-14 21:46 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

Hi,

On Tue, Jan 14, 2014 at 11:24:45AM +0100, Heiko Voigt wrote:
> I will write another post about how I think we should/can proceed.

and here is my suggestion how we should proceed.

I think there have been many interesting ideas in this thread but IMO
some of them tried to achieve a little bit to much and were not clear
enough. I am a fan of: Keep it as simple as possible, but *no simpler*.
I think some ideas where going in the "make it to simple" direction.

Take my idea for feature branch support from here[1]. After thinking more
thoroughly it still too many corner cases. E.g. it is way to easy to
accidentally merge the feature branch configuration into the stable branch. But
we want to support the user properly so we need to catch stuff like that.

Submodules are separate projects. There is a boundary between
superproject and submodule and IMO its there for a good reason. E.g.
take the typical "shared code" use-case. If A and B are using C
then both want to make sure a change from A does not break B's
expectations and vice versa. Thats were you usually write unit tests in
C for: Ensure that the expectations are met. The more users of the code
the higher the quality and thus the boundary for bad code should be.

I would like to step back a bit and get back to the original problem at hand:
Francescos original use case of an attached head for direct commits on a stable
branch in a submodule. How about we finish discussing the exact solution of
that first. AFAIK that is already solved with the following:

 * Trevor's first patch[2] to create a branch on initial clone of a submodule
 * A possibly a configuration variable for --remote so it can be
   set as the default update method
 * Combined with submodule.<name>.update=merge/rebase

That should be all (and IIRC Francesco agreed) needed for that use-case.

Lets not implement more than currently is needed. We can revisit the ideas once
some other real use-case manifests. Also we (Jens and I) would first like to
proceed with the recursive checkout / fetch (for which the plan is clear) as
the next complicated step.

Once that is done and people gain some experience with it we can still extend
further.

What do you think?

Cheers Heiko

[1] http://article.gmane.org/gmane.comp.version-control.git/240178/
[2] http://article.gmane.org/gmane.comp.version-control.git/239921

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 21:42                                                                   ` W. Trevor King
@ 2014-01-14 22:19                                                                     ` Heiko Voigt
  2014-01-14 22:39                                                                       ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Heiko Voigt @ 2014-01-14 22:19 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

On Tue, Jan 14, 2014 at 01:42:09PM -0800, W. Trevor King wrote:
> On Tue, Jan 14, 2014 at 09:58:30PM +0100, Heiko Voigt wrote:
> > A typical workflow where a feature in a project needs some extension or
> > change in a submodule goes like this:
> > 
> > 1. The developer does his changes locally implementing everything
> >    needed. To commit he creates a local branch in the submodule and in
> >    the superproject (most of the times from the current HEAD that is
> >    checked out).
> > 
> > 2. For convenience I usually commit the resulting commit sha1 of the
> >    submodule in the commit that needs the change. That way when I switch
> >    to a different branch and back I can simply say: git submodule update
> >    and get the correct code everywhere.
> 
> This checkout functionality is exactly what my
> submodule.<name>.localBranch is designed to automate [1].  I think
> that should be different from integrating local and external changes,
> which is what 'git submodule update' is about.  For example, after you
> run 'git submodule update' here, you'll have your original commit
> checked out, but you'll be on a detached HEAD instead of your original
> branch.  If you want to further develop the submodule feature branch,
> you currently have to cd into the submodule and check the branch out
> by hand.

Yes and thats exactly what my idea was about but after further thinking
am afraid that this is the wrong place. I am not sure but afraid as I
wrote in the other post that it would be way to dangerous to accidentally
merge these changes in. We would need something to prevent this
configuration from ever entering a stable branch.

Another solution (and completely different approach) would be to have
something that is outside of the tree and actually attached to a
branchname. E.g. at the gitmerge last year I though it would be nice to
have a place for a description for a branch inside git. In a short
discussion we were envisioning a special ref like the notes trees but
allowing to attach and describe branches. That place could also be where
we could store such a configuration. Once the branchname ceases to exist
so would the configuration.

I know this is a completely different piece of work so I am not sure
whether we want to pursue it at the moment. But at the moment I think
this would actually be the correct solution.

> > How about the use-case I sketched above? Is that what you are searching
> > for? In that use-case we have to update to the new master after a
> > submodule change was merged. That could be achieved by
> > 
> > 	git submodule update --remote <submodule>
> > 
> > with the wanted stable branch configured. But in practise something
> > along the lines of
> > 
> > 	(cd <submodule> && git checkout origin/<stable>)
> > 
> > is usually used and simple enough.
> 
> The “gitlinked commits must be in the subproject's master” rule
> protects you from blowing stuff away here.  You could use rebase- or
> merge-style integration as well, assuming the maintainer didn't have
> dirty local work in their submodule.

No we can't. Developers are not allowed to merge in some submodules.
The most central ones have maintainers and only they are allowed to
merge into the stable branch. So we need to track exact commits on the
stable branch, no local merge (except the fast-forward case of course)
allowed. Thats why the developer does an exact checkout here.

> > We have a tool in our git gui configuration that does
> > 
> > 	git submodule foreach 'git fetch && git checkout origin/master'
> 
> I agree that with 'submodule update' seems superfluous.  With proper
> out-of-tree submodule configs specifying remote URLs and upstream
> branches,
> 
>   git submodule foreach 'git fetch && git checkout @{upstream}'
> 
> (or merge/rebase/…) should cover this case more generically and with
> less mental overhead.
> 
> > I hope that draws a clear picture of how we use submodules.
> 
> It's certainly clearer, thanks :).  I'm not sure where checkout-mode
> is specifically important, though.  In your step-2, it doesn't restore
> your original branch.  In your “update the superproject's master”
> step, you aren't even using 'submodule update' :p.

Ah sorry I though that was clear. The "others" are using submodule update ;-)

I mean someone who gets stuff from a stable superproject branch by
either rebasing their development branch or updating their local copy of
a stable branch (e.g. master) by using

	git checkout master
	git pull --ff --ff-only
	git submodule update --init --recursive

This also prevents the pure "updaters" from creating unnecessary merges.

Cheers Heiko

> [1]: http://article.gmane.org/gmane.comp.version-control.git/240336

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 21:46                                                               ` Re: " Heiko Voigt
@ 2014-01-14 22:22                                                                 ` W. Trevor King
  2014-01-14 22:42                                                                   ` Heiko Voigt
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-14 22:22 UTC (permalink / raw)
  To: Heiko Voigt
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 3445 bytes --]

On Tue, Jan 14, 2014 at 10:46:08PM +0100, Heiko Voigt wrote:
> I would like to step back a bit and get back to the original problem
> at hand: Francescos original use case of an attached head for direct
> commits on a stable branch in a submodule. How about we finish
> discussing the exact solution of that first. AFAIK that is already
> solved with the following:
> 
>  * Trevor's first patch[2] to create a branch on initial clone of a submodule

v1 broke a bunch of tests.  Are you ok with v2 [1]?  v2 still needs a
clearer commit message, a test, and a possible transition to
triggering on non-checkout submodule.<name>.update instead of
non-empty submodule.<name>.branch [2].

> That should be all (and IIRC Francesco agreed) needed for that use-case.

That was my understanding [3] ;).

> Lets not implement more than currently is needed. We can revisit the
> ideas once some other real use-case manifests.

I have most of a real use case already.  I have a repository with
submodules in one branch (master) and a subtree version in another
(assembled) [4].  The *tree* is the same in each case, so I have to
'git rm -rf .'  to clear the submodules out of master before I can
checkout assembled.

  $ git checkout assembled
  error: The following untracked working tree files would be overwritten by checkout:
          modular/README.md
          modular/shell/README.md
          …
  $ git rm -rf .
  $ git checkout assembled

That leaves some extra stuff removed:

  $ git status
  On branch assembled
  Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

          deleted:    .gitignore
          deleted:    .mailmap
          deleted:    CONTRIBUTING.md
          deleted:    LICENSE.md
          deleted:    instructor.md

so I need to check that out by hand:

  $ git reset --hard HEAD

Now I can work in the assembled branch.  Going back to master is a bit
less tedious:

  $ git checkout master
  $ git submodule update --recursive

Luckily for me, I don't have a third superproject branch where the
submodules are on a different, so the submodule's HEADs are preserved.
As I understand it, the new recursive checkout functionality [5] would
checkout my submodules with detached HEADs.  The fact that they are
only accidentally preserved now is not comforting ;).

> Also we (Jens and I) would first like to proceed with the recursive
> checkout / fetch (for which the plan is clear) as the next
> complicated step.
> 
> Once that is done and people gain some experience with it we can
> still extend further.

This is quite reasonable.  Given the need for backwards compatibility,
I just wanted to make sure my ideal UI was clear before we went
forward.  There's no need to break fingers twice ;), but if tight
binding with localBranch is too big a chunk to bite off now, I'm happy
to kick that can down the road.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/239967
[2]: http://article.gmane.org/gmane.comp.version-control.git/239973
[3]: http://article.gmane.org/gmane.comp.version-control.git/240139
[4]: (gitweb) http://git.tremily.us/?p=swc-boot-camp.git
[5]: http://article.gmane.org/gmane.comp.version-control.git/239695

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 22:19                                                                     ` Heiko Voigt
@ 2014-01-14 22:39                                                                       ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-14 22:39 UTC (permalink / raw)
  To: Heiko Voigt
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 3020 bytes --]

On Tue, Jan 14, 2014 at 11:19:07PM +0100, Heiko Voigt wrote:
> On Tue, Jan 14, 2014 at 01:42:09PM -0800, W. Trevor King wrote:
> > The “gitlinked commits must be in the subproject's master” rule
> > protects you from blowing stuff away here.  You could use rebase- or
> > merge-style integration as well, assuming the maintainer didn't have
> > dirty local work in their submodule.
> 
> No we can't. Developers are not allowed to merge in some submodules.
> The most central ones have maintainers and only they are allowed to
> merge into the stable branch. So we need to track exact commits on the
> stable branch, no local merge (except the fast-forward case of course)
> allowed. Thats why the developer does an exact checkout here.

Because both sides of the merge/rebase are required (by your rule) to
be in the subproject's master, you're guaranteed to have a
fast-forward merge/rebase.

> > > We have a tool in our git gui configuration that does
> > > 
> > > 	git submodule foreach 'git fetch && git checkout origin/master'
> > 
> > I agree that with 'submodule update' seems superfluous.  With proper
> > out-of-tree submodule configs specifying remote URLs and upstream
> > branches,
> > 
> >   git submodule foreach 'git fetch && git checkout @{upstream}'
> > 
> > (or merge/rebase/…) should cover this case more generically and with
> > less mental overhead.
> > 
> > > I hope that draws a clear picture of how we use submodules.
> > 
> > It's certainly clearer, thanks :).  I'm not sure where checkout-mode
> > is specifically important, though.  In your step-2, it doesn't restore
> > your original branch.  In your “update the superproject's master”
> > step, you aren't even using 'submodule update' :p.
> 
> Ah sorry I though that was clear. The "others" are using submodule update ;-)
> 
> I mean someone who gets stuff from a stable superproject branch by
> either rebasing their development branch or updating their local copy of
> a stable branch (e.g. master) by using
> 
> 	git checkout master
> 	git pull --ff --ff-only
> 	git submodule update --init --recursive
> 
> This also prevents the pure "updaters" from creating unnecessary merges.

Right.  Folks who don't do local development in their submodules can
get away with checkout-mode updates and their detached HEADs.
Assuming the upstream superproject only advances the gitlinked commits
using fast-forwards, they could equally well use any of the other
update modes, but there is no need for them to make that assumption.
*This* is the use case that I think the current recursive-checkout
facilitates [1].  I don't think it helps folks who are actually doing
submodule development on branches from within their superproject.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/239695

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 22:22                                                                 ` W. Trevor King
@ 2014-01-14 22:42                                                                   ` Heiko Voigt
  2014-01-15  0:02                                                                     ` Francesco Pretto
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
  0 siblings, 2 replies; 144+ messages in thread
From: Heiko Voigt @ 2014-01-14 22:42 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Git, Jonathan Nieder

On Tue, Jan 14, 2014 at 02:22:31PM -0800, W. Trevor King wrote:
> On Tue, Jan 14, 2014 at 10:46:08PM +0100, Heiko Voigt wrote:
> > I would like to step back a bit and get back to the original problem
> > at hand: Francescos original use case of an attached head for direct
> > commits on a stable branch in a submodule. How about we finish
> > discussing the exact solution of that first. AFAIK that is already
> > solved with the following:
> > 
> >  * Trevor's first patch[2] to create a branch on initial clone of a submodule
> 
> v1 broke a bunch of tests.  Are you ok with v2 [1]?  v2 still needs a
> clearer commit message, a test, and a possible transition to
> triggering on non-checkout submodule.<name>.update instead of
> non-empty submodule.<name>.branch [2].

Will have a look.

> > That should be all (and IIRC Francesco agreed) needed for that use-case.
> 
> That was my understanding [3] ;).

Thanks for the pointer.

> > Lets not implement more than currently is needed. We can revisit the
> > ideas once some other real use-case manifests.
> 
> I have most of a real use case already.  I have a repository with
> submodules in one branch (master) and a subtree version in another
> (assembled) [4].  The *tree* is the same in each case, so I have to
> 'git rm -rf .'  to clear the submodules out of master before I can
> checkout assembled.
> 
>   $ git checkout assembled
>   error: The following untracked working tree files would be overwritten by checkout:
>           modular/README.md
>           modular/shell/README.md
>           …
>   $ git rm -rf .
>   $ git checkout assembled
> 
> That leaves some extra stuff removed:
> 
>   $ git status
>   On branch assembled
>   Changes to be committed:
>     (use "git reset HEAD <file>..." to unstage)
> 
>           deleted:    .gitignore
>           deleted:    .mailmap
>           deleted:    CONTRIBUTING.md
>           deleted:    LICENSE.md
>           deleted:    instructor.md
> 
> so I need to check that out by hand:
> 
>   $ git reset --hard HEAD
> 
> Now I can work in the assembled branch.  Going back to master is a bit
> less tedious:
> 
>   $ git checkout master
>   $ git submodule update --recursive
> 
> Luckily for me, I don't have a third superproject branch where the
> submodules are on a different, so the submodule's HEADs are preserved.
> As I understand it, the new recursive checkout functionality [5] would
> checkout my submodules with detached HEADs.  The fact that they are
> only accidentally preserved now is not comforting ;).

As it will be opt-in first (you will have to enable it with config
options) you can keep your current workflow. Once done with the initial
implementation we can discuss and iron out use-cases like yours.

> > Also we (Jens and I) would first like to proceed with the recursive
> > checkout / fetch (for which the plan is clear) as the next
> > complicated step.
> > 
> > Once that is done and people gain some experience with it we can
> > still extend further.
> 
> This is quite reasonable.  Given the need for backwards compatibility,
> I just wanted to make sure my ideal UI was clear before we went
> forward.  There's no need to break fingers twice ;), but if tight
> binding with localBranch is too big a chunk to bite off now, I'm happy
> to kick that can down the road.

Yes, that would be good to clearly understand and find out what we
actually want.

Cheers Heiko

> [1]: http://article.gmane.org/gmane.comp.version-control.git/239967
> [2]: http://article.gmane.org/gmane.comp.version-control.git/239973
> [3]: http://article.gmane.org/gmane.comp.version-control.git/240139
> [4]: (gitweb) http://git.tremily.us/?p=swc-boot-camp.git
> [5]: http://article.gmane.org/gmane.comp.version-control.git/239695

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: Re: [RFC v2] submodule: Respect requested branch on all clones
  2014-01-14 22:42                                                                   ` Heiko Voigt
@ 2014-01-15  0:02                                                                     ` Francesco Pretto
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
  1 sibling, 0 replies; 144+ messages in thread
From: Francesco Pretto @ 2014-01-15  0:02 UTC (permalink / raw)
  To: Heiko Voigt
  Cc: W. Trevor King, Jens Lehmann, Junio C Hamano, Git, Jonathan Nieder

2014/1/14 Heiko Voigt <hvoigt@hvoigt.net>:
> On Tue, Jan 14, 2014 at 02:22:31PM -0800, W. Trevor King wrote:
>> On Tue, Jan 14, 2014 at 10:46:08PM +0100, Heiko Voigt wrote:
>> > I would like to step back a bit and get back to the original problem
>> > at hand: Francescos original use case of an attached head for direct
>> > commits on a stable branch in a submodule. How about we finish
>> > discussing the exact solution of that first. AFAIK that is already
>> > solved with the following:
>> >
>> >  * Trevor's first patch[2] to create a branch on initial clone of a submodule
> [...]
>
>> > That should be all (and IIRC Francesco agreed) needed for that use-case.
>>
>> That was my understanding [3] ;).
>
>

I've been silent these days but yes: I confirm Trevor's second patch
iteration[1] gives, IMO, a better meaning of the
submodule.<name>.branch property and is perfectly fine for my use
case, to the point of stopping pursuing for my non behavior changing
patch[4] (I still think it deserved some more in depth reviews, though
;) ).

Cheers,
Francesco

[1]: http://article.gmane.org/gmane.comp.version-control.git/239967
[2]: http://article.gmane.org/gmane.comp.version-control.git/239973
[3]: http://article.gmane.org/gmane.comp.version-control.git/240139
[4]: http://article.gmane.org/gmane.comp.version-control.git/239956

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v3 3/4] submodule: Teach 'add' about a configurable local-branch
  2014-01-09  6:17                               ` [RFC v3 3/4] submodule: Teach 'add' about a configurable local-branch W. Trevor King
@ 2014-01-15  0:18                                 ` Francesco Pretto
  2014-01-15  1:02                                   ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-15  0:18 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Junio C Hamano, Heiko Voigt, Jens Lehmann, Jonathan Nieder

I've matured this opinion about "local-branch" some days ago, but I
couldn't join the discussion because I was extremely busy. Hope it's
is still current (and correct).

2014/1/9 W. Trevor King <wking@tremily.us>
>
> @@ -339,7 +339,19 @@ 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")
> +       superproject_branch=$(get_current_branch)
> +       default_local_branch=$(get_submodule_config "$sm_name" local-branch)
> +       (
> +               clear_local_git_env
> +               cd "$sm_path" &&
> +               GIT_WORK_TREE=. git config core.worktree "$rel/$b" &&
> +               local_branch=$(get_local_branch "${superproject_branch}" "${default_local_branch}") &&
> +               # ash fails to wordsplit ${branch:+-b "$branch"...}
> +               case "$branch" in
> +               '') git checkout -f -q -B "$local_branch" ;;
> +               ?*) git checkout -f -q -B "$local_branch" "origin/$branch" ;;
> +               esac
> +       ) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
>  }
>

also

2014/1/8 W. Trevor King <wking@tremily.us>:
>  To elaborate the idea I sketched out here [2], say
> you want:
>
>   Superproject branch  Submodule branch  Upstream branch
>   ===================  ================  ===============
>   master               master            master
>   super-feature        master            master
>   my-feature           my-feature        master
>   other-feature        other-feature     other-feature
>
> That's only going to work with per-superproject-branch configs for
> both the local and remote branches.  Using the same name for both
> local and remote branches does not work.
>
> Let me motivate each of the combinations in the above table:
>
> * master, master, master: The stable trunk.
> * super-feature, master, master: A superproject feature that works
>   with the stock submodule.
> * my-feature, my-feature, master: A superproject feature that needs an
>   improved submodule, but wants to integrate upstream master changes
>   during development.
> * other-feature, other-feature, other-feature: A superproject feature
>   that needs an improved submodule, and wants to integrate
>   other-feature changes that are also being developed upstream

The "local-branch" feature means to my brain the following: I,
maintainer, decide for you, developer, what name should be the branch
you are checking out. While, in general, it makes sense for a
developer to switch to a differently named "feature branch" that can
pull the original remote branch if he's actively developing (on any
repository, not only a submodule), this leads me to the following
questions: would it be good to introduce such enforcement? Do we allow
something similar on regular repositories? In short I believe this
workflow may reflect a personal attitude. In that case I'm unsure if
git should ease it so specifically.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [RFC v3 3/4] submodule: Teach 'add' about a configurable local-branch
  2014-01-15  0:18                                 ` Francesco Pretto
@ 2014-01-15  1:02                                   ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-15  1:02 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Git, Junio C Hamano, Heiko Voigt, Jens Lehmann, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 1499 bytes --]

On Wed, Jan 15, 2014 at 01:18:12AM +0100, Francesco Pretto wrote:
> I've matured this opinion about "local-branch" some days ago, but I
> couldn't join the discussion because I was extremely busy. Hope it's
> is still current (and correct).

I think the discussion is still open, but actions are postponed until
'checkout --recurse-submodules' lands [1].

> The "local-branch" feature means to my brain the following: I,
> maintainer, decide for you, developer, what name should be the
> branch you are checking out.

The goal is to have “I, your faithful Git command, check out for you,
oh wise developer, the superproject branch you requested, along with
the local submodule branch associated with that super project branch.”
;)  Maybe that would be more clear if the localBranch settings are
purely local (stored only in out-of-tree configs), and not contained
in the superproject's .gitmodules file?  As this series stands, that
would just drop step 3 from the lookup chain [2].  That step is below
all the local out-of-tree locations though, and I see no
non-psychological reason to keep folks from sharing reasonable default
names for local branches.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240420
[2]: http://article.gmane.org/gmane.comp.version-control.git/240251

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 0/6] submodule: Local branch creation in module_clone
  2014-01-14 22:42                                                                   ` Heiko Voigt
  2014-01-15  0:02                                                                     ` Francesco Pretto
@ 2014-01-16  4:09                                                                     ` W. Trevor King
  2014-01-16  4:10                                                                       ` [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit W. Trevor King
                                                                                         ` (5 more replies)
  1 sibling, 6 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16  4:09 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, W. Trevor King

Here is the next iteration of cloning-update local branch setup.  This
version is based on Francesco's fp/submodule-checkout-mode [1], and
moves back towards the weakly-bound v2 approach and away from the
tightly-bound v3 approach.

The first patch in this series extends that commit to consolidate ''
and 'checkout' update_module values.  I wouldn't mind if that gets
squashed into Francesco's patch.

The meat of the series is in the third patch, which changes the v2
implementation by triggering attached HEADs based on the update-mode
instead of on the existence of a non-empty submodule.<name>.branch
[2].  There has been pushback from both Heiko [3] and Jens [4] on my
mapping checkout updaters to “developers not interested in local
submodule development”, but I still think it's the right
interpretation.  I'm not clear on Heiko or Jens' current possitions,
maybe I've won them over ;).

The other patches in this series are all new in v4.

This still does a double checkout (once in module_clone to create a
local branch, and again in cmd_update to point that branch at the
correct commit), which Heiko was not excited about [5].

I'm also not sure if defaulting to $remote_name/$branch in cmd_update
is appropriate.  cmd_add defaults to using the remote's HEAD, and that
makes more sense to me than defaulting to the master branch.  However,
changing this logic is probably food for another series.

I still think that this series is only useful as a temporary stop-gap
[6] until we get something like my v3 [7], so the appropriate
submodule branch is automatically checked out when you change
superproject branches.

Cheers,
Trevor

[1]: http://article.gmane.org/gmane.comp.version-control.git/240036
[2]: http://article.gmane.org/gmane.comp.version-control.git/239973
[3]: http://article.gmane.org/gmane.comp.version-control.git/239978
[4]: http://article.gmane.org/gmane.comp.version-control.git/240368
[5]: http://article.gmane.org/gmane.comp.version-control.git/239968
[6]: http://article.gmane.org/gmane.comp.version-control.git/240232
[7]: http://article.gmane.org/gmane.comp.version-control.git/240248

W. Trevor King (6):
  submodule: Make 'checkout' update_module explicit
  submodule: Document module_clone arguments in comments
  submodule: Explicit local branch creation in module_clone
  t7406: Just-cloned checkouts update to the gitlinked hash with 'reset'
  t7406: Add explicit tests for head attachement after cloning updates
  Documentation: Describe 'submodule update' modes in detail

 Documentation/git-submodule.txt | 36 +++++++++++++-----
 Documentation/gitmodules.txt    |  4 ++
 git-submodule.sh                | 84 +++++++++++++++++++++++++----------------
 t/t7406-submodule-update.sh     | 39 ++++++++++++++++++-
 4 files changed, 121 insertions(+), 42 deletions(-)

-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
@ 2014-01-16  4:10                                                                       ` W. Trevor King
  2014-01-16 18:46                                                                         ` Junio C Hamano
  2014-01-16  4:10                                                                       ` [PATCH v4 2/6] submodule: Document module_clone arguments in comments W. Trevor King
                                                                                         ` (4 subsequent siblings)
  5 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-16  4:10 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, W. Trevor King

This avoids the current awkwardness of having either '' or 'checkout'
for checkout-mode updates, which makes testing for checkout-mode
updates (or non-checkout-mode updates) easier.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 git-submodule.sh | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 5247f78..5e8776c 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -803,17 +803,10 @@ cmd_update()
 			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")
@@ -882,11 +875,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=checkout ;;
 			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'")"
@@ -906,10 +904,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")
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 2/6] submodule: Document module_clone arguments in comments
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
  2014-01-16  4:10                                                                       ` [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit W. Trevor King
@ 2014-01-16  4:10                                                                       ` W. Trevor King
  2014-01-16  4:10                                                                       ` [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone W. Trevor King
                                                                                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16  4:10 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, W. Trevor King

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 git-submodule.sh | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/git-submodule.sh b/git-submodule.sh
index 5e8776c..68dcbe1 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -241,6 +241,12 @@ 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)
+#
 # 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,
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
  2014-01-16  4:10                                                                       ` [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit W. Trevor King
  2014-01-16  4:10                                                                       ` [PATCH v4 2/6] submodule: Document module_clone arguments in comments W. Trevor King
@ 2014-01-16  4:10                                                                       ` W. Trevor King
  2014-01-16 19:18                                                                         ` Junio C Hamano
  2014-01-16 19:43                                                                         ` Junio C Hamano
  2014-01-16  4:10                                                                       ` [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset' W. Trevor King
                                                                                         ` (2 subsequent siblings)
  5 siblings, 2 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16  4:10 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, W. Trevor King

The previous code only checked out branches in cmd_add.  This commit
moves the branch-checkout logic into module_clone, where it can be
shared by cmd_add and cmd_update.  I also update the initial checkout
command to use 'reset' to preserve branches setup during module_clone.

With this change, folks cloning submodules for the first time via:

  $ git submodule update ...

will get a local branch instead of a detached HEAD, unless they are
using the default checkout-mode updates.  This is a change from the
previous situation where cmd_update always used checkout-mode logic
(regardless of the requested update mode) for updates that triggered
an initial clone, which always resulted in a detached HEAD.

This commit does not change the logic for updates after the initial
clone, which will continue to create detached HEADs for checkout-mode
updates, and integrate remote work with the local HEAD (detached or
not) in other modes.

The motivation for the change is that developers doing local work
inside the submodule are likely to select a non-checkout-mode for
updates so their local work is integrated with upstream work.
Developers who are not doing local submodule work stick with
checkout-mode updates so any apparently local work is blown away
during updates.  For example, if upstream rolls back the remote branch
or gitlinked commit to an earlier version, the checkout-mode developer
wants their old submodule checkout to be rolled back as well, instead
of getting a no-op merge/rebase with the rolled-back reference.

By using the update mode to distinguish submodule developers from
black-box submodule consumers, we can setup local branches for the
developers who will want local branches, and stick with detached HEADs
for the developers that don't care.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 git-submodule.sh | 53 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 68dcbe1..4a09951 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -246,6 +246,9 @@ module_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.
@@ -259,6 +262,8 @@ module_clone()
 	url=$3
 	reference="$4"
 	depth="$5"
+	start_point="$6"
+	local_branch="$7"
 	quiet=
 	if test -n "$GIT_QUIET"
 	then
@@ -312,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()
@@ -475,16 +489,14 @@ 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=""
+		fi
+		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$start_point" "$local_branch" || exit
 	fi
 	git config submodule."$sm_name".url "$realrepo"
 
@@ -803,7 +815,9 @@ 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
@@ -817,11 +831,15 @@ cmd_update()
 
 		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=""
+			;;
+		esac
 
 		if test -z "$url"
 		then
@@ -835,7 +853,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
@@ -881,7 +900,7 @@ Maybe you want to use 'update --init'?")"
 			case ";$cloned_modules;" in
 			*";$name;"*)
 				# then there is no local change to integrate
-				update_module=checkout ;;
+				update_module='!git reset --hard -q'
 			esac
 
 			must_die_on_failure=
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset'
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
                                                                                         ` (2 preceding siblings ...)
  2014-01-16  4:10                                                                       ` [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone W. Trevor King
@ 2014-01-16  4:10                                                                       ` W. Trevor King
  2014-01-16 19:22                                                                         ` Junio C Hamano
  2014-01-16  4:10                                                                       ` [PATCH v4 5/6] t7406: Add explicit tests for head attachement after cloning updates W. Trevor King
  2014-01-16  4:10                                                                       ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail W. Trevor King
  5 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-16  4:10 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, W. Trevor King

To preserve the local branch, for situations where we're not on a
detached HEAD.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 t/t7406-submodule-update.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 0825a92..5aa9591 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -703,7 +703,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
 	 ) &&
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 5/6] t7406: Add explicit tests for head attachement after cloning updates
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
                                                                                         ` (3 preceding siblings ...)
  2014-01-16  4:10                                                                       ` [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset' W. Trevor King
@ 2014-01-16  4:10                                                                       ` W. Trevor King
  2014-01-16  4:10                                                                       ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail W. Trevor King
  5 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16  4:10 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, W. Trevor King

Test that cloning updates checkout the appropriate local branch for
their update-mode:

* Checkout-mode updates get detached HEADs
* Everyone else gets a local branch, matching the configured
  submodule.<name>.branch and defaulting to master.

The 'initial-setup' tag makes it easy to reset the superproject to a
known state, as several earlier tests commit to submodules and commit
the changed gitlinks to the superproject, but don't push the new
submodule commits to the upstream subprojects.  This makes it
impossible to checkout the current super master, because it references
submodule commits that don't exist in the upstream subprojects.  For a
specific example, see the tests that currently generate the
'two_new_submodule_commits' commits.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 t/t7406-submodule-update.sh | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 5aa9591..f056c01 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -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
 	)
 '
 
@@ -764,4 +767,38 @@ test_expect_success 'submodule update clone shallow submodule' '
 	 )
 	)
 '
+
+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
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
                                                                                         ` (4 preceding siblings ...)
  2014-01-16  4:10                                                                       ` [PATCH v4 5/6] t7406: Add explicit tests for head attachement after cloning updates W. Trevor King
@ 2014-01-16  4:10                                                                       ` W. Trevor King
  2014-01-16 20:21                                                                         ` Junio C Hamano
  5 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-16  4:10 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, W. Trevor King

The old documentation did not distinguish between cloning and
non-cloning updates and lacked clarity on which operations would lead
to detached HEADs, and which would not.  The new documentation
addresses these issues while updating the docs to reflect the changes
introduced by this branch's explicit local branch creation in
module_clone.

I also add '--checkout' to the usage summary and group the update-mode
options into a single set.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 Documentation/git-submodule.txt | 36 +++++++++++++++++++++++++++---------
 Documentation/gitmodules.txt    |  4 ++++
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index bfef8a0..02500b4 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -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 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
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index f7be93f..36e5447 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -53,6 +53,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
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit
  2014-01-16  4:10                                                                       ` [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit W. Trevor King
@ 2014-01-16 18:46                                                                         ` Junio C Hamano
  2014-01-16 19:22                                                                           ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-16 18:46 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

"W. Trevor King" <wking@tremily.us> writes:

> This avoids the current awkwardness of having either '' or 'checkout'
> for checkout-mode updates, which makes testing for checkout-mode
> updates (or non-checkout-mode updates) easier.
>
> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---
>  git-submodule.sh | 27 +++++++++++----------------
>  1 file changed, 11 insertions(+), 16 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 5247f78..5e8776c 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -803,17 +803,10 @@ cmd_update()
>  			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

Is this a good change?

It removes the code to prevent a broken configuration value from
slipping through.  The code used to stop early to give the user a
chance to fix it before actually letting "submodule update" to go
into the time consuming part, e.g. a call to module_clone, but that
code is now lost.

>  		displaypath=$(relative_path "$prefix$sm_path")
> @@ -882,11 +875,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=checkout ;;
>  			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'")"
> +				;;
>  ...
>  			*)
> -				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

These two hunks make sense.  It is clear in the updated code that
"checkout" is what is implemented with that "git checkout $subforce
-q", and not any other random update mode.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone
  2014-01-16  4:10                                                                       ` [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone W. Trevor King
@ 2014-01-16 19:18                                                                         ` Junio C Hamano
  2014-01-16 19:29                                                                           ` W. Trevor King
  2014-01-16 19:43                                                                         ` Junio C Hamano
  1 sibling, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-16 19:18 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

"W. Trevor King" <wking@tremily.us> writes:

> The previous code only checked out branches in cmd_add.  This commit
> moves the branch-checkout logic into module_clone, where it can be
> shared by cmd_add and cmd_update.  I also update the initial checkout
> command to use 'reset' to preserve branches setup during module_clone.
>
> With this change, folks cloning submodules for the first time via:
>
>   $ git submodule update ...
>
> will get a local branch instead of a detached HEAD, unless they are
> using the default checkout-mode updates.  This is a change from the
> previous situation where cmd_update always used checkout-mode logic
> (regardless of the requested update mode) for updates that triggered
> an initial clone, which always resulted in a detached HEAD.
>
> This commit does not change the logic for updates after the initial
> clone, which will continue to create detached HEADs for checkout-mode
> updates, and integrate remote work with the local HEAD (detached or
> not) in other modes.
>
> The motivation for the change is that developers doing local work
> inside the submodule are likely to select a non-checkout-mode for
> updates so their local work is integrated with upstream work.
> Developers who are not doing local submodule work stick with
> checkout-mode updates so any apparently local work is blown away
> during updates.  For example, if upstream rolls back the remote branch
> or gitlinked commit to an earlier version, the checkout-mode developer
> wants their old submodule checkout to be rolled back as well, instead
> of getting a no-op merge/rebase with the rolled-back reference.
>
> By using the update mode to distinguish submodule developers from
> black-box submodule consumers, we can setup local branches for the
> developers who will want local branches, and stick with detached HEADs
> for the developers that don't care.
>
> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---
>  git-submodule.sh | 53 ++++++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 36 insertions(+), 17 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 68dcbe1..4a09951 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -246,6 +246,9 @@ module_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.
> @@ -259,6 +262,8 @@ module_clone()
>  	url=$3
>  	reference="$4"
>  	depth="$5"
> +	start_point="$6"
> +	local_branch="$7"
>  	quiet=
>  	if test -n "$GIT_QUIET"
>  	then
> @@ -312,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"...}

Interesting...

> +		case "$local_branch" in
> +		'') git checkout -f -q ${start_point:+"$start_point"} ;;
> +		?*) git checkout -f -q -B "$local_branch" ${start_point:+"$start_point"} ;;
> +		esac

I am wondering if it makes more sense if you did this instead:

	git checkout -f -q ${start_point:+"$start_point"} &&
	if test -n "$local_branch"
        then
        	git checkout -B "$local_branch" HEAD
	fi

The optional "re-attaching to the local_branch" done with the second
"checkout" would be a non-destructive no-op to the working tree and
to the index, but it does distinguish between creating the branch
anew and resetting the existing branch in its output (note that
there is no "-q" to squelch it).  By doing it this way, when we
later teach "git branch -f" and "git checkout -B" to report more
about what commits have been lost by such a resetting, you will get
the safety for free if you made the switching with "-B" run without
"-q" here.

> +	) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
>  }
>  
>  isnumber()
> @@ -475,16 +489,14 @@ 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=""
> +		fi

I'd feel safer if the "else" clause explicitly cleared $local_branch
by assigning an empty string to it; it would make it a lot clearer
that "when $branch is an empty string here, we do not want to
trigger the new codepath to run checkout with "-B $local_branch" in
module_clone" is what you mean.

> +		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$start_point" "$local_branch" || exit

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset'
  2014-01-16  4:10                                                                       ` [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset' W. Trevor King
@ 2014-01-16 19:22                                                                         ` Junio C Hamano
  2014-01-16 19:32                                                                           ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-16 19:22 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

"W. Trevor King" <wking@tremily.us> writes:

> To preserve the local branch, for situations where we're not on a
> detached HEAD.
>
> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---

This should be a part of some other change that actually changes how
this "git submodule update" checks out the submodule, no?

>  t/t7406-submodule-update.sh | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
> index 0825a92..5aa9591 100755
> --- a/t/t7406-submodule-update.sh
> +++ b/t/t7406-submodule-update.sh
> @@ -703,7 +703,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
>  	 ) &&

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit
  2014-01-16 18:46                                                                         ` Junio C Hamano
@ 2014-01-16 19:22                                                                           ` W. Trevor King
  2014-01-16 20:07                                                                             ` Francesco Pretto
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 19:22 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 1577 bytes --]

On Thu, Jan 16, 2014 at 10:46:36AM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> > @@ -803,17 +803,10 @@ cmd_update()
> >  			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
> 
> Is this a good change?
> 
> It removes the code to prevent a broken configuration value from
> slipping through.  The code used to stop early to give the user a
> chance to fix it before actually letting "submodule update" to go
> into the time consuming part, e.g. a call to module_clone, but that
> code is now lost.

Avoiding useless clones is probably more important than avoiding
duplicate "Invalid update mode" messages.  I'll reinstate the case
statement in v5, but I think it should live outside of the “load from
config” block, in case someone adds the ability to set arbitrary
update modes from the command line (`--update merge`, `--update
'!command'`, etc.).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone
  2014-01-16 19:18                                                                         ` Junio C Hamano
@ 2014-01-16 19:29                                                                           ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 19:29 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 3077 bytes --]

On Thu, Jan 16, 2014 at 11:18:00AM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> > @@ -312,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"...}
> 
> Interesting...

That's copied out of the old cmd_add code ;).  I don't have ash
intalled to actually confirm the comment.

> > +		case "$local_branch" in
> > +		'') git checkout -f -q ${start_point:+"$start_point"} ;;
> > +		?*) git checkout -f -q -B "$local_branch" ${start_point:+"$start_point"} ;;
> > +		esac
> 
> I am wondering if it makes more sense if you did this instead:
> 
> 	git checkout -f -q ${start_point:+"$start_point"} &&
> 	if test -n "$local_branch"
>         then
>         	git checkout -B "$local_branch" HEAD
> 	fi
> 
> The optional "re-attaching to the local_branch" done with the second
> "checkout" would be a non-destructive no-op to the working tree and
> to the index, but it does distinguish between creating the branch
> anew and resetting the existing branch in its output (note that
> there is no "-q" to squelch it).  By doing it this way, when we
> later teach "git branch -f" and "git checkout -B" to report more
> about what commits have been lost by such a resetting, you will get
> the safety for free if you made the switching with "-B" run without
> "-q" here.

This is immediately post-non-checkout-clone.  There are no local
branches to clobber yet.

> > @@ -475,16 +489,14 @@ 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=""
> > +		fi
> 
> I'd feel safer if the "else" clause explicitly cleared $local_branch
> by assigning an empty string to it; it would make it a lot clearer
> that "when $branch is an empty string here, we do not want to
> trigger the new codepath to run checkout with "-B $local_branch" in
> module_clone" is what you mean.

Ok.  Will add in v5.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset'
  2014-01-16 19:22                                                                         ` Junio C Hamano
@ 2014-01-16 19:32                                                                           ` W. Trevor King
  2014-01-16 20:24                                                                             ` Junio C Hamano
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 19:32 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 908 bytes --]

On Thu, Jan 16, 2014 at 11:22:52AM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> 
> > To preserve the local branch, for situations where we're not on a
> > detached HEAD.
> >
> > Signed-off-by: W. Trevor King <wking@tremily.us>
> > ---
> 
> This should be a part of some other change that actually changes how
> this "git submodule update" checks out the submodule, no?

Sure, we can squash both this test fix and the subsequent new test
patch into patch #3 in v5.  I was just splitting them out because
backwards compatibility was a concern, and separate patches makes it
easy for me to explain why the results changed here without getting
lost in patch #3's implementation details.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone
  2014-01-16  4:10                                                                       ` [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone W. Trevor King
  2014-01-16 19:18                                                                         ` Junio C Hamano
@ 2014-01-16 19:43                                                                         ` Junio C Hamano
  2014-01-16 21:12                                                                           ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-16 19:43 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

"W. Trevor King" <wking@tremily.us> writes:

> @@ -817,11 +831,15 @@ cmd_update()
>  
>  		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=""
> +			;;
> +		esac

I wonder if there is a way to avoid detaching (and you may need to
update the coddpath that resets the submodule to the commit
specified by the superproject tree) when it is safe to do so.

For an end user, running "submodule update" is similar to running
"git pull" in a project that does not use submodules, expressing "I
want to catch up with the work done by others".  In a working tree
with local changes, we do allow you to run "git pull" as long as
your local changes do not overlap with the work done by others, and
the result of the pull would look as if you did not have any of the
local changes when you ran "git pull" and then you did the local
changes on top of the state that is up-to-date with their work.

Can't we design "submodule update --checkout" to work in a similar
fashion?  The updated superproject may say it wants $oSHA-1 at a
submodule path P, and also its .gitmodules may say that commit is
supposed to be at the tip of branch B=submodule.P.branch in the
submodule repository.  You may locally have advanced that branch in
your submodule repository in the meantime to point at $ySHA-1 while
others worked in the superproject and the submodule, and the
difference $oSHA-1...$ySHA-1 can be considered as the local change
made by you from the perspective of the superproject.

Without thinking things through, if $ySHA-1 matches or is a
descendant of $oSHA-1 (assuming that remote-tracking branch
origin/$B in the submodule does point at $oSHA-1 in either case), it
should be safe to do this update.

And in a situation where you cannot do the checkout safely, it is
perfectly fine to say "the submodules X and Y have local changes;
you cannot do 'submodule update' until you upstream them" and fail
the update, just like we fail a 'git pull' saying "you cannot do
pull until you commit them", no?

Perhaps that kind of "'git submodule update' is parallel to 'git
pull' in the project without submodules" is better done with other
update modes like --rebase or --merge.  If so, how should we explain
what 'submodule update --checkout' is to the end users?  Is it
supposed to be like "git fetch && git checkout origin/master"?

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit
  2014-01-16 19:22                                                                           ` W. Trevor King
@ 2014-01-16 20:07                                                                             ` Francesco Pretto
  2014-01-16 20:19                                                                               ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Francesco Pretto @ 2014-01-16 20:07 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Junio C Hamano, Git, Jens Lehmann, Heiko Voigt, Jonathan Nieder

2014/1/16 W. Trevor King <wking@tremily.us>:
> Avoiding useless clones is probably more important than avoiding
> duplicate "Invalid update mode" messages.

No, it's not duplicate code. I'll explain, please follow me:

> @@ -803,17 +803,10 @@ cmd_update()
>                         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

This is a *validation*. It's done before going more through the code
and die early.

>                       *)
> +                             die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
>

This should be an *assert* -> it means if you reach this case
statement you (programmer) have messed the code something in the code
before. In fact in my original patch I wrote something like "invalid
update_module at this flow".

Please keep both as Junio said.

Thanks,
Francesco

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit
  2014-01-16 20:07                                                                             ` Francesco Pretto
@ 2014-01-16 20:19                                                                               ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 20:19 UTC (permalink / raw)
  To: Francesco Pretto
  Cc: Junio C Hamano, Git, Jens Lehmann, Heiko Voigt, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 1009 bytes --]

On Thu, Jan 16, 2014 at 09:07:22PM +0100, Francesco Pretto wrote:
> 2014/1/16 W. Trevor King <wking@tremily.us>:
> > Avoiding useless clones is probably more important than avoiding
> > duplicate "Invalid update mode" messages.
> 
> No, it's not duplicate code.

I meant “duplicating the "Invalid update mode" error message”.  I
missed the die-early distinction, but I understand now.  I think its
non-DRY to have an early case statement to validate the update_module,
and a later case statement to use it.  Still, keeping those separate
statements in sync shouldn't be too hard ;).

> Please keep both as Junio said.

That's what I said I'd do in the email you're quoting ;).  Are you ok
with the die-early validation checking all update_module settings
instead of just checking the loaded-from config branch?

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16  4:10                                                                       ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail W. Trevor King
@ 2014-01-16 20:21                                                                         ` Junio C Hamano
  2014-01-16 20:55                                                                           ` W. Trevor King
  2014-01-16 22:18                                                                           ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail Philip Oakley
  0 siblings, 2 replies; 144+ messages in thread
From: Junio C Hamano @ 2014-01-16 20:21 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

"W. Trevor King" <wking@tremily.us> writes:

> The old documentation did not distinguish between cloning and
> non-cloning updates and lacked clarity on which operations would lead
> to detached HEADs, and which would not.  The new documentation
> addresses these issues while updating the docs to reflect the changes
> introduced by this branch's explicit local branch creation in
> module_clone.
>
> I also add '--checkout' to the usage summary and group the update-mode
> options into a single set.
>
> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---
>  Documentation/git-submodule.txt | 36 +++++++++++++++++++++++++++---------
>  Documentation/gitmodules.txt    |  4 ++++
>  2 files changed, 31 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
> index bfef8a0..02500b4 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -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 be
> +	configured with the 'submodule.<name>.update' setting or the
> +	'--rebase', '--merge', or 'checkout' options.

Not '--checkout'?

Other than that, the updated text above is far easier to
understand.  Good job.

> ++
> +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

That is, updates that update submodules that are already checked out?

> +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.

I think copying some motivation from the log message of 06b1abb5
(submodule update: add --remote for submodule's upstream changes,
2012-12-19) would help the readers here.  A naïve expectation from a
casual reader of the above would be "The superproject's tree ought
to point at the same commit as the tip of the branch used in the
submodule (modulo mirroring delays and somesuch), if the repository
of the superproject and submodules are maintained properly", which
would lead to "when would any sane person need to use --remote in
the first place???".

If I am reading 06b1abb5 correctly, the primary motivation behind
"--remote" seems to be that it is exactly to help the person who
wants to update superproject to satisify the "... are maintained
properly" part by fetching the latest in each of the submodules in
his superproject in preparation to 'git add .' them.  I still do not
think "--remote" was a better way than the "foreach", but that is a
separate topic.

If the person who works in the superproject does not control the
progress of, and/or does not care what development is happening in,
the submodules, he can push the superproject tree out without even
bothering to update the commits in the submodules bound to his
superproject tree, and the consumers of such a superproject could
catch up with the advancement of submodule by using --remote
individually to bring themselves up to date.  But I do not think
that is what you envisioned as the best recommended practice when
you wrote 06b1abb5.

> +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
> diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
> index f7be93f..36e5447 100644
> --- a/Documentation/gitmodules.txt
> +++ b/Documentation/gitmodules.txt
> @@ -53,6 +53,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

Other than the above minor nits, the updated text was very
readable.  Thanks.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset'
  2014-01-16 19:32                                                                           ` W. Trevor King
@ 2014-01-16 20:24                                                                             ` Junio C Hamano
  0 siblings, 0 replies; 144+ messages in thread
From: Junio C Hamano @ 2014-01-16 20:24 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

"W. Trevor King" <wking@tremily.us> writes:

> On Thu, Jan 16, 2014 at 11:22:52AM -0800, Junio C Hamano wrote:
>> "W. Trevor King" <wking@tremily.us> writes:
>> 
>> > To preserve the local branch, for situations where we're not on a
>> > detached HEAD.
>> >
>> > Signed-off-by: W. Trevor King <wking@tremily.us>
>> > ---
>> 
>> This should be a part of some other change that actually changes how
>> this "git submodule update" checks out the submodule, no?
>
> Sure, we can squash both this test fix and the subsequent new test
> patch into patch #3 in v5.  I was just splitting them out because
> backwards compatibility was a concern, and separate patches makes it
> easy for me to explain why the results changed here without getting
> lost in patch #3's implementation details.

On the contrary, if we had this as part of patch #3, it would have
helped reviewing the patch itself, as that would have served as one
more clue to illustrate the effect that is externally visible to end
users.

Besides, having them separate will break bisection.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16 20:21                                                                         ` Junio C Hamano
@ 2014-01-16 20:55                                                                           ` W. Trevor King
  2014-01-16 21:02                                                                             ` John Keeping
  2014-01-16 21:55                                                                             ` Junio C Hamano
  2014-01-16 22:18                                                                           ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail Philip Oakley
  1 sibling, 2 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 20:55 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 5175 bytes --]

On Thu, Jan 16, 2014 at 12:21:04PM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> > @@ -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 be
> > +	configured with the 'submodule.<name>.update' setting or the
> > +	'--rebase', '--merge', or 'checkout' options.
> 
> Not '--checkout'?

Oops, will fix in v5.

> > ++
> > +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
> 
> That is, updates that update submodules that are already checked out?

It's submodules for which $sm_path/.git does not exist.

> > +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.
> 
> I think copying some motivation from the log message of 06b1abb5
> (submodule update: add --remote for submodule's upstream changes,
> 2012-12-19) would help the readers here.

I think a brief reference to --remote is best here, mentioning that it
has something to do with the upstream subproject.  More detail on when
you should use --remote should probably go under the docs for --remote
;).

> A naïve expectation from a casual reader of the above would be "The
> superproject's tree ought to point at the same commit as the tip of
> the branch used in the submodule (modulo mirroring delays and
> somesuch),

What is the branch used in the submodule?  The remote subproject's
current submodule.<name>.branch?  The local submodule's
submodule.<name>.branch (or localBranch) branch?  The submodule's
current HEAD?

> if the repository of the superproject and submodules are maintained
> properly", which would lead to "when would any sane person need to
> use --remote in the first place???".

--remote is not for sane people (who will probably be pulling from
withing the submodule itself).  --remote is for folks who track too
many submodules to care about them as individuals, who just want to
blindly update to whatever the upstream subproject maintainer has in
submodule.<name>.branch.  For example, if you are a distribution with
a hundred submodules tracking all the projects you package, and want
to bump them all to a their current trunk tip in one fell swoop.

> If I am reading 06b1abb5 correctly, the primary motivation behind
> "--remote" seems to be that it is exactly to help the person who
> wants to update superproject to satisify the "... are maintained
> properly" part by fetching the latest in each of the submodules in
> his superproject in preparation to 'git add .' them.  I still do not
> think "--remote" was a better way than the "foreach", but that is a
> separate topic.

I agree now ;), the problems with:

  $ git submodule foreach 'git pull'

are:

1. You may not be on the “right” local branch to begin with, and
2. You may not have out-of-tree submodule configs setting up the
   “right” upstream for that branch.

06b1abb did not address the former, and added a new .gitmodules-level
submodule.<name>.branch to help with the latter.  I now think all of
this would be easier if we had automatic submodule local-branch
checkouts (fixing problem 1) and synchronized out-of-tree submodule
configs (fixing problem 2).  Fixing problem 1 is all you need if you
aren't interested in sharing your out-of-tree configs.

I think 06b1abb was inspired by “we already have a way to integrate
changes in the gitlinked commit, we should reuse those to integrate
other changes”.  In hindsight, changes in the gitlinked commit are
really a checkout-time issue, while changes in other places (like the
remote subproject) are pull-time issues.  Mixing them together was
more confusing than it was worth.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16 20:55                                                                           ` W. Trevor King
@ 2014-01-16 21:02                                                                             ` John Keeping
  2014-01-16 21:16                                                                               ` W. Trevor King
  2014-01-16 21:55                                                                             ` Junio C Hamano
  1 sibling, 1 reply; 144+ messages in thread
From: John Keeping @ 2014-01-16 21:02 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Junio C Hamano, Git, Jens Lehmann, Francesco Pretto, Heiko Voigt,
	Jonathan Nieder

On Thu, Jan 16, 2014 at 12:55:21PM -0800, W. Trevor King wrote:
> On Thu, Jan 16, 2014 at 12:21:04PM -0800, Junio C Hamano wrote:
> > "W. Trevor King" <wking@tremily.us> writes:
> > > @@ -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 be
> > > +	configured with the 'submodule.<name>.update' setting or the
> > > +	'--rebase', '--merge', or 'checkout' options.
> > 
> > Not '--checkout'?
> 
> Oops, will fix in v5.

Shouldn't this also be `--checkout` (backticks), according to
CodingGuidelines.  This applies to all this options in this patch I
think.

> > > ++
> > > +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
> > 
> > That is, updates that update submodules that are already checked out?
> 
> It's submodules for which $sm_path/.git does not exist.
> 
> > > +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.
> > 
> > I think copying some motivation from the log message of 06b1abb5
> > (submodule update: add --remote for submodule's upstream changes,
> > 2012-12-19) would help the readers here.
> 
> I think a brief reference to --remote is best here, mentioning that it
> has something to do with the upstream subproject.  More detail on when
> you should use --remote should probably go under the docs for --remote
> ;).
> 
> > A naïve expectation from a casual reader of the above would be "The
> > superproject's tree ought to point at the same commit as the tip of
> > the branch used in the submodule (modulo mirroring delays and
> > somesuch),
> 
> What is the branch used in the submodule?  The remote subproject's
> current submodule.<name>.branch?  The local submodule's
> submodule.<name>.branch (or localBranch) branch?  The submodule's
> current HEAD?
> 
> > if the repository of the superproject and submodules are maintained
> > properly", which would lead to "when would any sane person need to
> > use --remote in the first place???".
> 
> --remote is not for sane people (who will probably be pulling from
> withing the submodule itself).  --remote is for folks who track too
> many submodules to care about them as individuals, who just want to
> blindly update to whatever the upstream subproject maintainer has in
> submodule.<name>.branch.  For example, if you are a distribution with
> a hundred submodules tracking all the projects you package, and want
> to bump them all to a their current trunk tip in one fell swoop.
> 
> > If I am reading 06b1abb5 correctly, the primary motivation behind
> > "--remote" seems to be that it is exactly to help the person who
> > wants to update superproject to satisify the "... are maintained
> > properly" part by fetching the latest in each of the submodules in
> > his superproject in preparation to 'git add .' them.  I still do not
> > think "--remote" was a better way than the "foreach", but that is a
> > separate topic.
> 
> I agree now ;), the problems with:
> 
>   $ git submodule foreach 'git pull'
> 
> are:
> 
> 1. You may not be on the “right” local branch to begin with, and
> 2. You may not have out-of-tree submodule configs setting up the
>    “right” upstream for that branch.
> 
> 06b1abb did not address the former, and added a new .gitmodules-level
> submodule.<name>.branch to help with the latter.  I now think all of
> this would be easier if we had automatic submodule local-branch
> checkouts (fixing problem 1) and synchronized out-of-tree submodule
> configs (fixing problem 2).  Fixing problem 1 is all you need if you
> aren't interested in sharing your out-of-tree configs.
> 
> I think 06b1abb was inspired by “we already have a way to integrate
> changes in the gitlinked commit, we should reuse those to integrate
> other changes”.  In hindsight, changes in the gitlinked commit are
> really a checkout-time issue, while changes in other places (like the
> remote subproject) are pull-time issues.  Mixing them together was
> more confusing than it was worth.
> 
> Cheers,
> Trevor
> 
> -- 
> This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
> For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone
  2014-01-16 19:43                                                                         ` Junio C Hamano
@ 2014-01-16 21:12                                                                           ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 21:12 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 3261 bytes --]

On Thu, Jan 16, 2014 at 11:43:44AM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> 
> > @@ -817,11 +831,15 @@ cmd_update()
> >  
> >  		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=""
> > +			;;
> > +		esac
> 
> I wonder if there is a way to avoid detaching (and you may need to
> update the coddpath that resets the submodule to the commit
> specified by the superproject tree) when it is safe to do so.
>
> …
> 
> Perhaps that kind of "'git submodule update' is parallel to 'git
> pull' in the project without submodules" is better done with other
> update modes like --rebase or --merge.  If so, how should we explain
> what 'submodule update --checkout' is to the end users?  Is it
> supposed to be like "git fetch && git checkout origin/master"?

It sounds like you're looking for:

  submodule.<name>.update = !git merge --ff-only

That's fine for folks who want that sort of advancement, but I think
there will also be blind updaters who just want the gitlinked commit,
and don't care if that blows away local work, because they never work
locally in the submodule.  They'll still prefer the current
checkout-mode with it's clobbering.

I think the best way to explain this to users is to have 'git
checkout' (with an optional '--recurse-submdules' trial period)
checkout the gitlinked commit automatically.  Then there is never
local submodule work that is not committed or stashed in the
superproject (or stashed on some out-of-the-way branch in the
submodule).  Currently we have:

  1. Checkout a superproject branch and currently gitlinked submodule.
  2. Do local work on the submodule.
  3. Alter the superproject and its gitlinks.
  4. 'git submodule update' to integrate your work from 2 with the
     changes from 3 and checkout the appropriate submodule commit.

I think it would make more sense to:

  1. Checkout a superproject branch and currently gitlinked submodule.
  2. Do local work on the submodule.
  3. Commit your new gitlink to the superproject (or stash it, or put
     it on a temporary submodule branch and reset the submodule HEAD
     to the old value).
  4. Alter the superproject and its gitlinks, using the existing logic
     to integrate conflicts.  Automatically checkout the appropriate
     submodule commit (as the appropriate submodule branch).

That shifts “dealing with local submodule changes” from an
integration-time issue (I just called submodule update, what changes
are local?) to a pre-checkout-time issue (I've got a dirty submodule
(it's HEAD is not the gitlinked commit, all of these changes are
local).  I think that's a lot easier to wrap your head around.

This series is a stop-gap to avoid detached HEADs after cloning,
non-checkout updates, while we hash out the real solution ;).

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16 21:02                                                                             ` John Keeping
@ 2014-01-16 21:16                                                                               ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 21:16 UTC (permalink / raw)
  To: John Keeping
  Cc: Junio C Hamano, Git, Jens Lehmann, Francesco Pretto, Heiko Voigt,
	Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 772 bytes --]

On Thu, Jan 16, 2014 at 09:02:22PM +0000, John Keeping wrote:
> On Thu, Jan 16, 2014 at 12:55:21PM -0800, W. Trevor King wrote:
> > On Thu, Jan 16, 2014 at 12:21:04PM -0800, Junio C Hamano wrote:
> > > Not '--checkout'?
> > 
> > Oops, will fix in v5.
> 
> Shouldn't this also be `--checkout` (backticks), according to
> CodingGuidelines.  This applies to all this options in this patch I
> think.

I can change that too.  The existing content is inconsistent between
backticks and single quotes, but I see no mention of single quotes in
CodingGuidelines.  Thanks for the reference.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16 20:55                                                                           ` W. Trevor King
  2014-01-16 21:02                                                                             ` John Keeping
@ 2014-01-16 21:55                                                                             ` Junio C Hamano
  2014-01-17  2:37                                                                               ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Junio C Hamano @ 2014-01-16 21:55 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

"W. Trevor King" <wking@tremily.us> writes:

>> A naïve expectation from a casual reader of the above would be "The
>> superproject's tree ought to point at the same commit as the tip of
>> the branch used in the submodule (modulo mirroring delays and
>> somesuch),
>
> What is the branch used in the submodule?  The remote subproject's
> current submodule.<name>.branch?  The local submodule's
> submodule.<name>.branch (or localBranch) branch?  The submodule's
> current HEAD?

They are good questions that such casual readers would have, and
giving answers to them in this part of the documentation would be a
good way to give them a clear picture of how the command is designed
to be used.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16 20:21                                                                         ` Junio C Hamano
  2014-01-16 20:55                                                                           ` W. Trevor King
@ 2014-01-16 22:18                                                                           ` Philip Oakley
  2014-01-16 22:35                                                                             ` W. Trevor King
  1 sibling, 1 reply; 144+ messages in thread
From: Philip Oakley @ 2014-01-16 22:18 UTC (permalink / raw)
  To: Junio C Hamano, W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

From: "Junio C Hamano" <gitster@pobox.com>
> "W. Trevor King" <wking@tremily.us> writes:
>
[...]
>> @@ -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 be

nit:   s/but be/but can be/  ?

>> + configured with the 'submodule.<name>.update' setting or the
>> + '--rebase', '--merge', or 'checkout' options.
>
[...] 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16 22:18                                                                           ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail Philip Oakley
@ 2014-01-16 22:35                                                                             ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-16 22:35 UTC (permalink / raw)
  To: Philip Oakley
  Cc: Junio C Hamano, Git, Jens Lehmann, Francesco Pretto, Heiko Voigt,
	Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 469 bytes --]

On Thu, Jan 16, 2014 at 10:18:06PM -0000, Philip Oakley wrote:
> From: "Junio C Hamano" <gitster@pobox.com>
> > "W. Trevor King" <wking@tremily.us> writes:
> >> + repository.  The update mode defaults to 'checkout', but be
> 
> nit:   s/but be/but can be/  ?

Thanks.  Queuing for v5.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail
  2014-01-16 21:55                                                                             ` Junio C Hamano
@ 2014-01-17  2:37                                                                               ` W. Trevor King
  2014-01-26 20:45                                                                                 ` [PATCH v5 0/4] submodule: Local branch creation in module_clone W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-17  2:37 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git, Jens Lehmann, Francesco Pretto, Heiko Voigt, Jonathan Nieder

[-- Attachment #1: Type: text/plain, Size: 2321 bytes --]

On Thu, Jan 16, 2014 at 01:55:37PM -0800, Junio C Hamano wrote:
> "W. Trevor King" <wking@tremily.us> writes:
> > On Thu, Jan 16, 2014 at 12:21:04PM -0800, Junio C Hamano wrote:
> >> "W. Trevor King" <wking@tremily.us> writes:
> >>> +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.
> >> …
> >> A naïve expectation from a casual reader of the above would be
> >> "The superproject's tree ought to point at the same commit as the
> >> tip of the branch used in the submodule (modulo mirroring delays
> >> and somesuch),
> >
> > What is the branch used in the submodule?  The remote subproject's
> > current submodule.<name>.branch?  The local submodule's
> > submodule.<name>.branch (or localBranch) branch?  The submodule's
> > current HEAD?
>
> They are good questions that such casual readers would have, and
> giving answers to them in this part of the documentation would be a
> good way to give them a clear picture of how the command is designed
> to be used.

How about:

  Note that the update command only interacts with the submodule's
  HEAD.  It doesn't care what this head points to.  If the submodule
  has a branch checked out, HEAD will reference that branch.  If the
  submodule's HEAD is detached, it will reference a commit.  After
  following any references, the commit referenced by the submodule's
  HEAD may resolve to the commit gitlinked by the superproject, or it
  may not (if you have made local submodule changes, or checked out a
  different superproject branch).  The update command does not adjust
  your submodule's HEAD to point at the gitlinked commit before
  performing any integration.  It just takes your submodle's HEAD,
  whatever it points to, and integrates the remote reference.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v5 0/4] submodule: Local branch creation in module_clone
  2014-01-17  2:37                                                                               ` W. Trevor King
@ 2014-01-26 20:45                                                                                 ` W. Trevor King
  2014-01-26 20:45                                                                                   ` [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit W. Trevor King
                                                                                                     ` (3 more replies)
  0 siblings, 4 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-26 20:45 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, Philip Oakley, John Keeping, W. Trevor King

Changes since v4:

In git-submodule.sh:

* Explicitly set an empty $local_branch in cmd_add if $branch is empty
  [1].
* Restore die-early checking for invalid $update_module [2].  This
  check is now outside the load-from-config branch, ensuring we have a
  valid update_module, regardless of how it was set.

In Documentation/git-submodule.txt:

* Fix “but be” → “but can be” [3].
* Fix “checkout” → “--checkout” [4].
* New text on why you'd use --remote [5] (new commit #4).

In Documentation/git-submodule.txt and Documentation/gitmodules.txt:

* Use backticks (instead of single quotes) for command line options
  [6].

I also squashed the implementation, testing fixes, new tests, and
documentation for the new local_branch stuff (v4's #3, #4, #5, and #6)
into a single commit (v5's #3) [7].

[1]: http://article.gmane.org/gmane.comp.version-control.git/240524
[2]: http://article.gmane.org/gmane.comp.version-control.git/240522
[3]: http://article.gmane.org/gmane.comp.version-control.git/240543
[4]: http://article.gmane.org/gmane.comp.version-control.git/240531
[5]: http://article.gmane.org/gmane.comp.version-control.git/240529
[6]: http://article.gmane.org/gmane.comp.version-control.git/240536
[7]: http://article.gmane.org/gmane.comp.version-control.git/240530

W. Trevor King (4):
  submodule: Make 'checkout' update_module explicit
  submodule: Document module_clone arguments in comments
  submodule: Explicit local branch creation in module_clone
  Documentation: Describe 'submodule update --remote' use case

 Documentation/git-submodule.txt | 46 ++++++++++++++++-----
 Documentation/gitmodules.txt    |  4 ++
 git-submodule.sh                | 89 ++++++++++++++++++++++++++---------------
 t/t7406-submodule-update.sh     | 39 +++++++++++++++++-
 4 files changed, 136 insertions(+), 42 deletions(-)

-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit
  2014-01-26 20:45                                                                                 ` [PATCH v5 0/4] submodule: Local branch creation in module_clone W. Trevor King
@ 2014-01-26 20:45                                                                                   ` W. Trevor King
  2014-01-27  1:32                                                                                     ` Eric Sunshine
  2014-01-26 20:45                                                                                   ` [PATCH v5 2/4] submodule: Document module_clone arguments in comments W. Trevor King
                                                                                                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 144+ messages in thread
From: W. Trevor King @ 2014-01-26 20:45 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, Philip Oakley, John Keeping, W. Trevor King

This avoids the current awkwardness of having either '' or 'checkout'
for checkout-mode updates, which makes testing for checkout-mode
updates (or non-checkout-mode updates) easier.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 git-submodule.sh | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 5247f78..5e8776c 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -803,17 +803,10 @@ cmd_update()
 			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")
@@ -882,11 +875,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=checkout ;;
 			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'")"
@@ -906,10 +904,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")
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v5 2/4] submodule: Document module_clone arguments in comments
  2014-01-26 20:45                                                                                 ` [PATCH v5 0/4] submodule: Local branch creation in module_clone W. Trevor King
  2014-01-26 20:45                                                                                   ` [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit W. Trevor King
@ 2014-01-26 20:45                                                                                   ` W. Trevor King
  2014-01-26 20:45                                                                                   ` [PATCH v5 3/4] submodule: Explicit local branch creation in module_clone W. Trevor King
  2014-01-26 20:45                                                                                   ` [PATCH v5 4/4] Documentation: Describe 'submodule update --remote' use case W. Trevor King
  3 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-26 20:45 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, Philip Oakley, John Keeping, W. Trevor King

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 git-submodule.sh | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/git-submodule.sh b/git-submodule.sh
index 5e8776c..68dcbe1 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -241,6 +241,12 @@ 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)
+#
 # 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,
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v5 3/4] submodule: Explicit local branch creation in module_clone
  2014-01-26 20:45                                                                                 ` [PATCH v5 0/4] submodule: Local branch creation in module_clone W. Trevor King
  2014-01-26 20:45                                                                                   ` [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit W. Trevor King
  2014-01-26 20:45                                                                                   ` [PATCH v5 2/4] submodule: Document module_clone arguments in comments W. Trevor King
@ 2014-01-26 20:45                                                                                   ` W. Trevor King
  2014-01-26 20:45                                                                                   ` [PATCH v5 4/4] Documentation: Describe 'submodule update --remote' use case W. Trevor King
  3 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-26 20:45 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, Philip Oakley, John Keeping, W. Trevor King

The previous code only checked out branches in cmd_add.  This commit
moves the branch-checkout logic into module_clone, where it can be
shared by cmd_add and cmd_update.  I also update the initial checkout
command to use 'reset' to preserve branches setup during module_clone.

With this change, folks cloning submodules for the first time via:

  $ git submodule update ...

will get a local branch instead of a detached HEAD, unless they are
using the default checkout-mode updates.  This is a change from the
previous situation where cmd_update always used checkout-mode logic
(regardless of the requested update mode) for updates that triggered
an initial clone, which always resulted in a detached HEAD.

This commit does not change the logic for updates after the initial
clone, which will continue to create detached HEADs for checkout-mode
updates, and integrate remote work with the local HEAD (detached or
not) in other modes.

The motivation for the change is that developers doing local work
inside the submodule are likely to select a non-checkout-mode for
updates so their local work is integrated with upstream work.
Developers who are not doing local submodule work stick with
checkout-mode updates so any apparently local work is blown away
during updates.  For example, if upstream rolls back the remote branch
or gitlinked commit to an earlier version, the checkout-mode developer
wants their old submodule checkout to be rolled back as well, instead
of getting a no-op merge/rebase with the rolled-back reference.

By using the update mode to distinguish submodule developers from
black-box submodule consumers, we can setup local branches for the
developers who will want local branches, and stick with detached HEADs
for the developers that don't care.

Testing
=======

In t7406, just-cloned checkouts now update to the gitlinked hash with
'reset', to preserve the local branch for situations where we're not
on a detached HEAD.

I also added explicit tests to t7406 for HEAD attachement after
cloning updates, showing that it depends on their update mode:

* Checkout-mode updates get detached HEADs
* Everyone else gets a local branch, matching the configured
  submodule.<name>.branch and defaulting to master.

The 'initial-setup' tag makes it easy to reset the superproject to a
known state, as several earlier tests commit to submodules and commit
the changed gitlinks to the superproject, but don't push the new
submodule commits to the upstream subprojects.  This makes it
impossible to checkout the current super master, because it references
submodule commits that don't exist in the upstream subprojects.  For a
specific example, see the tests that currently generate the
'two_new_submodule_commits' commits.

Documentation
=============

I updated the docs to describe the 'submodule update' modes in detail.
The old documentation did not distinguish between cloning and
non-cloning updates and lacked clarity on which operations would lead
to detached HEADs, and which would not.  The new documentation
addresses these issues while updating the docs to reflect the changes
introduced by this commit's explicit local branch creation in
module_clone.

I also add '--checkout' to the usage summary and group the update-mode
options into a single set.

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 Documentation/git-submodule.txt | 36 ++++++++++++++++++-------
 Documentation/gitmodules.txt    |  4 +++
 git-submodule.sh                | 58 +++++++++++++++++++++++++++++------------
 t/t7406-submodule-update.sh     | 39 ++++++++++++++++++++++++++-
 4 files changed, 110 insertions(+), 27 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index bfef8a0..2e1c7a2 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -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
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index f7be93f..385f35d 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -53,6 +53,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
diff --git a/git-submodule.sh b/git-submodule.sh
index 68dcbe1..626a746 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -246,6 +246,9 @@ module_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.
@@ -259,6 +262,8 @@ module_clone()
 	url=$3
 	reference="$4"
 	depth="$5"
+	start_point="$6"
+	local_branch="$7"
 	quiet=
 	if test -n "$GIT_QUIET"
 	then
@@ -312,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()
@@ -475,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"
 
@@ -803,7 +816,9 @@ 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
@@ -817,11 +832,19 @@ cmd_update()
 
 		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
@@ -835,7 +858,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
@@ -881,7 +905,7 @@ Maybe you want to use 'update --init'?")"
 			case ";$cloned_modules;" in
 			*";$name;"*)
 				# then there is no local change to integrate
-				update_module=checkout ;;
+				update_module='!git reset --hard -q'
 			esac
 
 			must_die_on_failure=
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 0825a92..f056c01 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -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
 	 ) &&
@@ -764,4 +767,38 @@ test_expect_success 'submodule update clone shallow submodule' '
 	 )
 	)
 '
+
+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
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v5 4/4] Documentation: Describe 'submodule update --remote' use case
  2014-01-26 20:45                                                                                 ` [PATCH v5 0/4] submodule: Local branch creation in module_clone W. Trevor King
                                                                                                     ` (2 preceding siblings ...)
  2014-01-26 20:45                                                                                   ` [PATCH v5 3/4] submodule: Explicit local branch creation in module_clone W. Trevor King
@ 2014-01-26 20:45                                                                                   ` W. Trevor King
  3 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-26 20:45 UTC (permalink / raw)
  To: Git
  Cc: Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, Philip Oakley, John Keeping, W. Trevor King

On Thu, Jan 16, 2014 at 12:21:04PM -0800, Junio C Hamano wrote [1]:
> I think copying some motivation from the log message of 06b1abb5
> (submodule update: add --remote for submodule's upstream changes,
> 2012-12-19) would help the readers here.  A naïve expectation from a
> casual reader of the above would be "The superproject's tree ought
> to point at the same commit as the tip of the branch used in the
> submodule (modulo mirroring delays and somesuch), if the repository
> of the superproject and submodules are maintained properly", which
> would lead to "when would any sane person need to use --remote in
> the first place???".

There have been other interpretation issues with the --remote option
as well.  With this commit, I try to make it clear that there is no
implicit floating going on; --remote lets you explicitly integrate the
upstream branch in your current HEAD (just like running 'git pull' in
the submodule).  The only distinction with the current 'git pull' is
the config location/setting used for the upstream branch, which is
hopefully clear now.

With syncing between the out-of-tree submodule config and the in-tree
superproject .gitmodules [2], you wouldn't have to chose between (or
manually sync) "easily distributable .gitmodules settings" and "native
submodule pull", but this patch is my take on the current situation.

[1]: http://article.gmane.org/gmane.comp.version-control.git/240529
[2]: http://article.gmane.org/gmane.comp.version-control.git/240336

Signed-off-by: W. Trevor King <wking@tremily.us>
---
 Documentation/git-submodule.txt | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 2e1c7a2..21cb59a 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -299,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::
-- 
1.8.5.2.8.g0f6c0d1

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit
  2014-01-26 20:45                                                                                   ` [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit W. Trevor King
@ 2014-01-27  1:32                                                                                     ` Eric Sunshine
  2014-01-27  1:59                                                                                       ` W. Trevor King
  0 siblings, 1 reply; 144+ messages in thread
From: Eric Sunshine @ 2014-01-27  1:32 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Git, Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, Philip Oakley, John Keeping

On Sun, Jan 26, 2014 at 3:45 PM, W. Trevor King <wking@tremily.us> wrote:
> This avoids the current awkwardness of having either '' or 'checkout'
> for checkout-mode updates, which makes testing for checkout-mode
> updates (or non-checkout-mode updates) easier.
>
> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---
>  git-submodule.sh | 27 +++++++++++----------------
>  1 file changed, 11 insertions(+), 16 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 5247f78..5e8776c 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -803,17 +803,10 @@ cmd_update()
>                         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"

Here, you (unnecessarily) quote 'checkout'...

> +                       fi
>                 fi
>
>                 displaypath=$(relative_path "$prefix$sm_path")
> @@ -882,11 +875,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=checkout ;;

But here you use bare (unquoted) 'checkout'. Bare is probably more idiomatic.

>                         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'")"
> @@ -906,10 +904,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")
> --
> 1.8.5.2.8.g0f6c0d1

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit
  2014-01-27  1:32                                                                                     ` Eric Sunshine
@ 2014-01-27  1:59                                                                                       ` W. Trevor King
  0 siblings, 0 replies; 144+ messages in thread
From: W. Trevor King @ 2014-01-27  1:59 UTC (permalink / raw)
  To: Eric Sunshine
  Cc: Git, Jens Lehmann, Francesco Pretto, Junio C Hamano, Heiko Voigt,
	Jonathan Nieder, Philip Oakley, John Keeping

[-- Attachment #1: Type: text/plain, Size: 683 bytes --]

On Sun, Jan 26, 2014 at 08:32:04PM -0500, Eric Sunshine wrote:
> On Sun, Jan 26, 2014 at 3:45 PM, W. Trevor King <wking@tremily.us> wrote:
> > +                               update_module="checkout"
> 
> Here, you (unnecessarily) quote 'checkout'...
> 
> > -                               update_module= ;;
> > +                               update_module=checkout ;;
> 
> But here you use bare (unquoted) 'checkout'. Bare is probably more
> idiomatic.

Whatever you want ;).  Queued for v6.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 144+ messages in thread

end of thread, other threads:[~2014-01-27  2:00 UTC | newest]

Thread overview: 144+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-30  1:49 [PATCH/RFC] Introduce git submodule add|update --attach Francesco Pretto
2013-12-31 20:05 ` Phil Hord
2014-01-02 18:48   ` Francesco Pretto
2014-01-13 17:31     ` Junio C Hamano
2014-01-02 20:07 ` Junio C Hamano
2014-01-02 23:42   ` Francesco Pretto
2014-01-03  0:26     ` Francesco Pretto
2014-01-03  8:49     ` Francesco Pretto
2014-01-03 18:06       ` [PATCH] submodule: Respect reqested branch on all clones W. Trevor King
2014-01-04 22:09         ` Heiko Voigt
2014-01-04 22:54           ` W. Trevor King
2014-01-05  0:39             ` Heiko Voigt
2014-01-05  1:08               ` W. Trevor King
2014-01-05  3:53         ` Francesco Pretto
2014-01-05 16:17           ` [RFC v2] submodule: Respect requested " W. Trevor King
2014-01-05 19:48             ` Heiko Voigt
2014-01-05 21:24               ` W. Trevor King
2014-01-05 22:57                 ` Heiko Voigt
2014-01-05 23:39                   ` W. Trevor King
2014-01-06  0:33                     ` W. Trevor King
2014-01-06  1:12                       ` W. Trevor King
2014-01-06 16:02                         ` Heiko Voigt
2014-01-06 23:10                           ` Francesco Pretto
2014-01-06 23:32                             ` Francesco Pretto
2014-01-07 18:27                               ` Junio C Hamano
2014-01-07 19:19                                 ` Francesco Pretto
2014-01-07 19:45                                   ` W. Trevor King
2014-01-07 19:48                                     ` Francesco Pretto
2014-01-07 21:37                                       ` W. Trevor King
2014-01-07 21:51                                         ` Francesco Pretto
2014-01-07 22:38                                     ` Heiko Voigt
2014-01-08  0:17                                       ` Francesco Pretto
2014-01-08  1:05                                         ` W. Trevor King
2014-01-08  2:12                                           ` Francesco Pretto
2014-01-08 23:07                                           ` Francesco Pretto
2014-01-09  0:03                                             ` W. Trevor King
2014-01-09  1:09                                               ` Francesco Pretto
2014-01-09  2:22                                                 ` W. Trevor King
2014-01-09  8:31                                                 ` Jens Lehmann
2014-01-09 17:32                                                   ` W. Trevor King
2014-01-09 19:23                                                     ` Jens Lehmann
2014-01-09 19:55                                                       ` W. Trevor King
2014-01-09 21:40                                                         ` Jens Lehmann
2014-01-09 22:18                                                           ` W. Trevor King
2014-01-14 10:24                                                             ` Heiko Voigt
2014-01-14 16:57                                                               ` W. Trevor King
2014-01-14 20:58                                                                 ` Heiko Voigt
2014-01-14 21:42                                                                   ` W. Trevor King
2014-01-14 22:19                                                                     ` Heiko Voigt
2014-01-14 22:39                                                                       ` W. Trevor King
2014-01-14 21:46                                                               ` Re: " Heiko Voigt
2014-01-14 22:22                                                                 ` W. Trevor King
2014-01-14 22:42                                                                   ` Heiko Voigt
2014-01-15  0:02                                                                     ` Francesco Pretto
2014-01-16  4:09                                                                     ` [PATCH v4 0/6] submodule: Local branch creation in module_clone W. Trevor King
2014-01-16  4:10                                                                       ` [PATCH v4 1/6] submodule: Make 'checkout' update_module explicit W. Trevor King
2014-01-16 18:46                                                                         ` Junio C Hamano
2014-01-16 19:22                                                                           ` W. Trevor King
2014-01-16 20:07                                                                             ` Francesco Pretto
2014-01-16 20:19                                                                               ` W. Trevor King
2014-01-16  4:10                                                                       ` [PATCH v4 2/6] submodule: Document module_clone arguments in comments W. Trevor King
2014-01-16  4:10                                                                       ` [PATCH v4 3/6] submodule: Explicit local branch creation in module_clone W. Trevor King
2014-01-16 19:18                                                                         ` Junio C Hamano
2014-01-16 19:29                                                                           ` W. Trevor King
2014-01-16 19:43                                                                         ` Junio C Hamano
2014-01-16 21:12                                                                           ` W. Trevor King
2014-01-16  4:10                                                                       ` [PATCH v4 4/6] t7406: Just-cloned checkouts update to the gitlinked hash with 'reset' W. Trevor King
2014-01-16 19:22                                                                         ` Junio C Hamano
2014-01-16 19:32                                                                           ` W. Trevor King
2014-01-16 20:24                                                                             ` Junio C Hamano
2014-01-16  4:10                                                                       ` [PATCH v4 5/6] t7406: Add explicit tests for head attachement after cloning updates W. Trevor King
2014-01-16  4:10                                                                       ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail W. Trevor King
2014-01-16 20:21                                                                         ` Junio C Hamano
2014-01-16 20:55                                                                           ` W. Trevor King
2014-01-16 21:02                                                                             ` John Keeping
2014-01-16 21:16                                                                               ` W. Trevor King
2014-01-16 21:55                                                                             ` Junio C Hamano
2014-01-17  2:37                                                                               ` W. Trevor King
2014-01-26 20:45                                                                                 ` [PATCH v5 0/4] submodule: Local branch creation in module_clone W. Trevor King
2014-01-26 20:45                                                                                   ` [PATCH v5 1/4] submodule: Make 'checkout' update_module explicit W. Trevor King
2014-01-27  1:32                                                                                     ` Eric Sunshine
2014-01-27  1:59                                                                                       ` W. Trevor King
2014-01-26 20:45                                                                                   ` [PATCH v5 2/4] submodule: Document module_clone arguments in comments W. Trevor King
2014-01-26 20:45                                                                                   ` [PATCH v5 3/4] submodule: Explicit local branch creation in module_clone W. Trevor King
2014-01-26 20:45                                                                                   ` [PATCH v5 4/4] Documentation: Describe 'submodule update --remote' use case W. Trevor King
2014-01-16 22:18                                                                           ` [PATCH v4 6/6] Documentation: Describe 'submodule update' modes in detail Philip Oakley
2014-01-16 22:35                                                                             ` W. Trevor King
2014-01-08 23:54                                           ` Re: [RFC v2] submodule: Respect requested branch on all clones Francesco Pretto
2014-01-09  0:23                                             ` W. Trevor King
2014-01-07 19:52                                   ` Francesco Pretto
2014-01-06 15:47                     ` Re: " Heiko Voigt
2014-01-06 17:22                       ` W. Trevor King
2014-01-05 21:27             ` Francesco Pretto
2014-01-05 21:47               ` W. Trevor King
2014-01-05 22:01                 ` W. Trevor King
2014-01-06 14:47               ` Heiko Voigt
2014-01-06 16:56                 ` Junio C Hamano
2014-01-06 17:37                   ` W. Trevor King
2014-01-06 21:32                     ` Junio C Hamano
2014-01-07  0:55                   ` Francesco Pretto
2014-01-07 18:15             ` Junio C Hamano
2014-01-07 18:47               ` W. Trevor King
2014-01-07 19:21                 ` Junio C Hamano
2014-01-07 19:50                   ` W. Trevor King
2014-01-05  2:50       ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Francesco Pretto
2014-01-05  2:50         ` [PATCH 2/2] Introduce git submodule attached update Francesco Pretto
2014-01-05 19:55           ` Francesco Pretto
2014-01-05 20:33           ` Heiko Voigt
2014-01-05 21:46             ` Francesco Pretto
2014-01-06 14:06               ` Heiko Voigt
2014-01-06 17:47                 ` Francesco Pretto
2014-01-06 19:21                   ` David Engster
2014-01-07 19:27                     ` W. Trevor King
2014-01-07  4:10                   ` W. Trevor King
2014-01-07 22:36                     ` Preferred local submodule branches (was: Introduce git submodule attached update) W. Trevor King
2014-01-07 23:52                       ` W. Trevor King
2014-01-08  3:47                         ` Preferred local submodule branches W. Trevor King
2014-01-08  4:06                           ` W. Trevor King
2014-01-09  6:17                             ` [RFC v3 0/4] " W. Trevor King
2014-01-09  6:17                               ` [RFC v3 1/4] submodule: Add helpers for configurable local branches W. Trevor King
2014-01-09  6:17                               ` [RFC v3 2/4] submodule: Teach 'update' to preserve " W. Trevor King
2014-01-09  6:17                               ` [RFC v3 3/4] submodule: Teach 'add' about a configurable local-branch W. Trevor King
2014-01-15  0:18                                 ` Francesco Pretto
2014-01-15  1:02                                   ` W. Trevor King
2014-01-09  6:17                               ` [RFC v3 4/4] submodule: Add a new 'checkout' command W. Trevor King
2014-01-12  1:08                               ` Tight submodule bindings (was: Preferred local submodule branches) W. Trevor King
2014-01-13 19:37                                 ` Tight submodule bindings Jens Lehmann
2014-01-13 20:07                                   ` W. Trevor King
2014-01-13 22:13                                 ` Junio C Hamano
2014-01-14  2:44                                   ` W. Trevor King
2014-01-07 22:51                     ` Re: [PATCH 2/2] Introduce git submodule attached update Heiko Voigt
2014-01-07 23:14                       ` W. Trevor King
2014-01-07 18:56                   ` Junio C Hamano
2014-01-07 19:44                     ` Francesco Pretto
2014-01-07 19:07                   ` Junio C Hamano
2014-01-07 19:25                     ` Francesco Pretto
2014-01-05 23:22             ` Francesco Pretto
2014-01-06 14:18               ` Heiko Voigt
2014-01-06 15:58                 ` W. Trevor King
2014-01-05 20:20         ` [PATCH 1/2] git-submodule.sh: Support 'checkout' as a valid update command Heiko Voigt
2014-01-05 20:44         ` W. Trevor King
2014-01-06 16:20           ` Junio C Hamano
2014-01-06 17:42             ` Junio C Hamano
2014-01-06 17:52               ` Francesco Pretto

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.