git-merge.shon commit simple euristic for further free packing improvements (4e8da19)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5
   6
   7USAGE='[-n] [--no-commit] [-s <strategy>]... <merge-message> <head> <remote>+'
   8. git-sh-setup
   9
  10LF='
  11'
  12
  13all_strategies='recursive octopus resolve stupid ours'
  14default_twohead_strategies='recursive'
  15default_octopus_strategies='octopus'
  16no_trivial_merge_strategies='ours'
  17use_strategies=
  18
  19index_merge=t
  20if test "@@NO_PYTHON@@"; then
  21        all_strategies='resolve octopus stupid ours'
  22        default_twohead_strategies='resolve'
  23fi
  24
  25dropsave() {
  26        rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \
  27                 "$GIT_DIR/MERGE_SAVE" || exit 1
  28}
  29
  30savestate() {
  31        # Stash away any local modifications.
  32        git-diff-index -z --name-only $head |
  33        cpio -0 -o >"$GIT_DIR/MERGE_SAVE"
  34}
  35
  36restorestate() {
  37        if test -f "$GIT_DIR/MERGE_SAVE"
  38        then
  39                git reset --hard $head
  40                cpio -iuv <"$GIT_DIR/MERGE_SAVE"
  41                git-update-index --refresh >/dev/null
  42        fi
  43}
  44
  45finish () {
  46        test '' = "$2" || echo "$2"
  47        case "$merge_msg" in
  48        '')
  49                echo "No merge message -- not updating HEAD"
  50                ;;
  51        *)
  52                git-update-ref HEAD "$1" "$head" || exit 1
  53                ;;
  54        esac
  55
  56        case "$no_summary" in
  57        '')
  58                git-diff-tree -p -M "$head" "$1" |
  59                git-apply --stat --summary
  60                ;;
  61        esac
  62}
  63
  64while case "$#" in 0) break ;; esac
  65do
  66        case "$1" in
  67        -n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\
  68                --no-summa|--no-summar|--no-summary)
  69                no_summary=t ;;
  70        --no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
  71                no_commit=t ;;
  72        -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
  73                --strateg=*|--strategy=*|\
  74        -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
  75                case "$#,$1" in
  76                *,*=*)
  77                        strategy=`expr "$1" : '-[^=]*=\(.*\)'` ;;
  78                1,*)
  79                        usage ;;
  80                *)
  81                        strategy="$2"
  82                        shift ;;
  83                esac
  84                case " $all_strategies " in
  85                *" $strategy "*)
  86                        use_strategies="$use_strategies$strategy " ;;
  87                *)
  88                        die "available strategies are: $all_strategies" ;;
  89                esac
  90                ;;
  91        -*)     usage ;;
  92        *)      break ;;
  93        esac
  94        shift
  95done
  96
  97merge_msg="$1"
  98shift
  99head_arg="$1"
 100head=$(git-rev-parse --verify "$1"^0) || usage
 101shift
 102
 103# All the rest are remote heads
 104test "$#" = 0 && usage ;# we need at least one remote head.
 105
 106remoteheads=
 107for remote
 108do
 109        remotehead=$(git-rev-parse --verify "$remote"^0) ||
 110            die "$remote - not something we can merge"
 111        remoteheads="${remoteheads}$remotehead "
 112done
 113set x $remoteheads ; shift
 114
 115case "$use_strategies" in
 116'')
 117        case "$#" in
 118        1)
 119                use_strategies="$default_twohead_strategies" ;;
 120        *)
 121                use_strategies="$default_octopus_strategies" ;;
 122        esac
 123        ;;
 124esac
 125
 126for s in $use_strategies
 127do
 128        case " $s " in
 129        *" $no_trivial_merge_strategies "*)
 130                index_merge=f
 131                break
 132                ;;
 133        esac
 134done
 135
 136case "$#" in
 1371)
 138        common=$(git-merge-base --all $head "$@")
 139        ;;
 140*)
 141        common=$(git-show-branch --merge-base $head "$@")
 142        ;;
 143esac
 144echo "$head" >"$GIT_DIR/ORIG_HEAD"
 145
 146case "$index_merge,$#,$common,$no_commit" in
 147f,*)
 148        # We've been told not to try anything clever.  Skip to real merge.
 149        ;;
 150?,*,'',*)
 151        # No common ancestors found. We need a real merge.
 152        ;;
 153?,1,"$1",*)
 154        # If head can reach all the merge then we are up to date.
 155        # but first the most common case of merging one remote.
 156        echo "Already up-to-date."
 157        dropsave
 158        exit 0
 159        ;;
 160?,1,"$head",*)
 161        # Again the most common case of merging one remote.
 162        echo "Updating from $head to $1"
 163        git-update-index --refresh 2>/dev/null
 164        new_head=$(git-rev-parse --verify "$1^0") &&
 165        git-read-tree -u -v -m $head "$new_head" &&
 166        finish "$new_head" "Fast forward"
 167        dropsave
 168        exit 0
 169        ;;
 170?,1,?*"$LF"?*,*)
 171        # We are not doing octopus and not fast forward.  Need a
 172        # real merge.
 173        ;;
 174?,1,*,)
 175        # We are not doing octopus, not fast forward, and have only
 176        # one common.  See if it is really trivial.
 177        git var GIT_COMMITTER_IDENT >/dev/null || exit
 178
 179        echo "Trying really trivial in-index merge..."
 180        git-update-index --refresh 2>/dev/null
 181        if git-read-tree --trivial -m -u -v $common $head "$1" &&
 182           result_tree=$(git-write-tree)
 183        then
 184            echo "Wonderful."
 185            result_commit=$(
 186                echo "$merge_msg" |
 187                git-commit-tree $result_tree -p HEAD -p "$1"
 188            ) || exit
 189            finish "$result_commit" "In-index merge"
 190            dropsave
 191            exit 0
 192        fi
 193        echo "Nope."
 194        ;;
 195*)
 196        # An octopus.  If we can reach all the remote we are up to date.
 197        up_to_date=t
 198        for remote
 199        do
 200                common_one=$(git-merge-base --all $head $remote)
 201                if test "$common_one" != "$remote"
 202                then
 203                        up_to_date=f
 204                        break
 205                fi
 206        done
 207        if test "$up_to_date" = t
 208        then
 209                echo "Already up-to-date. Yeeah!"
 210                dropsave
 211                exit 0
 212        fi
 213        ;;
 214esac
 215
 216# We are going to make a new commit.
 217git var GIT_COMMITTER_IDENT >/dev/null || exit
 218
 219# At this point, we need a real merge.  No matter what strategy
 220# we use, it would operate on the index, possibly affecting the
 221# working tree, and when resolved cleanly, have the desired tree
 222# in the index -- this means that the index must be in sync with
 223# the $head commit.  The strategies are responsible to ensure this.
 224
 225case "$use_strategies" in
 226?*' '?*)
 227    # Stash away the local changes so that we can try more than one.
 228    savestate
 229    single_strategy=no
 230    ;;
 231*)
 232    rm -f "$GIT_DIR/MERGE_SAVE"
 233    single_strategy=yes
 234    ;;
 235esac
 236
 237result_tree= best_cnt=-1 best_strategy= wt_strategy=
 238merge_was_ok=
 239for strategy in $use_strategies
 240do
 241    test "$wt_strategy" = '' || {
 242        echo "Rewinding the tree to pristine..."
 243        restorestate
 244    }
 245    case "$single_strategy" in
 246    no)
 247        echo "Trying merge strategy $strategy..."
 248        ;;
 249    esac
 250
 251    # Remember which strategy left the state in the working tree
 252    wt_strategy=$strategy
 253
 254    git-merge-$strategy $common -- "$head_arg" "$@"
 255    exit=$?
 256    if test "$no_commit" = t && test "$exit" = 0
 257    then
 258        merge_was_ok=t
 259        exit=1 ;# pretend it left conflicts.
 260    fi
 261
 262    test "$exit" = 0 || {
 263
 264        # The backend exits with 1 when conflicts are left to be resolved,
 265        # with 2 when it does not handle the given merge at all.
 266
 267        if test "$exit" -eq 1
 268        then
 269            cnt=`{
 270                git-diff-files --name-only
 271                git-ls-files --unmerged
 272            } | wc -l`
 273            if test $best_cnt -le 0 -o $cnt -le $best_cnt
 274            then
 275                best_strategy=$strategy
 276                best_cnt=$cnt
 277            fi
 278        fi
 279        continue
 280    }
 281
 282    # Automerge succeeded.
 283    result_tree=$(git-write-tree) && break
 284done
 285
 286# If we have a resulting tree, that means the strategy module
 287# auto resolved the merge cleanly.
 288if test '' != "$result_tree"
 289then
 290    parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
 291    result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
 292    finish "$result_commit" "Merge $result_commit, made by $wt_strategy."
 293    dropsave
 294    exit 0
 295fi
 296
 297# Pick the result from the best strategy and have the user fix it up.
 298case "$best_strategy" in
 299'')
 300        restorestate
 301        echo >&2 "No merge strategy handled the merge."
 302        exit 2
 303        ;;
 304"$wt_strategy")
 305        # We already have its result in the working tree.
 306        ;;
 307*)
 308        echo "Rewinding the tree to pristine..."
 309        restorestate
 310        echo "Using the $best_strategy to prepare resolving by hand."
 311        git-merge-$best_strategy $common -- "$head_arg" "$@"
 312        ;;
 313esac
 314for remote
 315do
 316        echo $remote
 317done >"$GIT_DIR/MERGE_HEAD"
 318echo "$merge_msg" >"$GIT_DIR/MERGE_MSG"
 319
 320if test "$merge_was_ok" = t
 321then
 322        echo >&2 \
 323        "Automatic merge went well; stopped before committing as requested"
 324        exit 0
 325else
 326        {
 327            echo '
 328Conflicts:
 329'
 330                git ls-files --unmerged |
 331                sed -e 's/^[^   ]*      /       /' |
 332                uniq
 333        } >>"$GIT_DIR/MERGE_MSG"
 334        if test -d "$GIT_DIR/rr-cache"
 335        then
 336                git-rerere
 337        fi
 338        die "Automatic merge failed; fix conflicts and then commit the result."
 339fi