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