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