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