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