1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano. 4# 5 6USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]' 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 37RESOLVEMSG=" 38When you have resolved this problem run\"git rebase --continue\". 39If you would prefer to skip this patch, instead run\"git rebase --skip\". 40To restore the original branch and stop rebasing run\"git rebase --abort\". 41" 42unset newbase 43strategy=recursive 44do_merge= 45dotest="$GIT_DIR"/rebase-merge 46prec=4 47verbose= 48git_am_opt= 49 50continue_merge () { 51test -n"$prev_head"|| die "prev_head must be defined" 52test -d"$dotest"|| die "$dotestdirectory does not exist" 53 54 unmerged=$(git ls-files -u) 55iftest -n"$unmerged" 56then 57echo"You still have unmerged paths in your index" 58echo"did you forget to use git add?" 59 die "$RESOLVEMSG" 60fi 61 62 cmt=`cat "$dotest/current"` 63if! git diff-index --quiet --ignore-submodules HEAD -- 64then 65if! git commit --no-verify -C"$cmt" 66then 67echo"Commit failed, please do not call\"git commit\"" 68echo"directly, but instead do one of the following: " 69 die "$RESOLVEMSG" 70fi 71printf"Committed: %0${prec}d "$msgnum 72else 73printf"Already applied: %0${prec}d "$msgnum 74fi 75 git rev-list --pretty=oneline -1"$cmt"|sed-e's/^[^ ]* //' 76 77 prev_head=`git rev-parse HEAD^0` 78# save the resulting commit so we can read-tree on it later 79echo"$prev_head">"$dotest/prev_head" 80 81# onto the next patch: 82 msgnum=$(($msgnum + 1)) 83echo"$msgnum">"$dotest/msgnum" 84} 85 86call_merge () { 87 cmt="$(cat "$dotest/cmt.$1")" 88echo"$cmt">"$dotest/current" 89 hd=$(git rev-parse --verify HEAD) 90 cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD) 91 msgnum=$(cat "$dotest/msgnum") 92 end=$(cat "$dotest/end") 93eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"' 94eval GITHEAD_$hd='$(cat "$dotest/onto_name")' 95export GITHEAD_$cmt GITHEAD_$hd 96 git-merge-$strategy"$cmt^"--"$hd""$cmt" 97 rv=$? 98case"$rv"in 990) 100unset GITHEAD_$cmt GITHEAD_$hd 101return 102;; 1031) 104 git rerere 105 die "$RESOLVEMSG" 106;; 1072) 108echo"Strategy:$rv$strategyfailed, try another"1>&2 109 die "$RESOLVEMSG" 110;; 111*) 112 die "Unknown exit code ($rv) from command:" \ 113"git-merge-$strategy$cmt^ -- HEAD$cmt" 114;; 115esac 116} 117 118move_to_original_branch () { 119test -z"$head_name"&& 120 head_name="$(cat "$dotest"/head-name)"&& 121 onto="$(cat "$dotest"/onto)"&& 122 orig_head="$(cat "$dotest"/orig-head)" 123case"$head_name"in 124 refs/*) 125 message="rebase finished:$head_nameonto$onto" 126 git update-ref -m"$message" \ 127$head_name $(git rev-parse HEAD) $orig_head&& 128 git symbolic-ref HEAD $head_name|| 129 die "Could not move back to$head_name" 130;; 131esac 132} 133 134finish_rb_merge () { 135 move_to_original_branch 136rm-r"$dotest" 137echo"All done." 138} 139 140is_interactive () { 141whiletest$#!=0 142do 143case"$1"in 144-i|--interactive) 145 interactive_rebase=explicit 146break 147;; 148-p|--preserve-merges) 149 interactive_rebase=implied 150;; 151esac 152shift 153done 154 155if["$interactive_rebase"= implied ];then 156 GIT_EDITOR=: 157export GIT_EDITOR 158fi 159 160test -n"$interactive_rebase"||test -f"$dotest"/interactive 161} 162 163test -f"$GIT_DIR"/rebase-apply/applying && 164 die 'It looks like git-am is in progress. Cannot rebase.' 165 166is_interactive "$@"&&exec git-rebase--interactive"$@" 167 168iftest$#-eq0 169then 170test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| usage 171test -d"$dotest"-o -f"$GIT_DIR"/rebase-apply/rebasing && 172 die 'A rebase is in progress, try --continue, --skip or --abort.' 173 die "No arguments given and$GIT_DIR/rebase-apply already exists." 174fi 175 176whiletest$#!=0 177do 178case"$1"in 179--continue) 180test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 181 die "No rebase in progress?" 182 183 git diff-files --quiet --ignore-submodules|| { 184echo"You must edit all merge conflicts and then" 185echo"mark them as resolved using git add" 186exit1 187} 188iftest -d"$dotest" 189then 190 prev_head=$(cat "$dotest/prev_head") 191 end=$(cat "$dotest/end") 192 msgnum=$(cat "$dotest/msgnum") 193 onto=$(cat "$dotest/onto") 194 continue_merge 195whiletest"$msgnum"-le"$end" 196do 197 call_merge "$msgnum" 198 continue_merge 199done 200 finish_rb_merge 201exit 202fi 203 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name)&& 204 onto=$(cat "$GIT_DIR"/rebase-apply/onto)&& 205 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head)&& 206 git am --resolved --3way --resolvemsg="$RESOLVEMSG"&& 207 move_to_original_branch 208exit 209;; 210--skip) 211test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 212 die "No rebase in progress?" 213 214 git reset--hard HEAD ||exit $? 215iftest -d"$dotest" 216then 217 git rerere clear 218 prev_head=$(cat "$dotest/prev_head") 219 end=$(cat "$dotest/end") 220 msgnum=$(cat "$dotest/msgnum") 221 msgnum=$(($msgnum + 1)) 222 onto=$(cat "$dotest/onto") 223whiletest"$msgnum"-le"$end" 224do 225 call_merge "$msgnum" 226 continue_merge 227done 228 finish_rb_merge 229exit 230fi 231 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name)&& 232 onto=$(cat "$GIT_DIR"/rebase-apply/onto)&& 233 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head)&& 234 git am -3 --skip --resolvemsg="$RESOLVEMSG"&& 235 move_to_original_branch 236exit 237;; 238--abort) 239test -d"$dotest"-o -d"$GIT_DIR"/rebase-apply|| 240 die "No rebase in progress?" 241 242 git rerere clear 243iftest -d"$dotest" 244then 245 move_to_original_branch 246else 247 dotest="$GIT_DIR"/rebase-apply 248 move_to_original_branch 249fi 250 git reset--hard$(cat "$dotest/orig-head") 251rm-r"$dotest" 252exit 253;; 254--onto) 255test2-le"$#"|| usage 256 newbase="$2" 257shift 258;; 259-M|-m|--m|--me|--mer|--merg|--merge) 260 do_merge=t 261;; 262-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ 263--strateg=*|--strategy=*|\ 264-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) 265case"$#,$1"in 266*,*=*) 267 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'`;; 2681,*) 269 usage ;; 270*) 271 strategy="$2" 272shift;; 273esac 274 do_merge=t 275;; 276-v|--verbose) 277 verbose=t 278;; 279--whitespace=*) 280 git_am_opt="$git_am_opt$1" 281;; 282-C*) 283 git_am_opt="$git_am_opt$1" 284;; 285-*) 286 usage 287;; 288*) 289break 290;; 291esac 292shift 293done 294 295# Make sure we do not have $GIT_DIR/rebase-apply 296iftest -z"$do_merge" 297then 298ifmkdir"$GIT_DIR"/rebase-apply2>/dev/null 299then 300rmdir"$GIT_DIR"/rebase-apply 301else 302echo>&2' 303It seems that I cannot create a rebase-apply directory, and 304I wonder if you are in the middle of patch application or another 305rebase. If that is not the case, please 306 rm -fr '"$GIT_DIR"'/rebase-apply 307and run me again. I am stopping in case you still have something 308valuable there.' 309exit1 310fi 311else 312iftest -d"$dotest" 313then 314 die "previous rebase directory$doteststill exists." \ 315'Try git rebase (--continue | --abort | --skip)' 316fi 317fi 318 319# The tree must be really really clean. 320git update-index --ignore-submodules --refresh||exit 321diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --) 322case"$diff"in 323?*)echo"cannot rebase: your index is not up-to-date" 324echo"$diff" 325exit1 326;; 327esac 328 329# The upstream head must be given. Make sure it is valid. 330upstream_name="$1" 331upstream=`git rev-parse --verify "${upstream_name}^0"`|| 332 die "invalid upstream$upstream_name" 333 334# Make sure the branch to rebase onto is valid. 335onto_name=${newbase-"$upstream_name"} 336onto=$(git rev-parse --verify "${onto_name}^0")||exit 337 338# If a hook exists, give it a chance to interrupt 339iftest -x"$GIT_DIR/hooks/pre-rebase" 340then 341"$GIT_DIR/hooks/pre-rebase"${1+"$@"}|| { 342echo>&2"The pre-rebase hook refused to rebase." 343exit1 344} 345fi 346 347# If the branch to rebase is given, that is the branch we will rebase 348# $branch_name -- branch being rebased, or HEAD (already detached) 349# $orig_head -- commit object name of tip of the branch before rebasing 350# $head_name -- refs/heads/<that-branch> or "detached HEAD" 351switch_to= 352case"$#"in 3532) 354# Is it "rebase other $branchname" or "rebase other $commit"? 355 branch_name="$2" 356 switch_to="$2" 357 358if git show-ref --verify --quiet --"refs/heads/$2"&& 359 branch=$(git rev-parse --verify "refs/heads/$2" 2>/dev/null) 360then 361 head_name="refs/heads/$2" 362elif branch=$(git rev-parse --verify "$2" 2>/dev/null) 363then 364 head_name="detached HEAD" 365else 366 usage 367fi 368;; 369*) 370# Do not need to switch branches, we are already on it. 371if branch_name=`git symbolic-ref -q HEAD` 372then 373 head_name=$branch_name 374 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` 375else 376 head_name="detached HEAD" 377 branch_name=HEAD ;# detached 378fi 379 branch=$(git rev-parse --verify "${branch_name}^0")||exit 380;; 381esac 382orig_head=$branch 383 384# Now we are rebasing commits $upstream..$branch on top of $onto 385 386# Check if we are already based on $onto with linear history, 387# but this should be done only when upstream and onto are the same. 388mb=$(git merge-base "$onto" "$branch") 389iftest"$upstream"="$onto"&&test"$mb"="$onto"&& 390# linear history? 391! (git rev-list --parents"$onto".."$branch"|grep" .* ") > /dev/null 392then 393# Lazily switch to the target branch if needed... 394test -z"$switch_to"|| git checkout "$switch_to" 395echo>&2"Current branch$branch_nameis up to date." 396exit0 397fi 398 399iftest -n"$verbose" 400then 401echo"Changes from$mbto$onto:" 402# We want color (if set), but no pager 403 GIT_PAGER='' git diff--stat --summary"$mb""$onto" 404fi 405 406# Detach HEAD and reset the tree 407echo"First, rewinding head to replay your work on top of it..." 408git checkout -q"$onto^0"|| die "could not detach HEAD" 409git update-ref ORIG_HEAD $branch 410 411# If the $onto is a proper descendant of the tip of the branch, then 412# we just fast forwarded. 413iftest"$mb"="$branch" 414then 415echo>&2"Fast-forwarded$branch_nameto$onto_name." 416 move_to_original_branch 417exit0 418fi 419 420iftest -z"$do_merge" 421then 422 git format-patch -k --stdout --full-index --ignore-if-in-upstream \ 423"$upstream..$orig_head"| 424 git am $git_am_opt--rebasing --resolvemsg="$RESOLVEMSG"&& 425 move_to_original_branch 426 ret=$? 427test0!=$ret-a -d"$GIT_DIR"/rebase-apply&& 428echo$head_name>"$GIT_DIR"/rebase-apply/head-name&& 429echo$onto>"$GIT_DIR"/rebase-apply/onto && 430echo$orig_head>"$GIT_DIR"/rebase-apply/orig-head 431exit$ret 432fi 433 434# start doing a rebase with git-merge 435# this is rename-aware if the recursive (default) strategy is used 436 437mkdir-p"$dotest" 438echo"$onto">"$dotest/onto" 439echo"$onto_name">"$dotest/onto_name" 440prev_head=$orig_head 441echo"$prev_head">"$dotest/prev_head" 442echo"$orig_head">"$dotest/orig-head" 443echo"$head_name">"$dotest/head-name" 444 445msgnum=0 446for cmt in`git rev-list --reverse --no-merges "$upstream..$orig_head"` 447do 448 msgnum=$(($msgnum + 1)) 449echo"$cmt">"$dotest/cmt.$msgnum" 450done 451 452echo1>"$dotest/msgnum" 453echo$msgnum>"$dotest/end" 454 455end=$msgnum 456msgnum=1 457 458whiletest"$msgnum"-le"$end" 459do 460 call_merge "$msgnum" 461 continue_merge 462done 463 464finish_rb_merge