cvsimport: add <remote>/HEAD reference in separate remotes more
[gitweb.git] / git-merge.sh
index aec215e725826fb18a4d3d75408aa44acdd3e5de..981d69d35f4e6349d99192996af3b793071a6172 100755 (executable)
@@ -3,17 +3,23 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-USAGE='[-n] [--no-commit] [--squash] [-s <strategy>] [--reflog-action=<action>] [-m=<merge-message>] <commit>+'
+USAGE='[-n] [--summary] [--no-commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'
 
+SUBDIRECTORY_OK=Yes
 . git-sh-setup
+require_work_tree
+cd_to_toplevel
+
+test -z "$(git ls-files -u)" ||
+       die "You are in the middle of a conflicted merge."
 
 LF='
 '
 
-all_strategies='recur recursive octopus resolve stupid ours'
+all_strategies='recur recursive octopus resolve stupid ours subtree'
 default_twohead_strategies='recursive'
 default_octopus_strategies='octopus'
-no_trivial_merge_strategies='ours'
+no_trivial_merge_strategies='ours subtree'
 use_strategies=
 
 index_merge=t
@@ -57,10 +63,10 @@ squash_message () {
 finish () {
        if test '' = "$2"
        then
-               rlogm="$rloga"
+               rlogm="$GIT_REFLOG_ACTION"
        else
                echo "$2"
-               rlogm="$rloga: $2"
+               rlogm="$GIT_REFLOG_ACTION: $2"
        fi
        case "$squash" in
        t)
@@ -82,11 +88,11 @@ finish () {
        '')
                ;;
        ?*)
-               case "$no_summary" in
-               '')
-                       git-diff-tree --stat --summary -M "$head" "$1"
-                       ;;
-               esac
+               if test "$show_diffstat" = t
+               then
+                       # We want color (if set), but no pager
+                       GIT_PAGER='' git-diff --stat --summary -M "$head" "$1"
+               fi
                ;;
        esac
 }
@@ -102,6 +108,10 @@ merge_name () {
                git-show-ref -q --verify "refs/heads/$truname" 2>/dev/null
        then
                echo "$rh               branch '$truname' (early part) of ."
+       elif test "$remote" = "FETCH_HEAD" -a -r "$GIT_DIR/FETCH_HEAD"
+       then
+               sed -e 's/      not-for-merge   /               /' -e 1q \
+                       "$GIT_DIR/FETCH_HEAD"
        else
                echo "$rh               commit '$remote'"
        fi
@@ -109,13 +119,15 @@ merge_name () {
 
 case "$#" in 0) usage ;; esac
 
-rloga= have_message=
+have_message=
 while case "$#" in 0) break ;; esac
 do
        case "$1" in
        -n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\
                --no-summa|--no-summar|--no-summary)
-               no_summary=t ;;
+               show_diffstat=false ;;
+       --summary)
+               show_diffstat=t ;;
        --sq|--squ|--squa|--squas|--squash)
                squash=t no_commit=t ;;
        --no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
@@ -139,9 +151,6 @@ do
                        die "available strategies are: $all_strategies" ;;
                esac
                ;;
-       --reflog-action=*)
-               rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
-               ;;
        -m=*|--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
                merge_msg=`expr "z$1" : 'z-[^=]*=\(.*\)'`
                have_message=t
@@ -160,6 +169,11 @@ do
        shift
 done
 
+if test -z "$show_diffstat"; then
+    test "$(git-config --bool merge.diffstat)" = false && show_diffstat=false
+    test -z "$show_diffstat" && show_diffstat=t
+fi
+
 # This could be traditional "merge <msg> HEAD <commit>..."  and the
 # way we can tell it is to see if the second token is HEAD, but some
 # people might have misused the interface and used a committish that
@@ -213,7 +227,7 @@ head=$(git-rev-parse --verify "$head_arg"^0) || usage
 
 # All the rest are remote heads
 test "$#" = 0 && usage ;# we need at least one remote head.
-test "$rloga" = '' && rloga="merge: $@"
+set_reflog_action "merge $*"
 
 remoteheads=
 for remote
@@ -221,6 +235,8 @@ do
        remotehead=$(git-rev-parse --verify "$remote"^0 2>/dev/null) ||
            die "$remote - not something we can merge"
        remoteheads="${remoteheads}$remotehead "
+       eval GITHEAD_$remotehead='"$remote"'
+       export GITHEAD_$remotehead
 done
 set x $remoteheads ; shift
 
@@ -228,21 +244,36 @@ case "$use_strategies" in
 '')
        case "$#" in
        1)
-               use_strategies="$default_twohead_strategies" ;;
+               var="`git-config --get pull.twohead`"
+               if test -n "$var"
+               then
+                       use_strategies="$var"
+               else
+                       use_strategies="$default_twohead_strategies"
+               fi ;;
        *)
-               use_strategies="$default_octopus_strategies" ;;
+               var="`git-config --get pull.octopus`"
+               if test -n "$var"
+               then
+                       use_strategies="$var"
+               else
+                       use_strategies="$default_octopus_strategies"
+               fi ;;
        esac
        ;;
 esac
 
 for s in $use_strategies
 do
-       case " $s " in
-       *" $no_trivial_merge_strategies "*)
-               index_merge=f
-               break
-               ;;
-       esac
+       for nt in $no_trivial_merge_strategies
+       do
+               case " $s " in
+               *" $nt "*)
+                       index_merge=f
+                       break
+                       ;;
+               esac
+       done
 done
 
 case "$#" in
@@ -272,9 +303,14 @@ f,*)
        # Again the most common case of merging one remote.
        echo "Updating $(git-rev-parse --short $head)..$(git-rev-parse --short $1)"
        git-update-index --refresh 2>/dev/null
+       msg="Fast forward"
+       if test -n "$have_message"
+       then
+               msg="$msg (no commit created; -m option ignored)"
+       fi
        new_head=$(git-rev-parse --verify "$1^0") &&
        git-read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
-       finish "$new_head" "Fast forward"
+       finish "$new_head" "$msg" || exit
        dropsave
        exit 0
        ;;
@@ -284,24 +320,30 @@ f,*)
        ;;
 ?,1,*,)
        # We are not doing octopus, not fast forward, and have only
-       # one common.  See if it is really trivial.
-       git var GIT_COMMITTER_IDENT >/dev/null || exit
-
-       echo "Trying really trivial in-index merge..."
+       # one common.
        git-update-index --refresh 2>/dev/null
-       if git-read-tree --trivial -m -u -v $common $head "$1" &&
-          result_tree=$(git-write-tree)
-       then
-           echo "Wonderful."
-           result_commit=$(
-               echo "$merge_msg" |
-               git-commit-tree $result_tree -p HEAD -p "$1"
-           ) || exit
-           finish "$result_commit" "In-index merge"
-           dropsave
-           exit 0
-       fi
-       echo "Nope."
+       case " $use_strategies " in
+       *' recursive '*|*' recur '*)
+               : run merge later
+               ;;
+       *)
+               # See if it is really trivial.
+               git var GIT_COMMITTER_IDENT >/dev/null || exit
+               echo "Trying really trivial in-index merge..."
+               if git-read-tree --trivial -m -u -v $common $head "$1" &&
+                  result_tree=$(git-write-tree)
+               then
+                       echo "Wonderful."
+                       result_commit=$(
+                               printf '%s\n' "$merge_msg" |
+                               git-commit-tree $result_tree -p HEAD -p "$1"
+                       ) || exit
+                       finish "$result_commit" "In-index merge"
+                       dropsave
+                       exit 0
+               fi
+               echo "Nope."
+       esac
        ;;
 *)
        # An octopus.  If we can reach all the remote we are up to date.
@@ -398,7 +440,7 @@ done
 if test '' != "$result_tree"
 then
     parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
-    result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
+    result_commit=$(printf '%s\n' "$merge_msg" | git-commit-tree $result_tree $parents) || exit
     finish "$result_commit" "Merge made by $wt_strategy."
     dropsave
     exit 0
@@ -437,7 +479,7 @@ else
        do
                echo $remote
        done >"$GIT_DIR/MERGE_HEAD"
-       echo "$merge_msg" >"$GIT_DIR/MERGE_MSG"
+       printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG"
 fi
 
 if test "$merge_was_ok" = t