git-rebase.shon commit rebase: use 'git stash store' to simplify logic (20351bb)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano.
   4#
   5
   6SUBDIRECTORY_OK=Yes
   7OPTIONS_KEEPDASHDASH=
   8OPTIONS_SPEC="\
   9git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]
  10git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]
  11git-rebase --continue | --abort | --skip | --edit-todo
  12--
  13 Available options are
  14v,verbose!         display a diffstat of what changed upstream
  15q,quiet!           be quiet. implies --no-stat
  16autostash!         automatically stash/stash pop before and after
  17onto=!             rebase onto given branch instead of upstream
  18p,preserve-merges! try to recreate merges instead of ignoring them
  19s,strategy=!       use the given merge strategy
  20no-ff!             cherry-pick all commits, even if unchanged
  21m,merge!           use merging strategies to rebase
  22i,interactive!     let the user edit the list of commits to rebase
  23x,exec=!           add exec lines after each commit of the editable list
  24k,keep-empty       preserve empty commits during rebase
  25f,force-rebase!    force rebase even if branch is up to date
  26X,strategy-option=! pass the argument through to the merge strategy
  27stat!              display a diffstat of what changed upstream
  28n,no-stat!         do not show diffstat of what changed upstream
  29verify             allow pre-rebase hook to run
  30rerere-autoupdate  allow rerere to update index with resolved conflicts
  31root!              rebase all reachable commits up to the root(s)
  32autosquash         move commits that begin with squash!/fixup! under -i
  33committer-date-is-author-date! passed to 'git am'
  34ignore-date!       passed to 'git am'
  35whitespace=!       passed to 'git apply'
  36ignore-whitespace! passed to 'git apply'
  37C=!                passed to 'git apply'
  38 Actions:
  39continue!          continue
  40abort!             abort and check out the original branch
  41skip!              skip current patch and continue
  42edit-todo!         edit the todo list during an interactive rebase
  43"
  44. git-sh-setup
  45. git-sh-i18n
  46set_reflog_action rebase
  47require_work_tree_exists
  48cd_to_toplevel
  49
  50LF='
  51'
  52ok_to_skip_pre_rebase=
  53resolvemsg="
  54$(gettext 'When you have resolved this problem, run "git rebase --continue".
  55If you prefer to skip this patch, run "git rebase --skip" instead.
  56To check out the original branch and stop rebasing, run "git rebase --abort".')
  57"
  58unset onto
  59cmd=
  60strategy=
  61strategy_opts=
  62do_merge=
  63merge_dir="$GIT_DIR"/rebase-merge
  64apply_dir="$GIT_DIR"/rebase-apply
  65verbose=
  66diffstat=
  67test "$(git config --bool rebase.stat)" = true && diffstat=t
  68autostash="$(git config --bool rebase.autostash || echo false)"
  69git_am_opt=
  70rebase_root=
  71force_rebase=
  72allow_rerere_autoupdate=
  73# Non-empty if a rebase was in progress when 'git rebase' was invoked
  74in_progress=
  75# One of {am, merge, interactive}
  76type=
  77# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}
  78state_dir=
  79# One of {'', continue, skip, abort}, as parsed from command line
  80action=
  81preserve_merges=
  82autosquash=
  83keep_empty=
  84test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
  85
  86read_basic_state () {
  87        head_name=$(cat "$state_dir"/head-name) &&
  88        onto=$(cat "$state_dir"/onto) &&
  89        # We always write to orig-head, but interactive rebase used to write to
  90        # head. Fall back to reading from head to cover for the case that the
  91        # user upgraded git with an ongoing interactive rebase.
  92        if test -f "$state_dir"/orig-head
  93        then
  94                orig_head=$(cat "$state_dir"/orig-head)
  95        else
  96                orig_head=$(cat "$state_dir"/head)
  97        fi &&
  98        GIT_QUIET=$(cat "$state_dir"/quiet) &&
  99        test -f "$state_dir"/verbose && verbose=t
 100        test -f "$state_dir"/strategy && strategy="$(cat "$state_dir"/strategy)"
 101        test -f "$state_dir"/strategy_opts &&
 102                strategy_opts="$(cat "$state_dir"/strategy_opts)"
 103        test -f "$state_dir"/allow_rerere_autoupdate &&
 104                allow_rerere_autoupdate="$(cat "$state_dir"/allow_rerere_autoupdate)"
 105}
 106
 107write_basic_state () {
 108        echo "$head_name" > "$state_dir"/head-name &&
 109        echo "$onto" > "$state_dir"/onto &&
 110        echo "$orig_head" > "$state_dir"/orig-head &&
 111        echo "$GIT_QUIET" > "$state_dir"/quiet &&
 112        test t = "$verbose" && : > "$state_dir"/verbose
 113        test -n "$strategy" && echo "$strategy" > "$state_dir"/strategy
 114        test -n "$strategy_opts" && echo "$strategy_opts" > \
 115                "$state_dir"/strategy_opts
 116        test -n "$allow_rerere_autoupdate" && echo "$allow_rerere_autoupdate" > \
 117                "$state_dir"/allow_rerere_autoupdate
 118}
 119
 120output () {
 121        case "$verbose" in
 122        '')
 123                output=$("$@" 2>&1 )
 124                status=$?
 125                test $status != 0 && printf "%s\n" "$output"
 126                return $status
 127                ;;
 128        *)
 129                "$@"
 130                ;;
 131        esac
 132}
 133
 134move_to_original_branch () {
 135        case "$head_name" in
 136        refs/*)
 137                message="rebase finished: $head_name onto $onto"
 138                git update-ref -m "$message" \
 139                        $head_name $(git rev-parse HEAD) $orig_head &&
 140                git symbolic-ref \
 141                        -m "rebase finished: returning to $head_name" \
 142                        HEAD $head_name ||
 143                die "$(gettext "Could not move back to $head_name")"
 144                ;;
 145        esac
 146}
 147
 148finish_rebase () {
 149        if test -f "$state_dir/autostash"
 150        then
 151                stash_sha1=$(cat "$state_dir/autostash")
 152                if git stash apply $stash_sha1 2>&1 >/dev/null
 153                then
 154                        echo "$(gettext 'Applied autostash.')"
 155                else
 156                        git stash store -m "autostash" -q $stash_sha1 ||
 157                        die "$(eval_gettext "Cannot store \$stash_sha1")"
 158                        gettext 'Applying autostash resulted in conflicts.
 159Your changes are safe in the stash.
 160You can run "git stash pop" or "git stash drop" it at any time.
 161'
 162                fi
 163        fi
 164        git gc --auto &&
 165        rm -rf "$state_dir"
 166}
 167
 168run_specific_rebase () {
 169        if [ "$interactive_rebase" = implied ]; then
 170                GIT_EDITOR=:
 171                export GIT_EDITOR
 172                autosquash=
 173        fi
 174        . git-rebase--$type
 175        ret=$?
 176        if test $ret -eq 0
 177        then
 178                finish_rebase
 179        fi
 180        exit $ret
 181}
 182
 183run_pre_rebase_hook () {
 184        if test -z "$ok_to_skip_pre_rebase" &&
 185           test -x "$GIT_DIR/hooks/pre-rebase"
 186        then
 187                "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} ||
 188                die "$(gettext "The pre-rebase hook refused to rebase.")"
 189        fi
 190}
 191
 192test -f "$apply_dir"/applying &&
 193        die "$(gettext "It looks like git-am is in progress. Cannot rebase.")"
 194
 195if test -d "$apply_dir"
 196then
 197        type=am
 198        state_dir="$apply_dir"
 199elif test -d "$merge_dir"
 200then
 201        if test -f "$merge_dir"/interactive
 202        then
 203                type=interactive
 204                interactive_rebase=explicit
 205        else
 206                type=merge
 207        fi
 208        state_dir="$merge_dir"
 209fi
 210test -n "$type" && in_progress=t
 211
 212total_argc=$#
 213while test $# != 0
 214do
 215        case "$1" in
 216        --no-verify)
 217                ok_to_skip_pre_rebase=yes
 218                ;;
 219        --verify)
 220                ok_to_skip_pre_rebase=
 221                ;;
 222        --continue|--skip|--abort|--edit-todo)
 223                test $total_argc -eq 2 || usage
 224                action=${1##--}
 225                ;;
 226        --onto)
 227                test 2 -le "$#" || usage
 228                onto="$2"
 229                shift
 230                ;;
 231        -x)
 232                test 2 -le "$#" || usage
 233                cmd="${cmd}exec $2${LF}"
 234                shift
 235                ;;
 236        -i)
 237                interactive_rebase=explicit
 238                ;;
 239        -k)
 240                keep_empty=yes
 241                ;;
 242        -p)
 243                preserve_merges=t
 244                test -z "$interactive_rebase" && interactive_rebase=implied
 245                ;;
 246        --autosquash)
 247                autosquash=t
 248                ;;
 249        --no-autosquash)
 250                autosquash=
 251                ;;
 252        -M|-m)
 253                do_merge=t
 254                ;;
 255        -X)
 256                shift
 257                strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--$1")"
 258                do_merge=t
 259                test -z "$strategy" && strategy=recursive
 260                ;;
 261        -s)
 262                shift
 263                strategy="$1"
 264                do_merge=t
 265                ;;
 266        -n)
 267                diffstat=
 268                ;;
 269        --stat)
 270                diffstat=t
 271                ;;
 272        --autostash)
 273                autostash=true
 274                ;;
 275        -v)
 276                verbose=t
 277                diffstat=t
 278                GIT_QUIET=
 279                ;;
 280        -q)
 281                GIT_QUIET=t
 282                git_am_opt="$git_am_opt -q"
 283                verbose=
 284                diffstat=
 285                ;;
 286        --whitespace)
 287                shift
 288                git_am_opt="$git_am_opt --whitespace=$1"
 289                case "$1" in
 290                fix|strip)
 291                        force_rebase=t
 292                        ;;
 293                esac
 294                ;;
 295        --ignore-whitespace)
 296                git_am_opt="$git_am_opt $1"
 297                ;;
 298        --committer-date-is-author-date|--ignore-date)
 299                git_am_opt="$git_am_opt $1"
 300                force_rebase=t
 301                ;;
 302        -C)
 303                shift
 304                git_am_opt="$git_am_opt -C$1"
 305                ;;
 306        --root)
 307                rebase_root=t
 308                ;;
 309        -f|--no-ff)
 310                force_rebase=t
 311                ;;
 312        --rerere-autoupdate|--no-rerere-autoupdate)
 313                allow_rerere_autoupdate="$1"
 314                ;;
 315        --)
 316                shift
 317                break
 318                ;;
 319        esac
 320        shift
 321done
 322test $# -gt 2 && usage
 323
 324if test -n "$cmd" &&
 325   test "$interactive_rebase" != explicit
 326then
 327        die "$(gettext "The --exec option must be used with the --interactive option")"
 328fi
 329
 330if test -n "$action"
 331then
 332        test -z "$in_progress" && die "$(gettext "No rebase in progress?")"
 333        # Only interactive rebase uses detailed reflog messages
 334        if test "$type" = interactive && test "$GIT_REFLOG_ACTION" = rebase
 335        then
 336                GIT_REFLOG_ACTION="rebase -i ($action)"
 337                export GIT_REFLOG_ACTION
 338        fi
 339fi
 340
 341if test "$action" = "edit-todo" && test "$type" != "interactive"
 342then
 343        die "$(gettext "The --edit-todo action can only be used during interactive rebase.")"
 344fi
 345
 346case "$action" in
 347continue)
 348        # Sanity check
 349        git rev-parse --verify HEAD >/dev/null ||
 350                die "$(gettext "Cannot read HEAD")"
 351        git update-index --ignore-submodules --refresh &&
 352        git diff-files --quiet --ignore-submodules || {
 353                echo "$(gettext "You must edit all merge conflicts and then
 354mark them as resolved using git add")"
 355                exit 1
 356        }
 357        read_basic_state
 358        run_specific_rebase
 359        ;;
 360skip)
 361        output git reset --hard HEAD || exit $?
 362        read_basic_state
 363        run_specific_rebase
 364        ;;
 365abort)
 366        git rerere clear
 367        read_basic_state
 368        case "$head_name" in
 369        refs/*)
 370                git symbolic-ref -m "rebase: aborting" HEAD $head_name ||
 371                die "$(eval_gettext "Could not move back to \$head_name")"
 372                ;;
 373        esac
 374        output git reset --hard $orig_head
 375        finish_rebase
 376        exit
 377        ;;
 378edit-todo)
 379        run_specific_rebase
 380        ;;
 381esac
 382
 383# Make sure no rebase is in progress
 384if test -n "$in_progress"
 385then
 386        state_dir_base=${state_dir##*/}
 387        cmd_live_rebase="git rebase (--continue | --abort | --skip)"
 388        cmd_clear_stale_rebase="rm -fr \"$state_dir\""
 389        die "
 390$(eval_gettext 'It seems that there is already a $state_dir_base directory, and
 391I wonder if you are in the middle of another rebase.  If that is the
 392case, please try
 393        $cmd_live_rebase
 394If that is not the case, please
 395        $cmd_clear_stale_rebase
 396and run me again.  I am stopping in case you still have something
 397valuable there.')"
 398fi
 399
 400if test -n "$rebase_root" && test -z "$onto"
 401then
 402        test -z "$interactive_rebase" && interactive_rebase=implied
 403fi
 404
 405if test -n "$interactive_rebase"
 406then
 407        type=interactive
 408        state_dir="$merge_dir"
 409elif test -n "$do_merge"
 410then
 411        type=merge
 412        state_dir="$merge_dir"
 413else
 414        type=am
 415        state_dir="$apply_dir"
 416fi
 417
 418if test -z "$rebase_root"
 419then
 420        case "$#" in
 421        0)
 422                if ! upstream_name=$(git rev-parse --symbolic-full-name \
 423                        --verify -q @{upstream} 2>/dev/null)
 424                then
 425                        . git-parse-remote
 426                        error_on_missing_default_upstream "rebase" "rebase" \
 427                                "against" "git rebase <branch>"
 428                fi
 429                ;;
 430        *)      upstream_name="$1"
 431                shift
 432                ;;
 433        esac
 434        upstream=`git rev-parse --verify "${upstream_name}^0"` ||
 435        die "$(eval_gettext "invalid upstream \$upstream_name")"
 436        upstream_arg="$upstream_name"
 437else
 438        if test -z "$onto"
 439        then
 440                empty_tree=`git hash-object -t tree /dev/null`
 441                onto=`git commit-tree $empty_tree </dev/null`
 442                squash_onto="$onto"
 443        fi
 444        unset upstream_name
 445        unset upstream
 446        test $# -gt 1 && usage
 447        upstream_arg=--root
 448fi
 449
 450# Make sure the branch to rebase onto is valid.
 451onto_name=${onto-"$upstream_name"}
 452case "$onto_name" in
 453*...*)
 454        if      left=${onto_name%...*} right=${onto_name#*...} &&
 455                onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})
 456        then
 457                case "$onto" in
 458                ?*"$LF"?*)
 459                        die "$(eval_gettext "\$onto_name: there are more than one merge bases")"
 460                        ;;
 461                '')
 462                        die "$(eval_gettext "\$onto_name: there is no merge base")"
 463                        ;;
 464                esac
 465        else
 466                die "$(eval_gettext "\$onto_name: there is no merge base")"
 467        fi
 468        ;;
 469*)
 470        onto=$(git rev-parse --verify "${onto_name}^0") ||
 471        die "$(eval_gettext "Does not point to a valid commit: \$onto_name")"
 472        ;;
 473esac
 474
 475# If the branch to rebase is given, that is the branch we will rebase
 476# $branch_name -- branch being rebased, or HEAD (already detached)
 477# $orig_head -- commit object name of tip of the branch before rebasing
 478# $head_name -- refs/heads/<that-branch> or "detached HEAD"
 479switch_to=
 480case "$#" in
 4811)
 482        # Is it "rebase other $branchname" or "rebase other $commit"?
 483        branch_name="$1"
 484        switch_to="$1"
 485
 486        if git show-ref --verify --quiet -- "refs/heads/$1" &&
 487           orig_head=$(git rev-parse -q --verify "refs/heads/$1")
 488        then
 489                head_name="refs/heads/$1"
 490        elif orig_head=$(git rev-parse -q --verify "$1")
 491        then
 492                head_name="detached HEAD"
 493        else
 494                die "$(eval_gettext "fatal: no such branch: \$branch_name")"
 495        fi
 496        ;;
 4970)
 498        # Do not need to switch branches, we are already on it.
 499        if branch_name=`git symbolic-ref -q HEAD`
 500        then
 501                head_name=$branch_name
 502                branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
 503        else
 504                head_name="detached HEAD"
 505                branch_name=HEAD ;# detached
 506        fi
 507        orig_head=$(git rev-parse --verify HEAD) || exit
 508        ;;
 509*)
 510        die "BUG: unexpected number of arguments left to parse"
 511        ;;
 512esac
 513
 514if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
 515then
 516        stash_sha1=$(git stash create "autostash") ||
 517        die "$(gettext 'Cannot autostash')"
 518
 519        mkdir -p "$state_dir" &&
 520        echo $stash_sha1 >"$state_dir/autostash" &&
 521        stash_abbrev=$(git rev-parse --short $stash_sha1) &&
 522        echo "$(eval_gettext 'Created autostash: $stash_abbrev')" &&
 523        git reset --hard
 524fi
 525
 526require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")"
 527
 528# Now we are rebasing commits $upstream..$orig_head (or with --root,
 529# everything leading up to $orig_head) on top of $onto
 530
 531# Check if we are already based on $onto with linear history,
 532# but this should be done only when upstream and onto are the same
 533# and if this is not an interactive rebase.
 534mb=$(git merge-base "$onto" "$orig_head")
 535if test "$type" != interactive && test "$upstream" = "$onto" &&
 536        test "$mb" = "$onto" &&
 537        # linear history?
 538        ! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
 539then
 540        if test -z "$force_rebase"
 541        then
 542                # Lazily switch to the target branch if needed...
 543                test -z "$switch_to" || git checkout "$switch_to" --
 544                say "$(eval_gettext "Current branch \$branch_name is up to date.")"
 545                exit 0
 546        else
 547                say "$(eval_gettext "Current branch \$branch_name is up to date, rebase forced.")"
 548        fi
 549fi
 550
 551# If a hook exists, give it a chance to interrupt
 552run_pre_rebase_hook "$upstream_arg" "$@"
 553
 554if test -n "$diffstat"
 555then
 556        if test -n "$verbose"
 557        then
 558                echo "$(eval_gettext "Changes from \$mb to \$onto:")"
 559        fi
 560        # We want color (if set), but no pager
 561        GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
 562fi
 563
 564test "$type" = interactive && run_specific_rebase
 565
 566# Detach HEAD and reset the tree
 567say "$(gettext "First, rewinding head to replay your work on top of it...")"
 568git checkout -q "$onto^0" || die "could not detach HEAD"
 569git update-ref ORIG_HEAD $orig_head
 570
 571# If the $onto is a proper descendant of the tip of the branch, then
 572# we just fast-forwarded.
 573if test "$mb" = "$orig_head"
 574then
 575        say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
 576        move_to_original_branch
 577        exit 0
 578fi
 579
 580if test -n "$rebase_root"
 581then
 582        revisions="$onto..$orig_head"
 583else
 584        revisions="$upstream..$orig_head"
 585fi
 586
 587run_specific_rebase