Subject: Re: [PATCH] Documentation: update git-pull.txt for clone's new default behavior

From: Junio C Hamano <[email-masked]>
Date: Sun, 31 Dec 2006 17:44:37 -0800

Junio C Hamano <[email-masked]> writes:

> What we wanted to do ideally was to forbid "git pull" that does
> not have explicit refspec from the command line, without
> configuring branch.*.merge.  However this broke established
> workflow of people who has remote.$origin.fetch configured to
> list the remote branch to fetch explicitly; the merged branch
> selection has always been "the first set of branches listed in
> the configuration" and these peoples had their configuration
> right without needing to have branch.*.merge at all.
>
> Unfortunately git is too flexible around this area.  
>
> We probably could somehow arrante the remote branches that came
> from wildcarding not subject to the merge branch selection
> logic, but honestly I am tired of looking at that code for now.

I am still tired of looking at the code, but I would rather 
look at it now than having to still look at it next year.

How about doing this?  The difference this time around is that
if you have non-wildcard refspec listed first, which usually
is the case for people with established git workflow with
existing repositories, we use the old-and-proven rule to
merge the first set of refs.  An earlier round botched this
completely by basing the logic on lack of branch.*.merge,
which broke for many people.

-- >8 --
[PATCH] Do not merge random set of refs out of wildcarded refs

When your fetch configuration has only the wildcards, we would
pick the lexicographically first ref from the remote side for
merging, which was complete nonsense.  Make sure nothing except
the one that is specified with branch.*.merge is merged in this
case.

Signed-off-by: Junio C Hamano <[email-masked]>

---

diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 144f170..d2e4c2b 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -76,16 +76,32 @@ get_remote_default_refs_for_push () {
 # from get_remote_refs_for_fetch when it deals with refspecs
 # supplied on the command line.  $ls_remote_result has the list
 # of refs available at remote.
+#
+# The first token returned is either "explicit" or "glob"; this
+# is to help prevent randomly "globbed" ref from being chosen as
+# a merge candidate
 expand_refs_wildcard () {
+	first_one=yes
 	for ref
 	do
 		lref=${ref#'+'}
 		# a non glob pattern is given back as-is.
 		expr "z$lref" : 'zrefs/.*/\*:refs/.*/\*$' >/dev/null || {
+			if test -n "$first_one"
+			then
+				echo "explicit"
+				first_one=
+			fi
 			echo "$ref"
 			continue
 		}
 
+		# glob
+		if test -n "$first_one"
+		then
+			echo "glob"
+			first_one=
+		fi
 		from=`expr "z$lref" : 'z\(refs/.*/\)\*:refs/.*/\*$'`
 		to=`expr "z$lref" : 'zrefs/.*/\*:\(refs/.*/\)\*$'`
 		local_force=
@@ -116,7 +132,8 @@ canon_refs_list_for_fetch () {
 	if test "$1" = "-d"
 	then
 		shift ; remote="$1" ; shift
-		set x $(expand_refs_wildcard "$@")
+		set $(expand_refs_wildcard "$@")
+		is_explicit="$1"
 		shift
 		if test "$remote" = "$(get_default_remote)"
 		then
@@ -125,6 +142,10 @@ canon_refs_list_for_fetch () {
 			merge_branches=$(git-repo-config \
 			    --get-all "branch.${curr_branch}.merge")
 		fi
+		if test -z "$merge_branches" && test $is_explicit != explicit
+		then
+			merge_branches=..this.will.never.match.any.ref..
+		fi
 	fi
 	for ref
 	do