Merge branch 'tr/maint-merge-file-subdir'
[gitweb.git] / contrib / examples / git-merge.sh
index 0d53735d6719dfcc37b8651c26acdef2172e3ee9..7b922c39480c8b78d0687cbabac59672f9ae6ede 100755 (executable)
@@ -15,6 +15,8 @@ log                  add list of one-line log to merge commit message
 squash               create a single commit instead of doing a merge
 commit               perform a commit if the merge succeeds (default)
 ff                   allow fast-forward (default)
+ff-only              abort if fast-forward is not possible
+rerere-autoupdate    update index with any reused conflict resolution
 s,strategy=          merge strategy to use
 X=                   option for selected merge strategy
 m,message=           message to be used for the merge commit (if any)
@@ -36,6 +38,7 @@ LF='
 
 all_strategies='recur recursive octopus resolve stupid ours subtree'
 all_strategies="$all_strategies recursive-ours recursive-theirs"
+not_strategies='base file index tree'
 default_twohead_strategies='recursive'
 default_octopus_strategies='octopus'
 no_fast_forward_strategies='subtree ours'
@@ -44,12 +47,13 @@ use_strategies=
 xopt=
 
 allow_fast_forward=t
+fast_forward_only=
 allow_trivial_merge=t
-squash= no_commit= log_arg=
+squash= no_commit= log_arg= rr_arg=
 
 dropsave() {
        rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \
-                "$GIT_DIR/MERGE_STASH" || exit 1
+                "$GIT_DIR/MERGE_STASH" "$GIT_DIR/MERGE_MODE" || exit 1
 }
 
 savestate() {
@@ -145,13 +149,15 @@ merge_name () {
        if found_ref=$(git rev-parse --symbolic-full-name --verify \
                                                        "$remote" 2>/dev/null)
        then
+               expanded=$(git check-ref-format --branch "$remote") ||
+                       exit
                if test "${found_ref#refs/heads/}" != "$found_ref"
                then
-                       echo "$rh               branch '$remote' of ."
+                       echo "$rh               branch '$expanded' of ."
                        return
                elif test "${found_ref#refs/remotes/}" != "$found_ref"
                then
-                       echo "$rh               remote branch '$remote' of ."
+                       echo "$rh               remote branch '$expanded' of ."
                        return
                fi
        fi
@@ -188,14 +194,30 @@ parse_config () {
                --no-ff)
                        test "$squash" != t ||
                                die "You cannot combine --squash with --no-ff."
+                       test "$fast_forward_only" != t ||
+                               die "You cannot combine --ff-only with --no-ff."
                        allow_fast_forward=f ;;
+               --ff-only)
+                       test "$allow_fast_forward" != f ||
+                               die "You cannot combine --ff-only with --no-ff."
+                       fast_forward_only=t ;;
+               --rerere-autoupdate|--no-rerere-autoupdate)
+                       rr_arg=$1 ;;
                -s|--strategy)
                        shift
                        case " $all_strategies " in
                        *" $1 "*)
-                               use_strategies="$use_strategies$1 " ;;
+                               use_strategies="$use_strategies$1 "
+                               ;;
                        *)
-                               die "available strategies are: $all_strategies" ;;
+                               case " $not_strategies " in
+                               *" $1 "*)
+                                       false
+                               esac &&
+                               type "git-merge-$1" >/dev/null 2>&1 ||
+                                       die "available strategies are: $all_strategies"
+                               use_strategies="$use_strategies$1 "
+                               ;;
                        esac
                        ;;
                -X)
@@ -285,12 +307,18 @@ else
        # the given message.  If remote is invalid we will die
        # later in the common codepath so we discard the error
        # in this loop.
-       merge_name=$(for remote
+       merge_msg="$(
+               for remote
                do
                        merge_name "$remote"
-               done | git fmt-merge-msg $log_arg
-       )
-       merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"
+               done |
+               if test "$have_message" = t
+               then
+                       git fmt-merge-msg -m "$merge_msg" $log_arg
+               else
+                       git fmt-merge-msg $log_arg
+               fi
+       )"
 fi
 head=$(git rev-parse --verify "$head_arg"^0) || usage
 
@@ -359,7 +387,7 @@ case "$#" in
        common=$(git merge-base --all $head "$@")
        ;;
 *)
-       common=$(git show-branch --merge-base $head "$@")
+       common=$(git merge-base --all --octopus $head "$@")
        ;;
 esac
 echo "$head" >"$GIT_DIR/ORIG_HEAD"
@@ -397,8 +425,8 @@ t,1,"$head",*)
        # We are not doing octopus, not fast-forward, and have only
        # one common.
        git update-index --refresh 2>/dev/null
-       case "$allow_trivial_merge" in
-       t)
+       case "$allow_trivial_merge,$fast_forward_only" in
+       t,)
                # See if it is really trivial.
                git var GIT_COMMITTER_IDENT >/dev/null || exit
                echo "Trying really trivial in-index merge..."
@@ -437,6 +465,11 @@ t,1,"$head",*)
        ;;
 esac
 
+if test "$fast_forward_only" = t
+then
+       die "Not possible to fast-forward, aborting."
+fi
+
 # We are going to make a new commit.
 git var GIT_COMMITTER_IDENT >/dev/null || exit
 
@@ -513,9 +546,9 @@ if test '' != "$result_tree"
 then
     if test "$allow_fast_forward" = "t"
     then
-        parents=$(git show-branch --independent "$head" "$@")
+       parents=$(git merge-base --independent "$head" "$@")
     else
-        parents=$(git rev-parse "$head" "$@")
+       parents=$(git rev-parse "$head" "$@")
     fi
     parents=$(echo "$parents" | sed -e 's/^/-p /')
     result_commit=$(printf '%s\n' "$merge_msg" | git commit-tree $result_tree $parents) || exit
@@ -557,7 +590,15 @@ else
        do
                echo $remote
        done >"$GIT_DIR/MERGE_HEAD"
-       printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG"
+       printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG" ||
+               die "Could not write to $GIT_DIR/MERGE_MSG"
+       if test "$allow_fast_forward" != t
+       then
+               printf "%s" no-ff
+       else
+               :
+       fi >"$GIT_DIR/MERGE_MODE" ||
+               die "Could not write to $GIT_DIR/MERGE_MODE"
 fi
 
 if test "$merge_was_ok" = t
@@ -574,6 +615,6 @@ Conflicts:
                sed -e 's/^[^   ]*      /       /' |
                uniq
        } >>"$GIT_DIR/MERGE_MSG"
-       git rerere
+       git rerere $rr_arg
        die "Automatic merge failed; fix conflicts and then commit the result."
 fi