Fix default pull not to do an unintended Octopus.
authorJunio C Hamano <junkio@cox.net>
Mon, 26 Sep 2005 05:54:23 +0000 (22:54 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 28 Sep 2005 23:22:00 +0000 (16:22 -0700)
The refspecs specified in the .git/remotes/<remote> on the "Pull: "
lines are for fetching multiple heads in one go, but most of the time
making an Octopus out of them is not what is wanted.  Make git-fetch
leave the marker in .git/FETCH_HEAD file so that later stages can
tell which heads are for merging and which are not.

Tom Prince made me realize how stupid the original behaviour was.

Signed-off-by: Junio C Hamano <junkio@cox.net>
git-fetch.sh
git-fmt-merge-msg.perl
git-parse-remote.sh
git-pull.sh

index e4a6a68057edf0ff8cd4067f334ddf1eed211e44..82d897231a488d91d5408c7710dd481cf862171d 100755 (executable)
@@ -54,6 +54,10 @@ append_fetch_head () {
     remote_name_="$3"
     remote_nick_="$4"
     local_name_="$5"
+    case "$6" in
+    t) not_for_merge_='not-for-merge' ;;
+    '') not_for_merge_= ;;
+    esac
 
     # remote-nick is the URL given on the command line (or a shorthand)
     # remote-name is the $GIT_DIR relative refs/ path we computed
@@ -78,10 +82,11 @@ append_fetch_head () {
     if git-cat-file commit "$head_" >/dev/null 2>&1
     then
        headc_=$(git-rev-parse --verify "$head_^0") || exit
-       echo "$headc_   $note_" >>$GIT_DIR/FETCH_HEAD
+       echo "$headc_   $not_for_merge_ $note_" >>$GIT_DIR/FETCH_HEAD
        echo >&2 "* committish: $head_"
        echo >&2 "  $note_"
     else
+       echo "$head_    not-for-merge   $note_" >>$GIT_DIR/FETCH_HEAD
        echo >&2 "* non-commit: $head_"
        echo >&2 "  $note_"
     fi
@@ -157,6 +162,13 @@ do
 
     # These are relative path from $GIT_DIR, typically starting at refs/
     # but may be HEAD
+    if expr "$ref" : '\.' >/dev/null
+    then
+       not_for_merge=t
+       ref=$(expr "$ref" : '\.\(.*\)')
+    else
+       not_for_merge=
+    fi
     if expr "$ref" : '\+' >/dev/null
     then
        single_force=t
@@ -216,7 +228,8 @@ do
        continue ;;
     esac
 
-    append_fetch_head "$head" "$remote" "$remote_name" "$remote_nick" "$local_name"
+    append_fetch_head "$head" "$remote" \
+       "$remote_name" "$remote_nick" "$local_name" "$not_for_merge"
 
 done
 
@@ -241,16 +254,27 @@ http://* | https://* | rsync://* )
            case "$ref" in
            +$remote_name:*)
                single_force=t
+               not_for_merge=
+               found="$ref"
+               break ;;
+           .+$remote_name:*)
+               single_force=t
+               not_for_merge=t
+               found="$ref"
+               break ;;
+           .$remote_name:*)
+               not_for_merge=t
                found="$ref"
                break ;;
            $remote_name:*)
+               not_for_merge=
                found="$ref"
                break ;;
            esac
        done
-
        local_name=$(expr "$found" : '[^:]*:\(.*\)')
-       append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name"
+       append_fetch_head "$sha1" "$remote" \
+               "$remote_name" "$remote_nick" "$local_name" "$not_for_merge"
     done || exit
     ;;
 esac
index f0f3100eb1c089efd990b71bb747f4dd0cd035f9..778388e254e8ecc07494c168aec503e3bc511fb3 100755 (executable)
@@ -31,6 +31,8 @@ while (<>) {
        my ($bname, $tname, $gname, $src);
        chomp;
        s/^[0-9a-f]*    //;
+       next if (/^not-for-merge/);
+       s/^     //;
        if (s/ of (.*)$//) {
                $src = $1;
        } else {
@@ -86,7 +88,7 @@ for my $src (@src) {
                            $src{$src}{GENERIC});
        my $this = join(', ', @this);
        if ($src ne '.') {
-               $this .= " from $src";
+               $this .= " of $src";
        }
        push @msg, $this;
 }
index a9db0cd82558af9bebec083450b35348a1d0b29a..4d8a572a9903179494c7cc4f8a72729a47f1c12b 100755 (executable)
@@ -65,8 +65,11 @@ get_remote_default_refs_for_push () {
        esac
 }
 
-# Subroutine to canonicalize remote:local notation
+# Subroutine to canonicalize remote:local notation.
 canon_refs_list_for_fetch () {
+       # Leave only the first one alone; add prefix . to the rest
+       # to prevent the secondary branches to be merged by default.
+       dot_prefix=
        for ref
        do
                force=
@@ -91,7 +94,8 @@ canon_refs_list_for_fetch () {
                heads/* | tags/* ) local="refs/$local" ;;
                *) local="refs/heads/$local" ;;
                esac
-               echo "${force}${remote}:${local}"
+               echo "${dot_prefix}${force}${remote}:${local}"
+               dot_prefix=.
        done
 }
 
@@ -107,6 +111,9 @@ get_remote_default_refs_for_fetch () {
                echo "refs/heads/${remote_branch}:refs/heads/$1"
                ;;
        remotes)
+               # This prefixes the second and later default refspecs
+               # with a '.', to signal git-fetch to mark them
+               # not-for-merge.
                canon_refs_list_for_fetch $(sed -ne '/^Pull: */{
                                                s///p
                                        }' "$GIT_DIR/remotes/$1")
index e3d11961b0a5a7608648348153bde0ab6e7ccfff..67c7f9562b54acd08b67c840f508bd20f0879947 100755 (executable)
@@ -24,7 +24,9 @@ then
                die "You need to first update your working tree."
 fi
 
-merge_head=$(sed -e 's/        .*//' "$GIT_DIR"/FETCH_HEAD | tr '\012' ' ')
+merge_head=$(sed -e '/ not-for-merge   /d' \
+       -e 's/  .*//' "$GIT_DIR"/FETCH_HEAD | \
+       tr '\012' ' ')
 
 case "$merge_head" in
 '')