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