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