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