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