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