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