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