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