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