1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano. 4# 5 6USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--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 89iftest -z"$GIT_QUIET" 90then 91 git rev-list --pretty=oneline -1"$cmt"|sed-e's/^[^ ]* //' 92fi 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 115export GIT_MERGE_VERBOSITY=1 116fi 117 git-merge-$strategy"$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 203iftest$#-eq0 204then 205test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| usage 206test -d"$dotest"-o -f"$GIT_DIR"/rebase-apply/rebasing && 207 die 'A rebase is in progress, try --continue, --skip or --abort.' 208 die "No arguments given and$GIT_DIR/rebase-apply already exists." 209fi 210 211whiletest$#!=0 212do 213case"$1"in 214--no-verify) 215 OK_TO_SKIP_PRE_REBASE=yes 216;; 217--continue) 218test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 219 die "No rebase in progress?" 220 221 git diff-files --quiet --ignore-submodules|| { 222echo"You must edit all merge conflicts and then" 223echo"mark them as resolved using git add" 224exit1 225} 226iftest -d"$dotest" 227then 228 prev_head=$(cat "$dotest/prev_head") 229 end=$(cat "$dotest/end") 230 msgnum=$(cat "$dotest/msgnum") 231 onto=$(cat "$dotest/onto") 232 GIT_QUIET=$(cat "$dotest/quiet") 233 continue_merge 234whiletest"$msgnum"-le"$end" 235do 236 call_merge "$msgnum" 237 continue_merge 238done 239 finish_rb_merge 240exit 241fi 242 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name)&& 243 onto=$(cat "$GIT_DIR"/rebase-apply/onto)&& 244 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head)&& 245 GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet) 246 git am --resolved --3way --resolvemsg="$RESOLVEMSG"&& 247 move_to_original_branch 248exit 249;; 250--skip) 251test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 252 die "No rebase in progress?" 253 254 git reset--hard HEAD ||exit $? 255iftest -d"$dotest" 256then 257 git rerere clear 258 prev_head=$(cat "$dotest/prev_head") 259 end=$(cat "$dotest/end") 260 msgnum=$(cat "$dotest/msgnum") 261 msgnum=$(($msgnum + 1)) 262 onto=$(cat "$dotest/onto") 263 GIT_QUIET=$(cat "$dotest/quiet") 264whiletest"$msgnum"-le"$end" 265do 266 call_merge "$msgnum" 267 continue_merge 268done 269 finish_rb_merge 270exit 271fi 272 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name)&& 273 onto=$(cat "$GIT_DIR"/rebase-apply/onto)&& 274 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head)&& 275 GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet) 276 git am -3 --skip --resolvemsg="$RESOLVEMSG"&& 277 move_to_original_branch 278exit 279;; 280--abort) 281test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 282 die "No rebase in progress?" 283 284 git rerere clear 285iftest -d"$dotest" 286then 287 GIT_QUIET=$(cat "$dotest/quiet") 288 move_to_original_branch 289else 290 dotest="$GIT_DIR"/rebase-apply 291 GIT_QUIET=$(cat "$dotest/quiet") 292 move_to_original_branch 293fi 294 git reset--hard$(cat "$dotest/orig-head") 295rm-r"$dotest" 296exit 297;; 298--onto) 299test2-le"$#"|| usage 300 newbase="$2" 301shift 302;; 303-M|-m|--m|--me|--mer|--merg|--merge) 304 do_merge=t 305;; 306-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ 307--strateg=*|--strategy=*|\ 308-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) 309case"$#,$1"in 310*,*=*) 311 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'`;; 3121,*) 313 usage ;; 314*) 315 strategy="$2" 316shift;; 317esac 318 do_merge=t 319;; 320-n|--no-stat) 321 diffstat= 322;; 323--stat) 324 diffstat=t 325;; 326-v|--verbose) 327 verbose=t 328 diffstat=t 329 GIT_QUIET= 330;; 331-q|--quiet) 332 GIT_QUIET=t 333 git_am_opt="$git_am_opt-q" 334 verbose= 335 diffstat= 336;; 337--whitespace=*) 338 git_am_opt="$git_am_opt$1" 339case"$1"in 340--whitespace=fix|--whitespace=strip) 341 force_rebase=t 342;; 343esac 344;; 345--ignore-whitespace) 346 git_am_opt="$git_am_opt$1" 347;; 348--committer-date-is-author-date|--ignore-date) 349 git_am_opt="$git_am_opt$1" 350 force_rebase=t 351;; 352-C*) 353 git_am_opt="$git_am_opt$1" 354;; 355--root) 356 rebase_root=t 357;; 358-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase) 359 force_rebase=t 360;; 361--rerere-autoupdate|--no-rerere-autoupdate) 362 allow_rerere_autoupdate="$1" 363;; 364-*) 365 usage 366;; 367*) 368break 369;; 370esac 371shift 372done 373test$#-gt2&& usage 374 375# Make sure we do not have $GIT_DIR/rebase-apply 376iftest -z"$do_merge" 377then 378ifmkdir"$GIT_DIR"/rebase-apply2>/dev/null 379then 380rmdir"$GIT_DIR"/rebase-apply 381else 382echo>&2' 383It seems that I cannot create a rebase-apply directory, and 384I wonder if you are in the middle of patch application or another 385rebase. If that is not the case, please 386 rm -fr '"$GIT_DIR"'/rebase-apply 387and run me again. I am stopping in case you still have something 388valuable there.' 389exit1 390fi 391else 392iftest -d"$dotest" 393then 394 die "previous rebase directory$doteststill exists." \ 395'Try git rebase (--continue | --abort | --skip)' 396fi 397fi 398 399# The tree must be really really clean. 400if! git update-index --ignore-submodules --refresh> /dev/null;then 401echo>&2"cannot rebase: you have unstaged changes" 402 git diff-files --name-status -r --ignore-submodules -->&2 403exit1 404fi 405diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --) 406case"$diff"in 407?*)echo>&2"cannot rebase: your index contains uncommitted changes" 408echo>&2"$diff" 409exit1 410;; 411esac 412 413iftest -z"$rebase_root" 414then 415# The upstream head must be given. Make sure it is valid. 416 upstream_name="$1" 417shift 418 upstream=`git rev-parse --verify "${upstream_name}^0"`|| 419 die "invalid upstream$upstream_name" 420unset root_flag 421 upstream_arg="$upstream_name" 422else 423test -z"$newbase"&& die "--root must be used with --onto" 424unset upstream_name 425unset upstream 426 root_flag="--root" 427 upstream_arg="$root_flag" 428fi 429 430# Make sure the branch to rebase onto is valid. 431onto_name=${newbase-"$upstream_name"} 432case"$onto_name"in 433*...*) 434if left=${onto_name%...*} right=${onto_name#*...}&& 435 onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD}) 436then 437case"$onto"in 438 ?*"$LF"?*) 439 die "$onto_name: there are more than one merge bases" 440;; 441'') 442 die "$onto_name: there is no merge base" 443;; 444esac 445else 446 die "$onto_name: there is no merge base" 447fi 448;; 449*) 450 onto=$(git rev-parse --verify "${onto_name}^0")||exit 451;; 452esac 453 454# If a hook exists, give it a chance to interrupt 455run_pre_rebase_hook "$upstream_arg""$@" 456 457# If the branch to rebase is given, that is the branch we will rebase 458# $branch_name -- branch being rebased, or HEAD (already detached) 459# $orig_head -- commit object name of tip of the branch before rebasing 460# $head_name -- refs/heads/<that-branch> or "detached HEAD" 461switch_to= 462case"$#"in 4631) 464# Is it "rebase other $branchname" or "rebase other $commit"? 465 branch_name="$1" 466 switch_to="$1" 467 468if git show-ref --verify --quiet --"refs/heads/$1"&& 469 branch=$(git rev-parse -q --verify "refs/heads/$1") 470then 471 head_name="refs/heads/$1" 472elif branch=$(git rev-parse -q --verify "$1") 473then 474 head_name="detached HEAD" 475else 476 usage 477fi 478;; 479*) 480# Do not need to switch branches, we are already on it. 481if branch_name=`git symbolic-ref -q HEAD` 482then 483 head_name=$branch_name 484 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` 485else 486 head_name="detached HEAD" 487 branch_name=HEAD ;# detached 488fi 489 branch=$(git rev-parse --verify "${branch_name}^0")||exit 490;; 491esac 492orig_head=$branch 493 494# Now we are rebasing commits $upstream..$branch (or with --root, 495# everything leading up to $branch) on top of $onto 496 497# Check if we are already based on $onto with linear history, 498# but this should be done only when upstream and onto are the same. 499mb=$(git merge-base "$onto" "$branch") 500iftest"$upstream"="$onto"&&test"$mb"="$onto"&& 501# linear history? 502! (git rev-list --parents"$onto".."$branch"| sane_grep " .* ") > /dev/null 503then 504iftest -z"$force_rebase" 505then 506# Lazily switch to the target branch if needed... 507test -z"$switch_to"|| git checkout "$switch_to" 508 say "Current branch$branch_nameis up to date." 509exit0 510else 511 say "Current branch$branch_nameis up to date, rebase forced." 512fi 513fi 514 515# Detach HEAD and reset the tree 516say "First, rewinding head to replay your work on top of it..." 517git checkout -q"$onto^0"|| die "could not detach HEAD" 518git update-ref ORIG_HEAD $branch 519 520iftest -n"$diffstat" 521then 522iftest -n"$verbose" 523then 524echo"Changes from$mbto$onto:" 525fi 526# We want color (if set), but no pager 527 GIT_PAGER='' git diff--stat --summary"$mb""$onto" 528fi 529 530# If the $onto is a proper descendant of the tip of the branch, then 531# we just fast-forwarded. 532iftest"$mb"="$branch" 533then 534 say "Fast-forwarded$branch_nameto$onto_name." 535 move_to_original_branch 536exit0 537fi 538 539iftest -n"$rebase_root" 540then 541 revisions="$onto..$orig_head" 542else 543 revisions="$upstream..$orig_head" 544fi 545 546iftest -z"$do_merge" 547then 548 git format-patch -k --stdout --full-index --ignore-if-in-upstream \ 549$root_flag"$revisions"| 550 git am $git_am_opt--rebasing --resolvemsg="$RESOLVEMSG"&& 551 move_to_original_branch 552 ret=$? 553test0!=$ret-a -d"$GIT_DIR"/rebase-apply&& 554echo$head_name>"$GIT_DIR"/rebase-apply/head-name&& 555echo$onto>"$GIT_DIR"/rebase-apply/onto && 556echo$orig_head>"$GIT_DIR"/rebase-apply/orig-head&& 557echo"$GIT_QUIET">"$GIT_DIR"/rebase-apply/quiet 558exit$ret 559fi 560 561# start doing a rebase with git-merge 562# this is rename-aware if the recursive (default) strategy is used 563 564mkdir-p"$dotest" 565echo"$onto">"$dotest/onto" 566echo"$onto_name">"$dotest/onto_name" 567prev_head=$orig_head 568echo"$prev_head">"$dotest/prev_head" 569echo"$orig_head">"$dotest/orig-head" 570echo"$head_name">"$dotest/head-name" 571echo"$GIT_QUIET">"$dotest/quiet" 572 573msgnum=0 574for cmt in`git rev-list --reverse --no-merges "$revisions"` 575do 576 msgnum=$(($msgnum + 1)) 577echo"$cmt">"$dotest/cmt.$msgnum" 578done 579 580echo1>"$dotest/msgnum" 581echo$msgnum>"$dotest/end" 582 583end=$msgnum 584msgnum=1 585 586whiletest"$msgnum"-le"$end" 587do 588 call_merge "$msgnum" 589 continue_merge 590done 591 592finish_rb_merge