for preparation of new feature: Head reduction before selecting merge strategy Signed-off-by: Sverre Hvammen Johansen <hvammen@xxxxxxxxx> --- git-merge.sh | 166 ++++++++++++++++++++++++++++++---------------------------- 1 files changed, 85 insertions(+), 81 deletions(-) diff --git a/git-merge.sh b/git-merge.sh index 17f40f2..2acd2cc 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -207,6 +207,29 @@ parse_config () { args_left=$# } +# Find real parents +# Set the following variables as followd: +# real_parents: The parents specified on the command line +# common: All common ancestors or not_queried +# ff_head: Fast forward of head +find_real_parents () { + real_parents=$(git rev-parse "$@") + real_parents=${real_parents#$LF} + if test $# = 1 + then + common=$(git merge-base --all $head "$@") + if test "$common" = $head + then + ff_head=$1 + else + ff_head=$head + fi + else + common=not_queried + ff_head=$head + fi +} + test $# != 0 || usage have_message= @@ -294,24 +317,26 @@ do done set x $remoteheads ; shift +find_real_parents "$@" + case "$use_strategies" in '') - case "$#" in - 1) - var="`git config --get pull.twohead`" + case "$real_parents" in + ?*"$LF"?*) + var="`git config --get pull.octopus`" if test -n "$var" then use_strategies="$var" else - use_strategies="$default_twohead_strategies" + use_strategies="$default_octopus_strategies" fi ;; *) - var="`git config --get pull.octopus`" + var="`git config --get pull.twohead`" if test -n "$var" then use_strategies="$var" else - use_strategies="$default_octopus_strategies" + use_strategies="$default_twohead_strategies" fi ;; esac ;; @@ -339,87 +364,66 @@ do done done -case "$#" in -1) - common=$(git merge-base --all $head "$@") - ;; -*) - common=$(git show-branch --merge-base $head "$@") - ;; -esac echo "$head" >"$GIT_DIR/ORIG_HEAD" -case "$fast_forward,$#,$common,$no_commit" in -*,*,'',*) - # No common ancestors found. We need a real merge. - ;; -*,1,"$1",*) - # If head can reach all the merge then we are up to date. - # but first the most common case of merging one remote. - finish_up_to_date "Already up-to-date." - exit 0 - ;; -allow,1,"$head",*) - # 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" +if true +then + if test $head = $ff_head -a "$common" = "$real_parents" 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" "$msg" || exit - dropsave - exit 0 - ;; -*,1,?*"$LF"?*,*) - # We are not doing octopus and not fast forward. Need a - # real merge. - ;; -*,1,*,) - # 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) - # 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. - up_to_date=t - for remote - do - common_one=$(git merge-base --all $head $remote) - if test "$common_one" != "$remote" + finish_up_to_date "Already up-to-date." + exit 0 + elif test $fast_forward != never -a $ff_head = "$real_parents" + then + echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $ff_head)" + git update-index --refresh 2>/dev/null + msg="Fast forward" + if test -n "$have_message" then - up_to_date=f - break + msg="$msg (no commit created; -m option ignored)" fi - done - if test "$up_to_date" = t - then - finish_up_to_date "Already up-to-date. Yeeah!" + new_head=$(git rev-parse --verify "$ff_head^0") && + git read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" && + finish "$new_head" "$msg" || exit + dropsave exit 0 fi +fi + +case "$real_parents" in +?*"$LF"?*) + # We have more than one parent + common=$(git show-branch --merge-base $head $real_parents) ;; +*) + # We have exactly one parent + test "$common" != not_queried || common=$(git merge-base --all $head $real_parents) + case "$common" in + ?*"$LF"?*) + # We are not doing octopus and not fast forward. Need a + # real merge. + ;; + *) + git update-index --refresh 2>/dev/null + if test "$allow_trivial_merge" = t + then + # 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 $real_parents && + result_tree=$(git write-tree) + then + echo "Wonderful." + result_commit=$( + printf '%s\n' "$merge_msg" | + git commit-tree $result_tree -p HEAD -p $real_parents + ) || exit + finish "$result_commit" "In-index merge" + dropsave + exit 0 + fi + echo "Nope." + fi ;; + esac ;; esac # We are going to make a new commit. @@ -460,7 +464,7 @@ do # Remember which strategy left the state in the working tree wt_strategy=$strategy - git-merge-$strategy $common -- "$head_arg" "$@" + git-merge-$strategy $common -- "$head_arg" $real_parents exit=$? if test "$no_commit" = t && test "$exit" = 0 then @@ -530,7 +534,7 @@ case "$best_strategy" in echo "Rewinding the tree to pristine..." restorestate echo "Using the $best_strategy to prepare resolving by hand." - git-merge-$best_strategy $common -- "$head_arg" "$@" + git-merge-$best_strategy $common -- "$head_arg" $real_parents ;; esac -- Sverre Hvammen Johansen -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html