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