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