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