1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano. 4# 5 6USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--no-ff] [--onto <newbase>] (<upstream>|--root) [<branch>] [--quiet | -q]' 7LONG_USAGE='git-rebase replaces <branch> with a new branch of the 8same name. When the --onto option is provided the new branch starts 9out with a HEAD equal to <newbase>, otherwise it is equal to <upstream> 10It then attempts to create a new commit for each commit from the original 11<branch> that does not exist in the <upstream> branch. 12 13It is possible that a merge failure will prevent this process from being 14completely automatic. You will have to resolve any such merge failure 15and run git rebase --continue. Another option is to bypass the commit 16that caused the merge failure with git rebase --skip. To restore the 17original <branch> and remove the .git/rebase-apply working files, use the 18command git rebase --abort instead. 19 20Note that if <branch> is not specified on the command line, the 21currently checked out branch is used. 22 23Example: git-rebase master~1 topic 24 25 A---B---C topic A'\''--B'\''--C'\'' topic 26 / --> / 27 D---E---F---G master D---E---F---G master 28' 29 30SUBDIRECTORY_OK=Yes 31OPTIONS_SPEC= 32. git-sh-setup 33set_reflog_action rebase 34require_work_tree 35cd_to_toplevel 36 37LF=' 38' 39OK_TO_SKIP_PRE_REBASE= 40RESOLVEMSG=" 41When you have resolved this problem run\"git rebase --continue\". 42If you would prefer to skip this patch, instead run\"git rebase --skip\". 43To restore the original branch and stop rebasing run\"git rebase --abort\". 44" 45unset newbase 46strategy=recursive 47strategy_opts= 48do_merge= 49dotest="$GIT_DIR"/rebase-merge 50prec=4 51verbose= 52diffstat= 53test"$(git config --bool rebase.stat)"= true && diffstat=t 54git_am_opt= 55rebase_root= 56force_rebase= 57allow_rerere_autoupdate= 58 59continue_merge () { 60test -n"$prev_head"|| die "prev_head must be defined" 61test -d"$dotest"|| die "$dotestdirectory does not exist" 62 63 unmerged=$(git ls-files -u) 64iftest -n"$unmerged" 65then 66echo"You still have unmerged paths in your index" 67echo"did you forget to use git add?" 68 die "$RESOLVEMSG" 69fi 70 71 cmt=`cat "$dotest/current"` 72if! git diff-index --quiet --ignore-submodules HEAD -- 73then 74if! git commit --no-verify -C"$cmt" 75then 76echo"Commit failed, please do not call\"git commit\"" 77echo"directly, but instead do one of the following: " 78 die "$RESOLVEMSG" 79fi 80iftest -z"$GIT_QUIET" 81then 82printf"Committed: %0${prec}d "$msgnum 83fi 84echo"$cmt$(git rev-parse HEAD^0)">>"$dotest/rewritten" 85else 86iftest -z"$GIT_QUIET" 87then 88printf"Already applied: %0${prec}d "$msgnum 89fi 90fi 91test -z"$GIT_QUIET"&& 92 GIT_PAGER='' git log --format=%s -1"$cmt" 93 94 prev_head=`git rev-parse HEAD^0` 95# save the resulting commit so we can read-tree on it later 96echo"$prev_head">"$dotest/prev_head" 97 98# onto the next patch: 99 msgnum=$(($msgnum + 1)) 100echo"$msgnum">"$dotest/msgnum" 101} 102 103call_merge () { 104 cmt="$(cat "$dotest/cmt.$1")" 105echo"$cmt">"$dotest/current" 106 hd=$(git rev-parse --verify HEAD) 107 cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD) 108 msgnum=$(cat "$dotest/msgnum") 109 end=$(cat "$dotest/end") 110eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"' 111eval GITHEAD_$hd='$(cat "$dotest/onto_name")' 112export GITHEAD_$cmt GITHEAD_$hd 113iftest -n"$GIT_QUIET" 114then 115 GIT_MERGE_VERBOSITY=1&&export GIT_MERGE_VERBOSITY 116fi 117eval'git-merge-$strategy'$strategy_opts'"$cmt^" -- "$hd" "$cmt"' 118 rv=$? 119case"$rv"in 1200) 121unset GITHEAD_$cmt GITHEAD_$hd 122return 123;; 1241) 125 git rerere $allow_rerere_autoupdate 126 die "$RESOLVEMSG" 127;; 1282) 129echo"Strategy:$rv$strategyfailed, try another"1>&2 130 die "$RESOLVEMSG" 131;; 132*) 133 die "Unknown exit code ($rv) from command:" \ 134"git-merge-$strategy$cmt^ -- HEAD$cmt" 135;; 136esac 137} 138 139move_to_original_branch () { 140test -z"$head_name"&& 141 head_name="$(cat "$dotest"/head-name)"&& 142 onto="$(cat "$dotest"/onto)"&& 143 orig_head="$(cat "$dotest"/orig-head)" 144case"$head_name"in 145 refs/*) 146 message="rebase finished:$head_nameonto$onto" 147 git update-ref -m"$message" \ 148$head_name $(git rev-parse HEAD) $orig_head&& 149 git symbolic-ref HEAD $head_name|| 150 die "Could not move back to$head_name" 151;; 152esac 153} 154 155finish_rb_merge () { 156 move_to_original_branch 157 git notes copy --for-rewrite=rebase <"$dotest"/rewritten 158iftest -x"$GIT_DIR"/hooks/post-rewrite&& 159test -s"$dotest"/rewritten;then 160"$GIT_DIR"/hooks/post-rewrite rebase <"$dotest"/rewritten 161fi 162rm-r"$dotest" 163 say All done. 164} 165 166is_interactive () { 167whiletest$#!=0 168do 169case"$1"in 170-i|--interactive) 171 interactive_rebase=explicit 172break 173;; 174-p|--preserve-merges) 175 interactive_rebase=implied 176;; 177esac 178shift 179done 180 181if["$interactive_rebase"= implied ];then 182 GIT_EDITOR=: 183export GIT_EDITOR 184fi 185 186test -n"$interactive_rebase"||test -f"$dotest"/interactive 187} 188 189run_pre_rebase_hook () { 190iftest -z"$OK_TO_SKIP_PRE_REBASE"&& 191test -x"$GIT_DIR/hooks/pre-rebase" 192then 193"$GIT_DIR/hooks/pre-rebase"${1+"$@"}|| 194 die "The pre-rebase hook refused to rebase." 195fi 196} 197 198test -f"$GIT_DIR"/rebase-apply/applying && 199 die 'It looks like git-am is in progress. Cannot rebase.' 200 201is_interactive "$@"&&exec git-rebase--interactive"$@" 202 203whiletest$#!=0 204do 205case"$1"in 206--no-verify) 207 OK_TO_SKIP_PRE_REBASE=yes 208;; 209--continue) 210test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 211 die "No rebase in progress?" 212 213 git update-index --ignore-submodules --refresh&& 214 git diff-files --quiet --ignore-submodules|| { 215echo"You must edit all merge conflicts and then" 216echo"mark them as resolved using git add" 217exit1 218} 219iftest -d"$dotest" 220then 221 prev_head=$(cat "$dotest/prev_head") 222 end=$(cat "$dotest/end") 223 msgnum=$(cat "$dotest/msgnum") 224 onto=$(cat "$dotest/onto") 225 GIT_QUIET=$(cat "$dotest/quiet") 226 continue_merge 227whiletest"$msgnum"-le"$end" 228do 229 call_merge "$msgnum" 230 continue_merge 231done 232 finish_rb_merge 233exit 234fi 235 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name)&& 236 onto=$(cat "$GIT_DIR"/rebase-apply/onto)&& 237 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head)&& 238 GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet) 239 git am --resolved --3way --resolvemsg="$RESOLVEMSG"&& 240 move_to_original_branch 241exit 242;; 243--skip) 244test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 245 die "No rebase in progress?" 246 247 git reset--hard HEAD ||exit $? 248iftest -d"$dotest" 249then 250 git rerere clear 251 prev_head=$(cat "$dotest/prev_head") 252 end=$(cat "$dotest/end") 253 msgnum=$(cat "$dotest/msgnum") 254 msgnum=$(($msgnum + 1)) 255 onto=$(cat "$dotest/onto") 256 GIT_QUIET=$(cat "$dotest/quiet") 257whiletest"$msgnum"-le"$end" 258do 259 call_merge "$msgnum" 260 continue_merge 261done 262 finish_rb_merge 263exit 264fi 265 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name)&& 266 onto=$(cat "$GIT_DIR"/rebase-apply/onto)&& 267 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head)&& 268 GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet) 269 git am -3 --skip --resolvemsg="$RESOLVEMSG"&& 270 move_to_original_branch 271exit 272;; 273--abort) 274test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 275 die "No rebase in progress?" 276 277 git rerere clear 278 279test -d"$dotest"|| dotest="$GIT_DIR"/rebase-apply 280 281 head_name="$(cat "$dotest"/head-name)"&& 282case"$head_name"in 283 refs/*) 284 git symbolic-ref HEAD $head_name|| 285 die "Could not move back to$head_name" 286;; 287esac 288 git reset--hard$(cat "$dotest/orig-head") 289rm-r"$dotest" 290exit 291;; 292--onto) 293test2-le"$#"|| usage 294 newbase="$2" 295shift 296;; 297-M|-m|--m|--me|--mer|--merg|--merge) 298 do_merge=t 299;; 300-X*|--strategy-option*) 301case"$#,$1"in 3021,-X|1,--strategy-option) 303 usage ;; 304*,-X|*,--strategy-option) 305 newopt="$2" 306shift;; 307*,--strategy-option=*) 308 newopt="$(expr " $1" : ' --strategy-option=\(.*\)')";; 309*,-X*) 310 newopt="$(expr " $1" : ' -X\(.*\)')";; 3111,*) 312 usage ;; 313esac 314 strategy_opts="$strategy_opts$(git rev-parse --sq-quote "--$newopt")" 315 do_merge=t 316;; 317-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ 318--strateg=*|--strategy=*|\ 319-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) 320case"$#,$1"in 321*,*=*) 322 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'`;; 3231,*) 324 usage ;; 325*) 326 strategy="$2" 327shift;; 328esac 329 do_merge=t 330;; 331-n|--no-stat) 332 diffstat= 333;; 334--stat) 335 diffstat=t 336;; 337-v|--verbose) 338 verbose=t 339 diffstat=t 340 GIT_QUIET= 341;; 342-q|--quiet) 343 GIT_QUIET=t 344 git_am_opt="$git_am_opt-q" 345 verbose= 346 diffstat= 347;; 348--whitespace=*) 349 git_am_opt="$git_am_opt$1" 350case"$1"in 351--whitespace=fix|--whitespace=strip) 352 force_rebase=t 353;; 354esac 355;; 356--ignore-whitespace) 357 git_am_opt="$git_am_opt$1" 358;; 359--committer-date-is-author-date|--ignore-date) 360 git_am_opt="$git_am_opt$1" 361 force_rebase=t 362;; 363-C*) 364 git_am_opt="$git_am_opt$1" 365;; 366--root) 367 rebase_root=t 368;; 369-f|--f|--fo|--for|--forc|--force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase|--no-ff) 370 force_rebase=t 371;; 372--rerere-autoupdate|--no-rerere-autoupdate) 373 allow_rerere_autoupdate="$1" 374;; 375-*) 376 usage 377;; 378*) 379break 380;; 381esac 382shift 383done 384test$#-gt2&& usage 385 386iftest$#-eq0&&test -z"$rebase_root" 387then 388test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| usage 389test -d"$dotest"-o -f"$GIT_DIR"/rebase-apply/rebasing && 390 die 'A rebase is in progress, try --continue, --skip or --abort.' 391fi 392 393# Make sure we do not have $GIT_DIR/rebase-apply 394iftest -z"$do_merge" 395then 396ifmkdir"$GIT_DIR"/rebase-apply2>/dev/null 397then 398rmdir"$GIT_DIR"/rebase-apply 399else 400echo>&2' 401It seems that I cannot create a rebase-apply directory, and 402I wonder if you are in the middle of patch application or another 403rebase. If that is not the case, please 404 rm -fr '"$GIT_DIR"'/rebase-apply 405and run me again. I am stopping in case you still have something 406valuable there.' 407exit1 408fi 409else 410iftest -d"$dotest" 411then 412 die "previous rebase directory$doteststill exists." \ 413'Try git rebase (--continue | --abort | --skip)' 414fi 415fi 416 417# The tree must be really really clean. 418if! git update-index --ignore-submodules --refresh> /dev/null;then 419echo>&2"cannot rebase: you have unstaged changes" 420 git diff-files --name-status -r --ignore-submodules -->&2 421exit1 422fi 423diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --) 424case"$diff"in 425?*)echo>&2"cannot rebase: your index contains uncommitted changes" 426echo>&2"$diff" 427exit1 428;; 429esac 430 431iftest -z"$rebase_root" 432then 433# The upstream head must be given. Make sure it is valid. 434 upstream_name="$1" 435shift 436 upstream=`git rev-parse --verify "${upstream_name}^0"`|| 437 die "invalid upstream$upstream_name" 438unset root_flag 439 upstream_arg="$upstream_name" 440else 441test -z"$newbase"&& die "--root must be used with --onto" 442unset upstream_name 443unset upstream 444 root_flag="--root" 445 upstream_arg="$root_flag" 446fi 447 448# Make sure the branch to rebase onto is valid. 449onto_name=${newbase-"$upstream_name"} 450case"$onto_name"in 451*...*) 452if left=${onto_name%...*} right=${onto_name#*...}&& 453 onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD}) 454then 455case"$onto"in 456 ?*"$LF"?*) 457 die "$onto_name: there are more than one merge bases" 458;; 459'') 460 die "$onto_name: there is no merge base" 461;; 462esac 463else 464 die "$onto_name: there is no merge base" 465fi 466;; 467*) 468 onto=$(git rev-parse --verify "${onto_name}^0")||exit 469;; 470esac 471 472# If a hook exists, give it a chance to interrupt 473run_pre_rebase_hook "$upstream_arg""$@" 474 475# If the branch to rebase is given, that is the branch we will rebase 476# $branch_name -- branch being rebased, or HEAD (already detached) 477# $orig_head -- commit object name of tip of the branch before rebasing 478# $head_name -- refs/heads/<that-branch> or "detached HEAD" 479switch_to= 480case"$#"in 4811) 482# Is it "rebase other $branchname" or "rebase other $commit"? 483 branch_name="$1" 484 switch_to="$1" 485 486if git show-ref --verify --quiet --"refs/heads/$1"&& 487 branch=$(git rev-parse -q --verify "refs/heads/$1") 488then 489 head_name="refs/heads/$1" 490elif branch=$(git rev-parse -q --verify "$1") 491then 492 head_name="detached HEAD" 493else 494echo>&2"fatal: no such branch:$1" 495 usage 496fi 497;; 498*) 499# Do not need to switch branches, we are already on it. 500if branch_name=`git symbolic-ref -q HEAD` 501then 502 head_name=$branch_name 503 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` 504else 505 head_name="detached HEAD" 506 branch_name=HEAD ;# detached 507fi 508 branch=$(git rev-parse --verify "${branch_name}^0")||exit 509;; 510esac 511orig_head=$branch 512 513# Now we are rebasing commits $upstream..$branch (or with --root, 514# everything leading up to $branch) on top of $onto 515 516# Check if we are already based on $onto with linear history, 517# but this should be done only when upstream and onto are the same. 518mb=$(git merge-base "$onto" "$branch") 519iftest"$upstream"="$onto"&&test"$mb"="$onto"&& 520# linear history? 521! (git rev-list --parents"$onto".."$branch"| sane_grep " .* ") > /dev/null 522then 523iftest -z"$force_rebase" 524then 525# Lazily switch to the target branch if needed... 526test -z"$switch_to"|| git checkout "$switch_to"-- 527 say "Current branch$branch_nameis up to date." 528exit0 529else 530 say "Current branch$branch_nameis up to date, rebase forced." 531fi 532fi 533 534# Detach HEAD and reset the tree 535say "First, rewinding head to replay your work on top of it..." 536git checkout -q"$onto^0"|| die "could not detach HEAD" 537git update-ref ORIG_HEAD $branch 538 539iftest -n"$diffstat" 540then 541iftest -n"$verbose" 542then 543echo"Changes from$mbto$onto:" 544fi 545# We want color (if set), but no pager 546 GIT_PAGER='' git diff--stat --summary"$mb""$onto" 547fi 548 549# If the $onto is a proper descendant of the tip of the branch, then 550# we just fast-forwarded. 551iftest"$mb"="$branch" 552then 553 say "Fast-forwarded$branch_nameto$onto_name." 554 move_to_original_branch 555exit0 556fi 557 558iftest -n"$rebase_root" 559then 560 revisions="$onto..$orig_head" 561else 562 revisions="$upstream..$orig_head" 563fi 564 565iftest -z"$do_merge" 566then 567 git format-patch -k --stdout --full-index --ignore-if-in-upstream \ 568--src-prefix=a/--dst-prefix=b/ \ 569--no-renames$root_flag"$revisions"| 570 git am $git_am_opt--rebasing --resolvemsg="$RESOLVEMSG"&& 571 move_to_original_branch 572 ret=$? 573test0!=$ret-a -d"$GIT_DIR"/rebase-apply&& 574echo$head_name>"$GIT_DIR"/rebase-apply/head-name&& 575echo$onto>"$GIT_DIR"/rebase-apply/onto && 576echo$orig_head>"$GIT_DIR"/rebase-apply/orig-head&& 577echo"$GIT_QUIET">"$GIT_DIR"/rebase-apply/quiet 578exit$ret 579fi 580 581# start doing a rebase with git-merge 582# this is rename-aware if the recursive (default) strategy is used 583 584mkdir-p"$dotest" 585echo"$onto">"$dotest/onto" 586echo"$onto_name">"$dotest/onto_name" 587prev_head=$orig_head 588echo"$prev_head">"$dotest/prev_head" 589echo"$orig_head">"$dotest/orig-head" 590echo"$head_name">"$dotest/head-name" 591echo"$GIT_QUIET">"$dotest/quiet" 592 593msgnum=0 594for cmt in`git rev-list --reverse --no-merges "$revisions"` 595do 596 msgnum=$(($msgnum + 1)) 597echo"$cmt">"$dotest/cmt.$msgnum" 598done 599 600echo1>"$dotest/msgnum" 601echo$msgnum>"$dotest/end" 602 603end=$msgnum 604msgnum=1 605 606whiletest"$msgnum"-le"$end" 607do 608 call_merge "$msgnum" 609 continue_merge 610done 611 612finish_rb_merge