git-rebase.shon commit Merge branch 'gl/cleanup' into gl/cleanup-next (2ad6ba3)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano.
   4#
   5
   6USAGE='[--onto <newbase>] <upstream> [<branch>]'
   7LONG_USAGE='git-rebase replaces <branch> with a new branch of the
   8same name.  When the --onto option is provided the new branch starts
   9out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
  10It then attempts to create a new commit for each commit from the original
  11<branch> that does not exist in the <upstream> branch.
  12
  13It is possible that a merge failure will prevent this process from being
  14completely automatic.  You will have to resolve any such merge failure
  15and run git rebase --continue.  Another option is to bypass the commit
  16that caused the merge failure with git rebase --skip.  To restore the
  17original <branch> and remove the .dotest working files, use the command
  18git rebase --abort instead.
  19
  20Note that if <branch> is not specified on the command line, the
  21currently checked out branch is used.  You must be in the top
  22directory of your project to start (or continue) a rebase.
  23
  24Example:       git-rebase master~1 topic
  25
  26        A---B---C topic                   A'\''--B'\''--C'\'' topic
  27       /                   -->           /
  28  D---E---F---G master          D---E---F---G master
  29'
  30. git-sh-setup
  31
  32RESOLVEMSG="
  33When you have resolved this problem run \"git rebase --continue\".
  34If you would prefer to skip this patch, instead run \"git rebase --skip\".
  35To restore the original branch and stop rebasing run \"git rebase --abort\".
  36"
  37unset newbase
  38case "${GIT_USE_RECUR_FOR_RECURSIVE}" in
  39'')
  40        strategy=recursive ;;
  41?*)
  42        strategy=recur ;;
  43esac
  44
  45do_merge=
  46dotest=$GIT_DIR/.dotest-merge
  47prec=4
  48
  49continue_merge () {
  50        test -n "$prev_head" || die "prev_head must be defined"
  51        test -d "$dotest" || die "$dotest directory does not exist"
  52
  53        unmerged=$(git-ls-files -u)
  54        if test -n "$unmerged"
  55        then
  56                echo "You still have unmerged paths in your index"
  57                echo "did you forget update-index?"
  58                die "$RESOLVEMSG"
  59        fi
  60
  61        if test -n "`git-diff-index HEAD`"
  62        then
  63                if ! git-commit -C "`cat $dotest/current`"
  64                then
  65                        echo "Commit failed, please do not call \"git commit\""
  66                        echo "directly, but instead do one of the following: "
  67                        die "$RESOLVEMSG"
  68                fi
  69                printf "Committed: %0${prec}d" $msgnum
  70        else
  71                printf "Already applied: %0${prec}d" $msgnum
  72        fi
  73        echo ' '`git-rev-list --pretty=oneline -1 HEAD | \
  74                                sed 's/^[a-f0-9]\+ //'`
  75
  76        prev_head=`git-rev-parse HEAD^0`
  77        # save the resulting commit so we can read-tree on it later
  78        echo "$prev_head" > "$dotest/prev_head"
  79
  80        # onto the next patch:
  81        msgnum=$(($msgnum + 1))
  82        echo "$msgnum" >"$dotest/msgnum"
  83}
  84
  85call_merge () {
  86        cmt="$(cat $dotest/cmt.$1)"
  87        echo "$cmt" > "$dotest/current"
  88        git-merge-$strategy "$cmt^" -- HEAD "$cmt"
  89        rv=$?
  90        case "$rv" in
  91        0)
  92                return
  93                ;;
  94        1)
  95                test -d "$GIT_DIR/rr-cache" && git-rerere
  96                die "$RESOLVEMSG"
  97                ;;
  98        2)
  99                echo "Strategy: $rv $strategy failed, try another" 1>&2
 100                die "$RESOLVEMSG"
 101                ;;
 102        *)
 103                die "Unknown exit code ($rv) from command:" \
 104                        "git-merge-$strategy $cmt^ -- HEAD $cmt"
 105                ;;
 106        esac
 107}
 108
 109finish_rb_merge () {
 110        rm -r "$dotest"
 111        echo "All done."
 112}
 113
 114while case "$#" in 0) break ;; esac
 115do
 116        case "$1" in
 117        --continue)
 118                diff=$(git-diff-files)
 119                case "$diff" in
 120                ?*)     echo "You must edit all merge conflicts and then"
 121                        echo "mark them as resolved using git update-index"
 122                        exit 1
 123                        ;;
 124                esac
 125                if test -d "$dotest"
 126                then
 127                        prev_head="`cat $dotest/prev_head`"
 128                        end="`cat $dotest/end`"
 129                        msgnum="`cat $dotest/msgnum`"
 130                        onto="`cat $dotest/onto`"
 131                        continue_merge
 132                        while test "$msgnum" -le "$end"
 133                        do
 134                                call_merge "$msgnum"
 135                                continue_merge
 136                        done
 137                        finish_rb_merge
 138                        exit
 139                fi
 140                git am --resolved --3way --resolvemsg="$RESOLVEMSG" \
 141                        --reflog-action=rebase
 142                exit
 143                ;;
 144        --skip)
 145                if test -d "$dotest"
 146                then
 147                        prev_head="`cat $dotest/prev_head`"
 148                        end="`cat $dotest/end`"
 149                        msgnum="`cat $dotest/msgnum`"
 150                        msgnum=$(($msgnum + 1))
 151                        onto="`cat $dotest/onto`"
 152                        while test "$msgnum" -le "$end"
 153                        do
 154                                call_merge "$msgnum"
 155                                continue_merge
 156                        done
 157                        finish_rb_merge
 158                        exit
 159                fi
 160                git am -3 --skip --resolvemsg="$RESOLVEMSG" \
 161                        --reflog-action=rebase
 162                exit
 163                ;;
 164        --abort)
 165                if test -d "$dotest"
 166                then
 167                        rm -r "$dotest"
 168                elif test -d .dotest
 169                then
 170                        rm -r .dotest
 171                else
 172                        die "No rebase in progress?"
 173                fi
 174                git reset --hard ORIG_HEAD
 175                exit
 176                ;;
 177        --onto)
 178                test 2 -le "$#" || usage
 179                newbase="$2"
 180                shift
 181                ;;
 182        -M|-m|--m|--me|--mer|--merg|--merge)
 183                do_merge=t
 184                ;;
 185        -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
 186                --strateg=*|--strategy=*|\
 187        -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
 188                case "$#,$1" in
 189                *,*=*)
 190                        strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
 191                1,*)
 192                        usage ;;
 193                *)
 194                        strategy="$2"
 195                        shift ;;
 196                esac
 197                do_merge=t
 198                ;;
 199        -*)
 200                usage
 201                ;;
 202        *)
 203                break
 204                ;;
 205        esac
 206        shift
 207done
 208
 209case "$strategy,${GIT_USE_RECUR_FOR_RECURSIVE}" in
 210recursive,?*)
 211        strategy=recur ;;
 212esac
 213
 214# Make sure we do not have .dotest
 215if test -z "$do_merge"
 216then
 217        if mkdir .dotest
 218        then
 219                rmdir .dotest
 220        else
 221                echo >&2 '
 222It seems that I cannot create a .dotest directory, and I wonder if you
 223are in the middle of patch application or another rebase.  If that is not
 224the case, please rm -fr .dotest and run me again.  I am stopping in case
 225you still have something valuable there.'
 226                exit 1
 227        fi
 228else
 229        if test -d "$dotest"
 230        then
 231                die "previous dotest directory $dotest still exists." \
 232                        'try git-rebase < --continue | --abort >'
 233        fi
 234fi
 235
 236# The tree must be really really clean.
 237git-update-index --refresh || exit
 238diff=$(git-diff-index --cached --name-status -r HEAD)
 239case "$diff" in
 240?*)     echo "$diff"
 241        exit 1
 242        ;;
 243esac
 244
 245# The upstream head must be given.  Make sure it is valid.
 246upstream_name="$1"
 247upstream=`git rev-parse --verify "${upstream_name}^0"` ||
 248    die "invalid upstream $upstream_name"
 249
 250# If a hook exists, give it a chance to interrupt
 251if test -x "$GIT_DIR/hooks/pre-rebase"
 252then
 253        "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
 254                echo >&2 "The pre-rebase hook refused to rebase."
 255                exit 1
 256        }
 257fi
 258
 259# If the branch to rebase is given, first switch to it.
 260case "$#" in
 2612)
 262        branch_name="$2"
 263        git-checkout "$2" || usage
 264        ;;
 265*)
 266        branch_name=`git symbolic-ref HEAD` || die "No current branch"
 267        branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
 268        ;;
 269esac
 270branch=$(git-rev-parse --verify "${branch_name}^0") || exit
 271
 272# Make sure the branch to rebase onto is valid.
 273onto_name=${newbase-"$upstream_name"}
 274onto=$(git-rev-parse --verify "${onto_name}^0") || exit
 275
 276# Now we are rebasing commits $upstream..$branch on top of $onto
 277
 278# Check if we are already based on $onto, but this should be
 279# done only when upstream and onto are the same.
 280mb=$(git-merge-base "$onto" "$branch")
 281if test "$upstream" = "$onto" && test "$mb" = "$onto"
 282then
 283        echo >&2 "Current branch $branch_name is up to date."
 284        exit 0
 285fi
 286
 287# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
 288git-reset --hard "$onto"
 289
 290# If the $onto is a proper descendant of the tip of the branch, then
 291# we just fast forwarded.
 292if test "$mb" = "$branch"
 293then
 294        echo >&2 "Fast-forwarded $branch_name to $onto_name."
 295        exit 0
 296fi
 297
 298if test -z "$do_merge"
 299then
 300        git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD |
 301        git am --binary -3 -k --resolvemsg="$RESOLVEMSG" \
 302                --reflog-action=rebase
 303        exit $?
 304fi
 305
 306if test "@@NO_PYTHON@@" && test "$strategy" = "recursive"
 307then
 308        die 'The recursive merge strategy currently relies on Python,
 309which this installation of git was not configured with.  Please consider
 310a different merge strategy (e.g. octopus, resolve, stupid, ours)
 311or install Python and git with Python support.'
 312
 313fi
 314
 315# start doing a rebase with git-merge
 316# this is rename-aware if the recursive (default) strategy is used
 317
 318mkdir -p "$dotest"
 319echo "$onto" > "$dotest/onto"
 320prev_head=`git-rev-parse HEAD^0`
 321echo "$prev_head" > "$dotest/prev_head"
 322
 323msgnum=0
 324for cmt in `git-rev-list --no-merges "$upstream"..ORIG_HEAD \
 325                        | @@PERL@@ -e 'print reverse <>'`
 326do
 327        msgnum=$(($msgnum + 1))
 328        echo "$cmt" > "$dotest/cmt.$msgnum"
 329done
 330
 331echo 1 >"$dotest/msgnum"
 332echo $msgnum >"$dotest/end"
 333
 334end=$msgnum
 335msgnum=1
 336
 337while test "$msgnum" -le "$end"
 338do
 339        call_merge "$msgnum"
 340        continue_merge
 341done
 342
 343finish_rb_merge