git-merge.shon commit Improve merge performance by avoiding in-index merges. (c82d711)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5
   6USAGE='[-n] [--no-commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'
   7
   8. git-sh-setup
   9set_reflog_action "merge $*"
  10
  11test -z "$(git ls-files -u)" ||
  12        die "You are in a middle of conflicted merge."
  13
  14LF='
  15'
  16
  17all_strategies='recur recursive octopus resolve stupid ours'
  18default_twohead_strategies='recursive'
  19default_octopus_strategies='octopus'
  20no_trivial_merge_strategies='ours'
  21use_strategies=
  22
  23index_merge=t
  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 >/dev/null
  40                cpio -iuv <"$GIT_DIR/MERGE_SAVE"
  41                git-update-index --refresh >/dev/null
  42        fi
  43}
  44
  45finish_up_to_date () {
  46        case "$squash" in
  47        t)
  48                echo "$1 (nothing to squash)" ;;
  49        '')
  50                echo "$1" ;;
  51        esac
  52        dropsave
  53}
  54
  55squash_message () {
  56        echo Squashed commit of the following:
  57        echo
  58        git-log --no-merges ^"$head" $remote
  59}
  60
  61finish () {
  62        if test '' = "$2"
  63        then
  64                rlogm="$GIT_REFLOG_ACTION"
  65        else
  66                echo "$2"
  67                rlogm="$GIT_REFLOG_ACTION: $2"
  68        fi
  69        case "$squash" in
  70        t)
  71                echo "Squash commit -- not updating HEAD"
  72                squash_message >"$GIT_DIR/SQUASH_MSG"
  73                ;;
  74        '')
  75                case "$merge_msg" in
  76                '')
  77                        echo "No merge message -- not updating HEAD"
  78                        ;;
  79                *)
  80                        git-update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
  81                        ;;
  82                esac
  83                ;;
  84        esac
  85        case "$1" in
  86        '')
  87                ;;
  88        ?*)
  89                case "$no_summary" in
  90                '')
  91                        git-diff-tree --stat --summary -M "$head" "$1"
  92                        ;;
  93                esac
  94                ;;
  95        esac
  96}
  97
  98merge_name () {
  99        remote="$1"
 100        rh=$(git-rev-parse --verify "$remote^0" 2>/dev/null) || return
 101        bh=$(git-show-ref -s --verify "refs/heads/$remote" 2>/dev/null)
 102        if test "$rh" = "$bh"
 103        then
 104                echo "$rh               branch '$remote' of ."
 105        elif truname=$(expr "$remote" : '\(.*\)~[1-9][0-9]*$') &&
 106                git-show-ref -q --verify "refs/heads/$truname" 2>/dev/null
 107        then
 108                echo "$rh               branch '$truname' (early part) of ."
 109        else
 110                echo "$rh               commit '$remote'"
 111        fi
 112}
 113
 114case "$#" in 0) usage ;; esac
 115
 116have_message=
 117while case "$#" in 0) break ;; esac
 118do
 119        case "$1" in
 120        -n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\
 121                --no-summa|--no-summar|--no-summary)
 122                no_summary=t ;;
 123        --sq|--squ|--squa|--squas|--squash)
 124                squash=t no_commit=t ;;
 125        --no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
 126                no_commit=t ;;
 127        -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
 128                --strateg=*|--strategy=*|\
 129        -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
 130                case "$#,$1" in
 131                *,*=*)
 132                        strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
 133                1,*)
 134                        usage ;;
 135                *)
 136                        strategy="$2"
 137                        shift ;;
 138                esac
 139                case " $all_strategies " in
 140                *" $strategy "*)
 141                        use_strategies="$use_strategies$strategy " ;;
 142                *)
 143                        die "available strategies are: $all_strategies" ;;
 144                esac
 145                ;;
 146        -m=*|--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
 147                merge_msg=`expr "z$1" : 'z-[^=]*=\(.*\)'`
 148                have_message=t
 149                ;;
 150        -m|--m|--me|--mes|--mess|--messa|--messag|--message)
 151                shift
 152                case "$#" in
 153                1)      usage ;;
 154                esac
 155                merge_msg="$1"
 156                have_message=t
 157                ;;
 158        -*)     usage ;;
 159        *)      break ;;
 160        esac
 161        shift
 162done
 163
 164# This could be traditional "merge <msg> HEAD <commit>..."  and the
 165# way we can tell it is to see if the second token is HEAD, but some
 166# people might have misused the interface and used a committish that
 167# is the same as HEAD there instead.  Traditional format never would
 168# have "-m" so it is an additional safety measure to check for it.
 169
 170if test -z "$have_message" &&
 171        second_token=$(git-rev-parse --verify "$2^0" 2>/dev/null) &&
 172        head_commit=$(git-rev-parse --verify "HEAD" 2>/dev/null) &&
 173        test "$second_token" = "$head_commit"
 174then
 175        merge_msg="$1"
 176        shift
 177        head_arg="$1"
 178        shift
 179elif ! git-rev-parse --verify HEAD >/dev/null 2>&1
 180then
 181        # If the merged head is a valid one there is no reason to
 182        # forbid "git merge" into a branch yet to be born.  We do
 183        # the same for "git pull".
 184        if test 1 -ne $#
 185        then
 186                echo >&2 "Can merge only exactly one commit into empty head"
 187                exit 1
 188        fi
 189
 190        rh=$(git rev-parse --verify "$1^0") ||
 191                die "$1 - not something we can merge"
 192
 193        git-update-ref -m "initial pull" HEAD "$rh" "" &&
 194        git-read-tree --reset -u HEAD
 195        exit
 196
 197else
 198        # We are invoked directly as the first-class UI.
 199        head_arg=HEAD
 200
 201        # All the rest are the commits being merged; prepare
 202        # the standard merge summary message to be appended to
 203        # the given message.  If remote is invalid we will die
 204        # later in the common codepath so we discard the error
 205        # in this loop.
 206        merge_name=$(for remote
 207                do
 208                        merge_name "$remote"
 209                done | git-fmt-merge-msg
 210        )
 211        merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"
 212fi
 213head=$(git-rev-parse --verify "$head_arg"^0) || usage
 214
 215# All the rest are remote heads
 216test "$#" = 0 && usage ;# we need at least one remote head.
 217
 218remoteheads=
 219for remote
 220do
 221        remotehead=$(git-rev-parse --verify "$remote"^0 2>/dev/null) ||
 222            die "$remote - not something we can merge"
 223        remoteheads="${remoteheads}$remotehead "
 224        eval GITHEAD_$remotehead='"$remote"'
 225        export GITHEAD_$remotehead
 226done
 227set x $remoteheads ; shift
 228
 229case "$use_strategies" in
 230'')
 231        case "$#" in
 232        1)
 233                var="`git-repo-config --get pull.twohead`"
 234                if test -n "$var"
 235                then
 236                        use_strategies="$var"
 237                else
 238                        use_strategies="$default_twohead_strategies"
 239                fi ;;
 240        *)
 241                var="`git-repo-config --get pull.octopus`"
 242                if test -n "$var"
 243                then
 244                        use_strategies="$var"
 245                else
 246                        use_strategies="$default_octopus_strategies"
 247                fi ;;
 248        esac
 249        ;;
 250esac
 251
 252for s in $use_strategies
 253do
 254        case " $s " in
 255        *" $no_trivial_merge_strategies "*)
 256                index_merge=f
 257                break
 258                ;;
 259        esac
 260done
 261
 262case "$#" in
 2631)
 264        common=$(git-merge-base --all $head "$@")
 265        ;;
 266*)
 267        common=$(git-show-branch --merge-base $head "$@")
 268        ;;
 269esac
 270echo "$head" >"$GIT_DIR/ORIG_HEAD"
 271
 272case "$index_merge,$#,$common,$no_commit" in
 273f,*)
 274        # We've been told not to try anything clever.  Skip to real merge.
 275        ;;
 276?,*,'',*)
 277        # No common ancestors found. We need a real merge.
 278        ;;
 279?,1,"$1",*)
 280        # If head can reach all the merge then we are up to date.
 281        # but first the most common case of merging one remote.
 282        finish_up_to_date "Already up-to-date."
 283        exit 0
 284        ;;
 285?,1,"$head",*)
 286        # Again the most common case of merging one remote.
 287        echo "Updating $(git-rev-parse --short $head)..$(git-rev-parse --short $1)"
 288        git-update-index --refresh 2>/dev/null
 289        new_head=$(git-rev-parse --verify "$1^0") &&
 290        git-read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
 291        finish "$new_head" "Fast forward"
 292        dropsave
 293        exit 0
 294        ;;
 295?,1,?*"$LF"?*,*)
 296        # We are not doing octopus and not fast forward.  Need a
 297        # real merge.
 298        ;;
 299?,1,*,)
 300        # We are not doing octopus, not fast forward, and have only
 301        # one common.
 302        git-update-index --refresh 2>/dev/null
 303        case " $use_strategies " in
 304        *' recursive '*|*' recur '*)
 305                : run merge later
 306                ;;
 307        *)
 308                # See if it is really trivial.
 309                git var GIT_COMMITTER_IDENT >/dev/null || exit
 310                echo "Trying really trivial in-index merge..."
 311                if git-read-tree --trivial -m -u -v $common $head "$1" &&
 312                   result_tree=$(git-write-tree)
 313                then
 314                        echo "Wonderful."
 315                        result_commit=$(
 316                                echo "$merge_msg" |
 317                                git-commit-tree $result_tree -p HEAD -p "$1"
 318                        ) || exit
 319                        finish "$result_commit" "In-index merge"
 320                        dropsave
 321                        exit 0
 322                fi
 323                echo "Nope."
 324        esac
 325        ;;
 326*)
 327        # An octopus.  If we can reach all the remote we are up to date.
 328        up_to_date=t
 329        for remote
 330        do
 331                common_one=$(git-merge-base --all $head $remote)
 332                if test "$common_one" != "$remote"
 333                then
 334                        up_to_date=f
 335                        break
 336                fi
 337        done
 338        if test "$up_to_date" = t
 339        then
 340                finish_up_to_date "Already up-to-date. Yeeah!"
 341                exit 0
 342        fi
 343        ;;
 344esac
 345
 346# We are going to make a new commit.
 347git var GIT_COMMITTER_IDENT >/dev/null || exit
 348
 349# At this point, we need a real merge.  No matter what strategy
 350# we use, it would operate on the index, possibly affecting the
 351# working tree, and when resolved cleanly, have the desired tree
 352# in the index -- this means that the index must be in sync with
 353# the $head commit.  The strategies are responsible to ensure this.
 354
 355case "$use_strategies" in
 356?*' '?*)
 357    # Stash away the local changes so that we can try more than one.
 358    savestate
 359    single_strategy=no
 360    ;;
 361*)
 362    rm -f "$GIT_DIR/MERGE_SAVE"
 363    single_strategy=yes
 364    ;;
 365esac
 366
 367result_tree= best_cnt=-1 best_strategy= wt_strategy=
 368merge_was_ok=
 369for strategy in $use_strategies
 370do
 371    test "$wt_strategy" = '' || {
 372        echo "Rewinding the tree to pristine..."
 373        restorestate
 374    }
 375    case "$single_strategy" in
 376    no)
 377        echo "Trying merge strategy $strategy..."
 378        ;;
 379    esac
 380
 381    # Remember which strategy left the state in the working tree
 382    wt_strategy=$strategy
 383
 384    git-merge-$strategy $common -- "$head_arg" "$@"
 385    exit=$?
 386    if test "$no_commit" = t && test "$exit" = 0
 387    then
 388        merge_was_ok=t
 389        exit=1 ;# pretend it left conflicts.
 390    fi
 391
 392    test "$exit" = 0 || {
 393
 394        # The backend exits with 1 when conflicts are left to be resolved,
 395        # with 2 when it does not handle the given merge at all.
 396
 397        if test "$exit" -eq 1
 398        then
 399            cnt=`{
 400                git-diff-files --name-only
 401                git-ls-files --unmerged
 402            } | wc -l`
 403            if test $best_cnt -le 0 -o $cnt -le $best_cnt
 404            then
 405                best_strategy=$strategy
 406                best_cnt=$cnt
 407            fi
 408        fi
 409        continue
 410    }
 411
 412    # Automerge succeeded.
 413    result_tree=$(git-write-tree) && break
 414done
 415
 416# If we have a resulting tree, that means the strategy module
 417# auto resolved the merge cleanly.
 418if test '' != "$result_tree"
 419then
 420    parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
 421    result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
 422    finish "$result_commit" "Merge made by $wt_strategy."
 423    dropsave
 424    exit 0
 425fi
 426
 427# Pick the result from the best strategy and have the user fix it up.
 428case "$best_strategy" in
 429'')
 430        restorestate
 431        case "$use_strategies" in
 432        ?*' '?*)
 433                echo >&2 "No merge strategy handled the merge."
 434                ;;
 435        *)
 436                echo >&2 "Merge with strategy $use_strategies failed."
 437                ;;
 438        esac
 439        exit 2
 440        ;;
 441"$wt_strategy")
 442        # We already have its result in the working tree.
 443        ;;
 444*)
 445        echo "Rewinding the tree to pristine..."
 446        restorestate
 447        echo "Using the $best_strategy to prepare resolving by hand."
 448        git-merge-$best_strategy $common -- "$head_arg" "$@"
 449        ;;
 450esac
 451
 452if test "$squash" = t
 453then
 454        finish
 455else
 456        for remote
 457        do
 458                echo $remote
 459        done >"$GIT_DIR/MERGE_HEAD"
 460        echo "$merge_msg" >"$GIT_DIR/MERGE_MSG"
 461fi
 462
 463if test "$merge_was_ok" = t
 464then
 465        echo >&2 \
 466        "Automatic merge went well; stopped before committing as requested"
 467        exit 0
 468else
 469        {
 470            echo '
 471Conflicts:
 472'
 473                git ls-files --unmerged |
 474                sed -e 's/^[^   ]*      /       /' |
 475                uniq
 476        } >>"$GIT_DIR/MERGE_MSG"
 477        if test -d "$GIT_DIR/rr-cache"
 478        then
 479                git-rerere
 480        fi
 481        die "Automatic merge failed; fix conflicts and then commit the result."
 482fi