1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano. 4# 5 6USAGE='[--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 .dotest working files, use the command 18git rebase --abort instead. 19 20Note that if <branch> is not specified on the command line, the 21currently checked out branch is used. You must be in the top 22directory of your project to start (or continue) a rebase. 23 24Example: git-rebase master~1 topic 25 26 A---B---C topic A'\''--B'\''--C'\'' topic 27 / --> / 28 D---E---F---G master D---E---F---G master 29' 30. git-sh-setup 31 32RESOLVEMSG=" 33When you have resolved this problem run\"git rebase --continue\". 34If you would prefer to skip this patch, instead run\"git rebase --skip\". 35To restore the original branch and stop rebasing run\"git rebase --abort\". 36" 37unset newbase 38case"${GIT_USE_RECUR_FOR_RECURSIVE}"in 39'') 40 strategy=recursive ;; 41?*) 42 strategy=recur ;; 43esac 44 45do_merge= 46dotest=$GIT_DIR/.dotest-merge 47prec=4 48 49continue_merge () { 50test -n"$prev_head"|| die "prev_head must be defined" 51test -d"$dotest"|| die "$dotestdirectory does not exist" 52 53 unmerged=$(git-ls-files -u) 54iftest -n"$unmerged" 55then 56echo"You still have unmerged paths in your index" 57echo"did you forget update-index?" 58 die "$RESOLVEMSG" 59fi 60 61iftest -n"`git-diff-index HEAD`" 62then 63if! git-commit -C"`cat$dotest/current`" 64then 65echo"Commit failed, please do not call\"git commit\"" 66echo"directly, but instead do one of the following: " 67 die "$RESOLVEMSG" 68fi 69printf"Committed: %0${prec}d"$msgnum 70else 71printf"Already applied: %0${prec}d"$msgnum 72fi 73echo' '`git-rev-list --pretty=oneline -1 HEAD | \ 74 sed 's/^[a-f0-9]\+ //'` 75 76 prev_head=`git-rev-parse HEAD^0` 77# save the resulting commit so we can read-tree on it later 78echo"$prev_head">"$dotest/prev_head" 79 80# onto the next patch: 81 msgnum=$(($msgnum + 1)) 82echo"$msgnum">"$dotest/msgnum" 83} 84 85call_merge () { 86 cmt="$(cat $dotest/cmt.$1)" 87echo"$cmt">"$dotest/current" 88 git-merge-$strategy"$cmt^"-- HEAD "$cmt" 89 rv=$? 90case"$rv"in 910) 92return 93;; 941) 95test -d"$GIT_DIR/rr-cache"&& git-rerere 96 die "$RESOLVEMSG" 97;; 982) 99echo"Strategy:$rv$strategyfailed, try another"1>&2 100 die "$RESOLVEMSG" 101;; 102*) 103 die "Unknown exit code ($rv) from command:" \ 104"git-merge-$strategy$cmt^ -- HEAD$cmt" 105;; 106esac 107} 108 109finish_rb_merge () { 110rm-r"$dotest" 111echo"All done." 112} 113 114while case"$#"in0)break;;esac 115do 116case"$1"in 117--continue) 118diff=$(git-diff-files) 119case"$diff"in 120 ?*)echo"You must edit all merge conflicts and then" 121echo"mark them as resolved using git update-index" 122exit1 123;; 124esac 125iftest -d"$dotest" 126then 127 prev_head="`cat$dotest/prev_head`" 128 end="`cat$dotest/end`" 129 msgnum="`cat$dotest/msgnum`" 130 onto="`cat$dotest/onto`" 131 continue_merge 132whiletest"$msgnum"-le"$end" 133do 134 call_merge "$msgnum" 135 continue_merge 136done 137 finish_rb_merge 138exit 139fi 140 git am --resolved --3way --resolvemsg="$RESOLVEMSG" 141exit 142;; 143--skip) 144iftest -d"$dotest" 145then 146 prev_head="`cat$dotest/prev_head`" 147 end="`cat$dotest/end`" 148 msgnum="`cat$dotest/msgnum`" 149 msgnum=$(($msgnum + 1)) 150 onto="`cat$dotest/onto`" 151whiletest"$msgnum"-le"$end" 152do 153 call_merge "$msgnum" 154 continue_merge 155done 156 finish_rb_merge 157exit 158fi 159 git am -3 --skip --resolvemsg="$RESOLVEMSG" 160exit 161;; 162--abort) 163iftest -d"$dotest" 164then 165rm-r"$dotest" 166eliftest -d .dotest 167then 168rm-r .dotest 169else 170 die "No rebase in progress?" 171fi 172 git reset--hard ORIG_HEAD 173exit 174;; 175--onto) 176test2-le"$#"|| usage 177 newbase="$2" 178shift 179;; 180-M|-m|--m|--me|--mer|--merg|--merge) 181 do_merge=t 182;; 183-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ 184--strateg=*|--strategy=*|\ 185-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) 186case"$#,$1"in 187*,*=*) 188 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'`;; 1891,*) 190 usage ;; 191*) 192 strategy="$2" 193shift;; 194esac 195 do_merge=t 196;; 197-*) 198 usage 199;; 200*) 201break 202;; 203esac 204shift 205done 206 207case"$strategy,${GIT_USE_RECUR_FOR_RECURSIVE}"in 208recursive,?*) 209 strategy=recur ;; 210esac 211 212# Make sure we do not have .dotest 213iftest -z"$do_merge" 214then 215ifmkdir .dotest 216then 217rmdir .dotest 218else 219echo>&2' 220It seems that I cannot create a .dotest directory, and I wonder if you 221are in the middle of patch application or another rebase. If that is not 222the case, please rm -fr .dotest and run me again. I am stopping in case 223you still have something valuable there.' 224exit1 225fi 226else 227iftest -d"$dotest" 228then 229 die "previous dotest directory$doteststill exists." \ 230'try git-rebase < --continue | --abort >' 231fi 232fi 233 234# The tree must be really really clean. 235git-update-index --refresh||exit 236diff=$(git-diff-index --cached --name-status -r HEAD) 237case"$diff"in 238?*)echo"$diff" 239exit1 240;; 241esac 242 243# The upstream head must be given. Make sure it is valid. 244upstream_name="$1" 245upstream=`git rev-parse --verify "${upstream_name}^0"`|| 246 die "invalid upstream$upstream_name" 247 248# If a hook exists, give it a chance to interrupt 249iftest -x"$GIT_DIR/hooks/pre-rebase" 250then 251"$GIT_DIR/hooks/pre-rebase"${1+"$@"}|| { 252echo>&2"The pre-rebase hook refused to rebase." 253exit1 254} 255fi 256 257# If the branch to rebase is given, first switch to it. 258case"$#"in 2592) 260 branch_name="$2" 261 git-checkout"$2"|| usage 262;; 263*) 264 branch_name=`git symbolic-ref HEAD`|| die "No current branch" 265 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` 266;; 267esac 268branch=$(git-rev-parse --verify "${branch_name}^0")||exit 269 270# Make sure the branch to rebase onto is valid. 271onto_name=${newbase-"$upstream_name"} 272onto=$(git-rev-parse --verify "${onto_name}^0")||exit 273 274# Now we are rebasing commits $upstream..$branch on top of $onto 275 276# Check if we are already based on $onto, but this should be 277# done only when upstream and onto are the same. 278iftest"$upstream"="$onto" 279then 280 mb=$(git-merge-base "$onto" "$branch") 281iftest"$mb"="$onto" 282then 283echo>&2"Current branch$branch_nameis up to date." 284exit0 285fi 286fi 287 288# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD. 289git-reset --hard"$onto" 290 291# If the $onto is a proper descendant of the tip of the branch, then 292# we just fast forwarded. 293iftest"$mb"="$onto" 294then 295echo>&2"Fast-forwarded$branchto$newbase." 296exit0 297fi 298 299iftest -z"$do_merge" 300then 301 git-format-patch -k --stdout --full-index"$upstream"..ORIG_HEAD | 302 git am --binary -3 -k --resolvemsg="$RESOLVEMSG" 303exit $? 304fi 305 306iftest"@@NO_PYTHON@@"&&test"$strategy"="recursive" 307then 308 die 'The recursive merge strategy currently relies on Python, 309which this installation of git was not configured with. Please consider 310a different merge strategy (e.g. octopus, resolve, stupid, ours) 311or install Python and git with Python support.' 312 313fi 314 315# start doing a rebase with git-merge 316# this is rename-aware if the recursive (default) strategy is used 317 318mkdir-p"$dotest" 319echo"$onto">"$dotest/onto" 320prev_head=`git-rev-parse HEAD^0` 321echo"$prev_head">"$dotest/prev_head" 322 323msgnum=0 324for cmt in`git-rev-list --no-merges "$upstream"..ORIG_HEAD \ 325 | @@PERL@@ -e 'print reverse <>'` 326do 327 msgnum=$(($msgnum + 1)) 328echo"$cmt">"$dotest/cmt.$msgnum" 329done 330 331echo1>"$dotest/msgnum" 332echo$msgnum>"$dotest/end" 333 334end=$msgnum 335msgnum=1 336 337whiletest"$msgnum"-le"$end" 338do 339 call_merge "$msgnum" 340 continue_merge 341done 342 343finish_rb_merge