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