8b0d7b0ac1769beea14ebeea1e0d58216f3baadf
   1#!/bin/sh
   2#
   3# Copyright (c) 2006 Johannes E. Schindelin
   4
   5# SHORT DESCRIPTION
   6#
   7# This script makes it easy to fix up commits in the middle of a series,
   8# and rearrange commits.
   9#
  10# The original idea comes from Eric W. Biederman, in
  11# http://article.gmane.org/gmane.comp.version-control.git/22407
  12
  13OPTIONS_KEEPDASHDASH=
  14OPTIONS_SPEC="\
  15git-rebase [-i] [options] [--] <upstream> [<branch>]
  16git-rebase [-i] (--continue | --abort | --skip)
  17--
  18 Available options are
  19v,verbose          display a diffstat of what changed upstream
  20onto=              rebase onto given branch instead of upstream
  21p,preserve-merges  try to recreate merges instead of ignoring them
  22s,strategy=        use the given merge strategy
  23no-ff              cherry-pick all commits, even if unchanged
  24m,merge            always used (no-op)
  25i,interactive      always used (no-op)
  26 Actions:
  27continue           continue rebasing process
  28abort              abort rebasing process and restore original branch
  29skip               skip current patch and continue rebasing process
  30no-verify          override pre-rebase hook from stopping the operation
  31verify             allow pre-rebase hook to run
  32root               rebase all reachable commmits up to the root(s)
  33autosquash         move commits that begin with squash!/fixup! under -i
  34"
  35
  36. git-sh-setup
  37require_work_tree
  38
  39dotest="$GIT_DIR/rebase-merge"
  40
  41# The file containing rebase commands, comments, and empty lines.
  42# This file is created by "git rebase -i" then edited by the user.  As
  43# the lines are processed, they are removed from the front of this
  44# file and written to the tail of $done.
  45todo="$dotest"/git-rebase-todo
  46
  47# The rebase command lines that have already been processed.  A line
  48# is moved here when it is first handled, before any associated user
  49# actions.
  50done="$dotest"/done
  51
  52# The commit message that is planned to be used for any changes that
  53# need to be committed following a user interaction.
  54msg="$dotest"/message
  55
  56# The file into which is accumulated the suggested commit message for
  57# squash/fixup commands.  When the first of a series of squash/fixups
  58# is seen, the file is created and the commit message from the
  59# previous commit and from the first squash/fixup commit are written
  60# to it.  The commit message for each subsequent squash/fixup commit
  61# is appended to the file as it is processed.
  62#
  63# The first line of the file is of the form
  64#     # This is a combination of $count commits.
  65# where $count is the number of commits whose messages have been
  66# written to the file so far (including the initial "pick" commit).
  67# Each time that a commit message is processed, this line is read and
  68# updated.  It is deleted just before the combined commit is made.
  69squash_msg="$dotest"/message-squash
  70
  71# If the current series of squash/fixups has not yet included a squash
  72# command, then this file exists and holds the commit message of the
  73# original "pick" commit.  (If the series ends without a "squash"
  74# command, then this can be used as the commit message of the combined
  75# commit without opening the editor.)
  76fixup_msg="$dotest"/message-fixup
  77
  78# $rewritten is the name of a directory containing files for each
  79# commit that is reachable by at least one merge base of $head and
  80# $upstream. They are not necessarily rewritten, but their children
  81# might be.  This ensures that commits on merged, but otherwise
  82# unrelated side branches are left alone. (Think "X" in the man page's
  83# example.)
  84rewritten="$dotest"/rewritten
  85
  86dropped="$dotest"/dropped
  87
  88# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
  89# GIT_AUTHOR_DATE that will be used for the commit that is currently
  90# being rebased.
  91author_script="$dotest"/author-script
  92
  93# When an "edit" rebase command is being processed, the SHA1 of the
  94# commit to be edited is recorded in this file.  When "git rebase
  95# --continue" is executed, if there are any staged changes then they
  96# will be amended to the HEAD commit, but only provided the HEAD
  97# commit is still the commit to be edited.  When any other rebase
  98# command is processed, this file is deleted.
  99amend="$dotest"/amend
 100
 101# For the post-rewrite hook, we make a list of rewritten commits and
 102# their new sha1s.  The rewritten-pending list keeps the sha1s of
 103# commits that have been processed, but not committed yet,
 104# e.g. because they are waiting for a 'squash' command.
 105rewritten_list="$dotest"/rewritten-list
 106rewritten_pending="$dotest"/rewritten-pending
 107
 108preserve_merges=
 109strategy=
 110onto=
 111verbose=
 112ok_to_skip_pre_rebase=
 113rebase_root=
 114autosquash=
 115test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
 116force_rebase=
 117
 118GIT_CHERRY_PICK_HELP="\
 119hint: after resolving the conflicts, mark the corrected paths
 120hint: with 'git add <paths>' and run 'git rebase --continue'"
 121export GIT_CHERRY_PICK_HELP
 122
 123warn () {
 124        printf '%s\n' "$*" >&2
 125}
 126
 127output () {
 128        case "$verbose" in
 129        '')
 130                output=$("$@" 2>&1 )
 131                status=$?
 132                test $status != 0 && printf "%s\n" "$output"
 133                return $status
 134                ;;
 135        *)
 136                "$@"
 137                ;;
 138        esac
 139}
 140
 141# Output the commit message for the specified commit.
 142commit_message () {
 143        git cat-file commit "$1" | sed "1,/^$/d"
 144}
 145
 146run_pre_rebase_hook () {
 147        if test -z "$ok_to_skip_pre_rebase" &&
 148           test -x "$GIT_DIR/hooks/pre-rebase"
 149        then
 150                "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
 151                        echo >&2 "The pre-rebase hook refused to rebase."
 152                        exit 1
 153                }
 154        fi
 155}
 156
 157
 158orig_reflog_action="$GIT_REFLOG_ACTION"
 159
 160comment_for_reflog () {
 161        case "$orig_reflog_action" in
 162        ''|rebase*)
 163                GIT_REFLOG_ACTION="rebase -i ($1)"
 164                export GIT_REFLOG_ACTION
 165                ;;
 166        esac
 167}
 168
 169last_count=
 170mark_action_done () {
 171        sed -e 1q < "$todo" >> "$done"
 172        sed -e 1d < "$todo" >> "$todo".new
 173        mv -f "$todo".new "$todo"
 174        new_count=$(sane_grep -c '^[^#]' < "$done")
 175        total=$(($new_count+$(sane_grep -c '^[^#]' < "$todo")))
 176        if test "$last_count" != "$new_count"
 177        then
 178                last_count=$new_count
 179                printf "Rebasing (%d/%d)\r" $new_count $total
 180                test -z "$verbose" || echo
 181        fi
 182}
 183
 184make_patch () {
 185        sha1_and_parents="$(git rev-list --parents -1 "$1")"
 186        case "$sha1_and_parents" in
 187        ?*' '?*' '?*)
 188                git diff --cc $sha1_and_parents
 189                ;;
 190        ?*' '?*)
 191                git diff-tree -p "$1^!"
 192                ;;
 193        *)
 194                echo "Root commit"
 195                ;;
 196        esac > "$dotest"/patch
 197        test -f "$msg" ||
 198                commit_message "$1" > "$msg"
 199        test -f "$author_script" ||
 200                get_author_ident_from_commit "$1" > "$author_script"
 201}
 202
 203die_with_patch () {
 204        echo "$1" > "$dotest"/stopped-sha
 205        make_patch "$1"
 206        git rerere
 207        die "$2"
 208}
 209
 210die_abort () {
 211        rm -rf "$dotest"
 212        die "$1"
 213}
 214
 215has_action () {
 216        sane_grep '^[^#]' "$1" >/dev/null
 217}
 218
 219# Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
 220# GIT_AUTHOR_DATE exported from the current environment.
 221do_with_author () {
 222        (
 223                export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
 224                "$@"
 225        )
 226}
 227
 228pick_one () {
 229        ff=--ff
 230        case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac
 231        case "$force_rebase" in '') ;; ?*) ff= ;; esac
 232        output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
 233        test -d "$rewritten" &&
 234                pick_one_preserving_merges "$@" && return
 235        if test -n "$rebase_root"
 236        then
 237                output git cherry-pick "$@"
 238                return
 239        fi
 240        output git cherry-pick $ff "$@"
 241}
 242
 243pick_one_preserving_merges () {
 244        fast_forward=t
 245        case "$1" in
 246        -n)
 247                fast_forward=f
 248                sha1=$2
 249                ;;
 250        *)
 251                sha1=$1
 252                ;;
 253        esac
 254        sha1=$(git rev-parse $sha1)
 255
 256        if test -f "$dotest"/current-commit
 257        then
 258                if test "$fast_forward" = t
 259                then
 260                        while read current_commit
 261                        do
 262                                git rev-parse HEAD > "$rewritten"/$current_commit
 263                        done <"$dotest"/current-commit
 264                        rm "$dotest"/current-commit ||
 265                        die "Cannot write current commit's replacement sha1"
 266                fi
 267        fi
 268
 269        echo $sha1 >> "$dotest"/current-commit
 270
 271        # rewrite parents; if none were rewritten, we can fast-forward.
 272        new_parents=
 273        pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)"
 274        if test "$pend" = " "
 275        then
 276                pend=" root"
 277        fi
 278        while [ "$pend" != "" ]
 279        do
 280                p=$(expr "$pend" : ' \([^ ]*\)')
 281                pend="${pend# $p}"
 282
 283                if test -f "$rewritten"/$p
 284                then
 285                        new_p=$(cat "$rewritten"/$p)
 286
 287                        # If the todo reordered commits, and our parent is marked for
 288                        # rewriting, but hasn't been gotten to yet, assume the user meant to
 289                        # drop it on top of the current HEAD
 290                        if test -z "$new_p"
 291                        then
 292                                new_p=$(git rev-parse HEAD)
 293                        fi
 294
 295                        test $p != $new_p && fast_forward=f
 296                        case "$new_parents" in
 297                        *$new_p*)
 298                                ;; # do nothing; that parent is already there
 299                        *)
 300                                new_parents="$new_parents $new_p"
 301                                ;;
 302                        esac
 303                else
 304                        if test -f "$dropped"/$p
 305                        then
 306                                fast_forward=f
 307                                replacement="$(cat "$dropped"/$p)"
 308                                test -z "$replacement" && replacement=root
 309                                pend=" $replacement$pend"
 310                        else
 311                                new_parents="$new_parents $p"
 312                        fi
 313                fi
 314        done
 315        case $fast_forward in
 316        t)
 317                output warn "Fast-forward to $sha1"
 318                output git reset --hard $sha1 ||
 319                        die "Cannot fast-forward to $sha1"
 320                ;;
 321        f)
 322                first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
 323
 324                if [ "$1" != "-n" ]
 325                then
 326                        # detach HEAD to current parent
 327                        output git checkout $first_parent 2> /dev/null ||
 328                                die "Cannot move HEAD to $first_parent"
 329                fi
 330
 331                case "$new_parents" in
 332                ' '*' '*)
 333                        test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
 334
 335                        # redo merge
 336                        author_script_content=$(get_author_ident_from_commit $sha1)
 337                        eval "$author_script_content"
 338                        msg_content="$(commit_message $sha1)"
 339                        # No point in merging the first parent, that's HEAD
 340                        new_parents=${new_parents# $first_parent}
 341                        if ! do_with_author output \
 342                                git merge ${strategy:+-s $strategy} -m \
 343                                        "$msg_content" $new_parents
 344                        then
 345                                printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG
 346                                die_with_patch $sha1 "Error redoing merge $sha1"
 347                        fi
 348                        echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
 349                        ;;
 350                *)
 351                        output git cherry-pick "$@" ||
 352                                die_with_patch $sha1 "Could not pick $sha1"
 353                        ;;
 354                esac
 355                ;;
 356        esac
 357}
 358
 359nth_string () {
 360        case "$1" in
 361        *1[0-9]|*[04-9]) echo "$1"th;;
 362        *1) echo "$1"st;;
 363        *2) echo "$1"nd;;
 364        *3) echo "$1"rd;;
 365        esac
 366}
 367
 368update_squash_messages () {
 369        if test -f "$squash_msg"; then
 370                mv "$squash_msg" "$squash_msg".bak || exit
 371                count=$(($(sed -n \
 372                        -e "1s/^# This is a combination of \(.*\) commits\./\1/p" \
 373                        -e "q" < "$squash_msg".bak)+1))
 374                {
 375                        echo "# This is a combination of $count commits."
 376                        sed -e 1d -e '2,/^./{
 377                                /^$/d
 378                        }' <"$squash_msg".bak
 379                } >"$squash_msg"
 380        else
 381                commit_message HEAD > "$fixup_msg" || die "Cannot write $fixup_msg"
 382                count=2
 383                {
 384                        echo "# This is a combination of 2 commits."
 385                        echo "# The first commit's message is:"
 386                        echo
 387                        cat "$fixup_msg"
 388                } >"$squash_msg"
 389        fi
 390        case $1 in
 391        squash)
 392                rm -f "$fixup_msg"
 393                echo
 394                echo "# This is the $(nth_string $count) commit message:"
 395                echo
 396                commit_message $2
 397                ;;
 398        fixup)
 399                echo
 400                echo "# The $(nth_string $count) commit message will be skipped:"
 401                echo
 402                commit_message $2 | sed -e 's/^/#       /'
 403                ;;
 404        esac >>"$squash_msg"
 405}
 406
 407peek_next_command () {
 408        sed -n -e "/^#/d" -e '/^$/d' -e "s/ .*//p" -e "q" < "$todo"
 409}
 410
 411# A squash/fixup has failed.  Prepare the long version of the squash
 412# commit message, then die_with_patch.  This code path requires the
 413# user to edit the combined commit message for all commits that have
 414# been squashed/fixedup so far.  So also erase the old squash
 415# messages, effectively causing the combined commit to be used as the
 416# new basis for any further squash/fixups.  Args: sha1 rest
 417die_failed_squash() {
 418        mv "$squash_msg" "$msg" || exit
 419        rm -f "$fixup_msg"
 420        cp "$msg" "$GIT_DIR"/MERGE_MSG || exit
 421        warn
 422        warn "Could not apply $1... $2"
 423        die_with_patch $1 ""
 424}
 425
 426flush_rewritten_pending() {
 427        test -s "$rewritten_pending" || return
 428        newsha1="$(git rev-parse HEAD^0)"
 429        sed "s/$/ $newsha1/" < "$rewritten_pending" >> "$rewritten_list"
 430        rm -f "$rewritten_pending"
 431}
 432
 433record_in_rewritten() {
 434        oldsha1="$(git rev-parse $1)"
 435        echo "$oldsha1" >> "$rewritten_pending"
 436
 437        case "$(peek_next_command)" in
 438        squash|s|fixup|f)
 439                ;;
 440        *)
 441                flush_rewritten_pending
 442                ;;
 443        esac
 444}
 445
 446do_next () {
 447        rm -f "$msg" "$author_script" "$amend" || exit
 448        read -r command sha1 rest < "$todo"
 449        case "$command" in
 450        '#'*|''|noop)
 451                mark_action_done
 452                ;;
 453        pick|p)
 454                comment_for_reflog pick
 455
 456                mark_action_done
 457                pick_one $sha1 ||
 458                        die_with_patch $sha1 "Could not apply $sha1... $rest"
 459                record_in_rewritten $sha1
 460                ;;
 461        reword|r)
 462                comment_for_reflog reword
 463
 464                mark_action_done
 465                pick_one $sha1 ||
 466                        die_with_patch $sha1 "Could not apply $sha1... $rest"
 467                git commit --amend --no-post-rewrite
 468                record_in_rewritten $sha1
 469                ;;
 470        edit|e)
 471                comment_for_reflog edit
 472
 473                mark_action_done
 474                pick_one $sha1 ||
 475                        die_with_patch $sha1 "Could not apply $sha1... $rest"
 476                echo "$sha1" > "$dotest"/stopped-sha
 477                make_patch $sha1
 478                git rev-parse --verify HEAD > "$amend"
 479                warn "Stopped at $sha1... $rest"
 480                warn "You can amend the commit now, with"
 481                warn
 482                warn "  git commit --amend"
 483                warn
 484                warn "Once you are satisfied with your changes, run"
 485                warn
 486                warn "  git rebase --continue"
 487                warn
 488                exit 0
 489                ;;
 490        squash|s|fixup|f)
 491                case "$command" in
 492                squash|s)
 493                        squash_style=squash
 494                        ;;
 495                fixup|f)
 496                        squash_style=fixup
 497                        ;;
 498                esac
 499                comment_for_reflog $squash_style
 500
 501                test -f "$done" && has_action "$done" ||
 502                        die "Cannot '$squash_style' without a previous commit"
 503
 504                mark_action_done
 505                update_squash_messages $squash_style $sha1
 506                author_script_content=$(get_author_ident_from_commit HEAD)
 507                echo "$author_script_content" > "$author_script"
 508                eval "$author_script_content"
 509                output git reset --soft HEAD^
 510                pick_one -n $sha1 || die_failed_squash $sha1 "$rest"
 511                case "$(peek_next_command)" in
 512                squash|s|fixup|f)
 513                        # This is an intermediate commit; its message will only be
 514                        # used in case of trouble.  So use the long version:
 515                        do_with_author output git commit --no-verify -F "$squash_msg" ||
 516                                die_failed_squash $sha1 "$rest"
 517                        ;;
 518                *)
 519                        # This is the final command of this squash/fixup group
 520                        if test -f "$fixup_msg"
 521                        then
 522                                do_with_author git commit --no-verify -F "$fixup_msg" ||
 523                                        die_failed_squash $sha1 "$rest"
 524                        else
 525                                cp "$squash_msg" "$GIT_DIR"/SQUASH_MSG || exit
 526                                rm -f "$GIT_DIR"/MERGE_MSG
 527                                do_with_author git commit --no-verify -e ||
 528                                        die_failed_squash $sha1 "$rest"
 529                        fi
 530                        rm -f "$squash_msg" "$fixup_msg"
 531                        ;;
 532                esac
 533                record_in_rewritten $sha1
 534                ;;
 535        x|"exec")
 536                read -r command rest < "$todo"
 537                mark_action_done
 538                printf 'Executing: %s\n' "$rest"
 539                # "exec" command doesn't take a sha1 in the todo-list.
 540                # => can't just use $sha1 here.
 541                git rev-parse --verify HEAD > "$dotest"/stopped-sha
 542                ${SHELL:-@SHELL_PATH@} -c "$rest" # Actual execution
 543                status=$?
 544                if test "$status" -ne 0
 545                then
 546                        warn "Execution failed: $rest"
 547                        warn "You can fix the problem, and then run"
 548                        warn
 549                        warn "  git rebase --continue"
 550                        warn
 551                        exit "$status"
 552                fi
 553                # Run in subshell because require_clean_work_tree can die.
 554                if ! (require_clean_work_tree "rebase")
 555                then
 556                        warn "Commit or stash your changes, and then run"
 557                        warn
 558                        warn "  git rebase --continue"
 559                        warn
 560                        exit 1
 561                fi
 562                ;;
 563        *)
 564                warn "Unknown command: $command $sha1 $rest"
 565                if git rev-parse --verify -q "$sha1" >/dev/null
 566                then
 567                        die_with_patch $sha1 "Please fix this in the file $todo."
 568                else
 569                        die "Please fix this in the file $todo."
 570                fi
 571                ;;
 572        esac
 573        test -s "$todo" && return
 574
 575        comment_for_reflog finish &&
 576        headname=$(cat "$dotest"/head-name) &&
 577        oldhead=$(cat "$dotest"/head) &&
 578        shortonto=$(git rev-parse --short $(cat "$dotest"/onto)) &&
 579        newhead=$(git rev-parse HEAD) &&
 580        case $headname in
 581        refs/*)
 582                message="$GIT_REFLOG_ACTION: $headname onto $shortonto" &&
 583                git update-ref -m "$message" $headname $newhead $oldhead &&
 584                git symbolic-ref HEAD $headname
 585                ;;
 586        esac && {
 587                test ! -f "$dotest"/verbose ||
 588                        git diff-tree --stat $(cat "$dotest"/head)..HEAD
 589        } &&
 590        {
 591                test -s "$rewritten_list" &&
 592                git notes copy --for-rewrite=rebase < "$rewritten_list" ||
 593                true # we don't care if this copying failed
 594        } &&
 595        if test -x "$GIT_DIR"/hooks/post-rewrite &&
 596                test -s "$rewritten_list"; then
 597                "$GIT_DIR"/hooks/post-rewrite rebase < "$rewritten_list"
 598                true # we don't care if this hook failed
 599        fi &&
 600        rm -rf "$dotest" &&
 601        git gc --auto &&
 602        warn "Successfully rebased and updated $headname."
 603
 604        exit
 605}
 606
 607do_rest () {
 608        while :
 609        do
 610                do_next
 611        done
 612}
 613
 614# skip picking commits whose parents are unchanged
 615skip_unnecessary_picks () {
 616        fd=3
 617        while read -r command rest
 618        do
 619                # fd=3 means we skip the command
 620                case "$fd,$command" in
 621                3,pick|3,p)
 622                        # pick a commit whose parent is current $onto -> skip
 623                        sha1=${rest%% *}
 624                        case "$(git rev-parse --verify --quiet "$sha1"^)" in
 625                        "$onto"*)
 626                                onto=$sha1
 627                                ;;
 628                        *)
 629                                fd=1
 630                                ;;
 631                        esac
 632                        ;;
 633                3,#*|3,)
 634                        # copy comments
 635                        ;;
 636                *)
 637                        fd=1
 638                        ;;
 639                esac
 640                printf '%s\n' "$command${rest:+ }$rest" >&$fd
 641        done <"$todo" >"$todo.new" 3>>"$done" &&
 642        mv -f "$todo".new "$todo" &&
 643        case "$(peek_next_command)" in
 644        squash|s|fixup|f)
 645                record_in_rewritten "$onto"
 646                ;;
 647        esac ||
 648        die "Could not skip unnecessary pick commands"
 649}
 650
 651# check if no other options are set
 652is_standalone () {
 653        test $# -eq 2 -a "$2" = '--' &&
 654        test -z "$onto" &&
 655        test -z "$preserve_merges" &&
 656        test -z "$strategy" &&
 657        test -z "$verbose"
 658}
 659
 660get_saved_options () {
 661        test -d "$rewritten" && preserve_merges=t
 662        test -f "$dotest"/strategy && strategy="$(cat "$dotest"/strategy)"
 663        test -f "$dotest"/verbose && verbose=t
 664        test -f "$dotest"/rebase-root && rebase_root=t
 665}
 666
 667# Rearrange the todo list that has both "pick sha1 msg" and
 668# "pick sha1 fixup!/squash! msg" appears in it so that the latter
 669# comes immediately after the former, and change "pick" to
 670# "fixup"/"squash".
 671rearrange_squash () {
 672        # extract fixup!/squash! lines and resolve any referenced sha1's
 673        while read -r pick sha1 message
 674        do
 675                case "$message" in
 676                "squash! "*|"fixup! "*)
 677                        action="${message%%!*}"
 678                        rest="${message#*! }"
 679                        echo "$sha1 $action $rest"
 680                        # if it's a single word, try to resolve to a full sha1 and
 681                        # emit a second copy. This allows us to match on both message
 682                        # and on sha1 prefix
 683                        if test "${rest#* }" = "$rest"; then
 684                                fullsha="$(git rev-parse -q --verify "$rest" 2>/dev/null)"
 685                                if test -n "$fullsha"; then
 686                                        # prefix the action to uniquely identify this line as
 687                                        # intended for full sha1 match
 688                                        echo "$sha1 +$action $fullsha"
 689                                fi
 690                        fi
 691                esac
 692        done >"$1.sq" <"$1"
 693        test -s "$1.sq" || return
 694
 695        used=
 696        while read -r pick sha1 message
 697        do
 698                case " $used" in
 699                *" $sha1 "*) continue ;;
 700                esac
 701                printf '%s\n' "$pick $sha1 $message"
 702                used="$used$sha1 "
 703                while read -r squash action msg_content
 704                do
 705                        case " $used" in
 706                        *" $squash "*) continue ;;
 707                        esac
 708                        emit=0
 709                        case "$action" in
 710                        +*)
 711                                action="${action#+}"
 712                                # full sha1 prefix test
 713                                case "$msg_content" in "$sha1"*) emit=1;; esac ;;
 714                        *)
 715                                # message prefix test
 716                                case "$message" in "$msg_content"*) emit=1;; esac ;;
 717                        esac
 718                        if test $emit = 1; then
 719                                printf '%s\n' "$action $squash $action! $msg_content"
 720                                used="$used$squash "
 721                        fi
 722                done <"$1.sq"
 723        done >"$1.rearranged" <"$1"
 724        cat "$1.rearranged" >"$1"
 725        rm -f "$1.sq" "$1.rearranged"
 726}
 727
 728LF='
 729'
 730parse_onto () {
 731        case "$1" in
 732        *...*)
 733                if      left=${1%...*} right=${1#*...} &&
 734                        onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})
 735                then
 736                        case "$onto" in
 737                        ?*"$LF"?* | '')
 738                                exit 1 ;;
 739                        esac
 740                        echo "$onto"
 741                        exit 0
 742                fi
 743        esac
 744        git rev-parse --verify "$1^0"
 745}
 746
 747while test $# != 0
 748do
 749        case "$1" in
 750        --no-verify)
 751                ok_to_skip_pre_rebase=yes
 752                ;;
 753        --verify)
 754                ok_to_skip_pre_rebase=
 755                ;;
 756        --continue)
 757                is_standalone "$@" || usage
 758                get_saved_options
 759                comment_for_reflog continue
 760
 761                test -d "$dotest" || die "No interactive rebase running"
 762
 763                # Sanity check
 764                git rev-parse --verify HEAD >/dev/null ||
 765                        die "Cannot read HEAD"
 766                git update-index --ignore-submodules --refresh &&
 767                        git diff-files --quiet --ignore-submodules ||
 768                        die "Working tree is dirty"
 769
 770                # do we have anything to commit?
 771                if git diff-index --cached --quiet --ignore-submodules HEAD --
 772                then
 773                        : Nothing to commit -- skip this
 774                else
 775                        . "$author_script" ||
 776                                die "Cannot find the author identity"
 777                        current_head=
 778                        if test -f "$amend"
 779                        then
 780                                current_head=$(git rev-parse --verify HEAD)
 781                                test "$current_head" = $(cat "$amend") ||
 782                                die "\
 783You have uncommitted changes in your working tree. Please, commit them
 784first and then run 'git rebase --continue' again."
 785                                git reset --soft HEAD^ ||
 786                                die "Cannot rewind the HEAD"
 787                        fi
 788                        do_with_author git commit --no-verify -F "$msg" -e || {
 789                                test -n "$current_head" && git reset --soft $current_head
 790                                die "Could not commit staged changes."
 791                        }
 792                fi
 793
 794                record_in_rewritten "$(cat "$dotest"/stopped-sha)"
 795
 796                require_clean_work_tree "rebase"
 797                do_rest
 798                ;;
 799        --abort)
 800                is_standalone "$@" || usage
 801                get_saved_options
 802                comment_for_reflog abort
 803
 804                git rerere clear
 805                test -d "$dotest" || die "No interactive rebase running"
 806
 807                headname=$(cat "$dotest"/head-name)
 808                head=$(cat "$dotest"/head)
 809                case $headname in
 810                refs/*)
 811                        git symbolic-ref HEAD $headname
 812                        ;;
 813                esac &&
 814                output git reset --hard $head &&
 815                rm -rf "$dotest"
 816                exit
 817                ;;
 818        --skip)
 819                is_standalone "$@" || usage
 820                get_saved_options
 821                comment_for_reflog skip
 822
 823                git rerere clear
 824                test -d "$dotest" || die "No interactive rebase running"
 825
 826                output git reset --hard && do_rest
 827                ;;
 828        -s)
 829                case "$#,$1" in
 830                *,*=*)
 831                        strategy=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
 832                1,*)
 833                        usage ;;
 834                *)
 835                        strategy="$2"
 836                        shift ;;
 837                esac
 838                ;;
 839        -m)
 840                # we use merge anyway
 841                ;;
 842        -v)
 843                verbose=t
 844                ;;
 845        -p)
 846                preserve_merges=t
 847                ;;
 848        -i)
 849                # yeah, we know
 850                ;;
 851        --no-ff)
 852                force_rebase=t
 853                ;;
 854        --root)
 855                rebase_root=t
 856                ;;
 857        --autosquash)
 858                autosquash=t
 859                ;;
 860        --no-autosquash)
 861                autosquash=
 862                ;;
 863        --onto)
 864                test 2 -le "$#" || usage
 865                onto="$2"
 866                shift
 867                ;;
 868        --)
 869                shift
 870                break
 871                ;;
 872        esac
 873        shift
 874done
 875
 876if test -n "$onto"
 877then
 878        onto=$(parse_onto "$onto") || die "Does not point to a valid commit: $1"
 879fi
 880
 881test -z "$rebase_root" -a $# -ge 1 -a $# -le 2 ||
 882test ! -z "$rebase_root" -a $# -le 1 || usage
 883test -d "$dotest" &&
 884        die "Interactive rebase already started"
 885
 886git var GIT_COMMITTER_IDENT >/dev/null ||
 887        die "You need to set your committer info first"
 888
 889if test -z "$rebase_root"
 890then
 891        upstream_arg="$1"
 892        upstream=$(git rev-parse --verify "$1") || die "Invalid base"
 893        test -z "$onto" && onto=$upstream
 894        shift
 895else
 896        upstream=
 897        upstream_arg=--root
 898        test -z "$onto" &&
 899                die "You must specify --onto when using --root"
 900fi
 901run_pre_rebase_hook "$upstream_arg" "$@"
 902
 903comment_for_reflog start
 904
 905require_clean_work_tree "rebase" "Please commit or stash them."
 906
 907if test ! -z "$1"
 908then
 909        output git checkout "$1" -- ||
 910                die "Could not checkout $1"
 911fi
 912
 913head=$(git rev-parse --verify HEAD) || die "No HEAD?"
 914mkdir "$dotest" || die "Could not create temporary $dotest"
 915
 916: > "$dotest"/interactive || die "Could not mark as interactive"
 917git symbolic-ref HEAD > "$dotest"/head-name 2> /dev/null ||
 918        echo "detached HEAD" > "$dotest"/head-name
 919
 920echo $head > "$dotest"/head
 921case "$rebase_root" in
 922'')
 923        rm -f "$dotest"/rebase-root ;;
 924*)
 925        : >"$dotest"/rebase-root ;;
 926esac
 927echo $onto > "$dotest"/onto
 928test -z "$strategy" || echo "$strategy" > "$dotest"/strategy
 929test t = "$verbose" && : > "$dotest"/verbose
 930if test t = "$preserve_merges"
 931then
 932        if test -z "$rebase_root"
 933        then
 934                mkdir "$rewritten" &&
 935                for c in $(git merge-base --all $head $upstream)
 936                do
 937                        echo $onto > "$rewritten"/$c ||
 938                                die "Could not init rewritten commits"
 939                done
 940        else
 941                mkdir "$rewritten" &&
 942                echo $onto > "$rewritten"/root ||
 943                        die "Could not init rewritten commits"
 944        fi
 945        # No cherry-pick because our first pass is to determine
 946        # parents to rewrite and skipping dropped commits would
 947        # prematurely end our probe
 948        merges_option=
 949        first_after_upstream="$(git rev-list --reverse --first-parent $upstream..$head | head -n 1)"
 950else
 951        merges_option="--no-merges --cherry-pick"
 952fi
 953
 954shorthead=$(git rev-parse --short $head)
 955shortonto=$(git rev-parse --short $onto)
 956if test -z "$rebase_root"
 957        # this is now equivalent to ! -z "$upstream"
 958then
 959        shortupstream=$(git rev-parse --short $upstream)
 960        revisions=$upstream...$head
 961        shortrevisions=$shortupstream..$shorthead
 962else
 963        revisions=$onto...$head
 964        shortrevisions=$shorthead
 965fi
 966git rev-list $merges_option --pretty=oneline --abbrev-commit \
 967        --abbrev=7 --reverse --left-right --topo-order \
 968        $revisions | \
 969        sed -n "s/^>//p" |
 970while read -r shortsha1 rest
 971do
 972        if test t != "$preserve_merges"
 973        then
 974                printf '%s\n' "pick $shortsha1 $rest" >> "$todo"
 975        else
 976                sha1=$(git rev-parse $shortsha1)
 977                if test -z "$rebase_root"
 978                then
 979                        preserve=t
 980                        for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
 981                        do
 982                                if test -f "$rewritten"/$p -a \( $p != $onto -o $sha1 = $first_after_upstream \)
 983                                then
 984                                        preserve=f
 985                                fi
 986                        done
 987                else
 988                        preserve=f
 989                fi
 990                if test f = "$preserve"
 991                then
 992                        touch "$rewritten"/$sha1
 993                        printf '%s\n' "pick $shortsha1 $rest" >> "$todo"
 994                fi
 995        fi
 996done
 997
 998# Watch for commits that been dropped by --cherry-pick
 999if test t = "$preserve_merges"
1000then
1001        mkdir "$dropped"
1002        # Save all non-cherry-picked changes
1003        git rev-list $revisions --left-right --cherry-pick | \
1004                sed -n "s/^>//p" > "$dotest"/not-cherry-picks
1005        # Now all commits and note which ones are missing in
1006        # not-cherry-picks and hence being dropped
1007        git rev-list $revisions |
1008        while read rev
1009        do
1010                if test -f "$rewritten"/$rev -a "$(sane_grep "$rev" "$dotest"/not-cherry-picks)" = ""
1011                then
1012                        # Use -f2 because if rev-list is telling us this commit is
1013                        # not worthwhile, we don't want to track its multiple heads,
1014                        # just the history of its first-parent for others that will
1015                        # be rebasing on top of it
1016                        git rev-list --parents -1 $rev | cut -d' ' -s -f2 > "$dropped"/$rev
1017                        short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)
1018                        sane_grep -v "^[a-z][a-z]* $short" <"$todo" > "${todo}2" ; mv "${todo}2" "$todo"
1019                        rm "$rewritten"/$rev
1020                fi
1021        done
1022fi
1023
1024test -s "$todo" || echo noop >> "$todo"
1025test -n "$autosquash" && rearrange_squash "$todo"
1026cat >> "$todo" << EOF
1027
1028# Rebase $shortrevisions onto $shortonto
1029#
1030# Commands:
1031#  p, pick = use commit
1032#  r, reword = use commit, but edit the commit message
1033#  e, edit = use commit, but stop for amending
1034#  s, squash = use commit, but meld into previous commit
1035#  f, fixup = like "squash", but discard this commit's log message
1036#  x, exec = run command (the rest of the line) using shell
1037#
1038# If you remove a line here THAT COMMIT WILL BE LOST.
1039# However, if you remove everything, the rebase will be aborted.
1040#
1041EOF
1042
1043has_action "$todo" ||
1044        die_abort "Nothing to do"
1045
1046cp "$todo" "$todo".backup
1047git_editor "$todo" ||
1048        die_abort "Could not execute editor"
1049
1050has_action "$todo" ||
1051        die_abort "Nothing to do"
1052
1053test -d "$rewritten" || test -n "$force_rebase" || skip_unnecessary_picks
1054
1055output git checkout $onto || die_abort "could not detach HEAD"
1056git update-ref ORIG_HEAD $head
1057do_rest