blob: 18bc6946cfa592c11cf7499b1c1ff9a6cb378b26 [file] [log] [blame]
Junio C Hamano59e6b232005-06-25 02:23:43 -07001#!/bin/sh
2#
3# Copyright (c) 2005 Junio C Hamano.
4#
5
Stephen Boyd0e987a12009-06-16 15:33:01 -07006USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]'
sean031321c2006-04-26 10:49:38 -04007LONG_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.
Carl Worth69a60af2006-02-21 17:10:12 -080012
sean031321c2006-04-26 10:49:38 -040013It is possible that a merge failure will prevent this process from being
14completely automatic. You will have to resolve any such merge failure
Seancc120052006-05-13 23:34:08 -040015and run git rebase --continue. Another option is to bypass the commit
16that caused the merge failure with git rebase --skip. To restore the
Johannes Schindelin51ef1da2008-07-21 12:51:02 +020017original <branch> and remove the .git/rebase-apply working files, use the
18command git rebase --abort instead.
Carl Worth69a60af2006-02-21 17:10:12 -080019
sean031321c2006-04-26 10:49:38 -040020Note that if <branch> is not specified on the command line, the
SZEDER Gábor702088a2008-03-10 15:38:33 +010021currently checked out branch is used.
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080022
sean031321c2006-04-26 10:49:38 -040023Example: git-rebase master~1 topic
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080024
sean031321c2006-04-26 10:49:38 -040025 A---B---C topic A'\''--B'\''--C'\'' topic
26 / --> /
27 D---E---F---G master D---E---F---G master
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080028'
Junio C Hamano533b7032007-01-12 12:52:03 -080029
30SUBDIRECTORY_OK=Yes
Junio C Hamano8f321a32007-11-06 01:50:02 -080031OPTIONS_SPEC=
Junio C Hamanoae2b0f12005-11-24 00:12:11 -080032. git-sh-setup
Shawn O. Pearcef9474132006-12-28 02:34:48 -050033set_reflog_action rebase
Shawn O. Pearce7eff28a2006-12-30 23:32:38 -050034require_work_tree
Junio C Hamano533b7032007-01-12 12:52:03 -080035cd_to_toplevel
Junio C Hamano4282c4f2005-08-07 15:51:09 -070036
Nanako Shiraishic4427652008-10-06 14:14:29 +090037OK_TO_SKIP_PRE_REBASE=
Seancc120052006-05-13 23:34:08 -040038RESOLVEMSG="
39When you have resolved this problem run \"git rebase --continue\".
40If you would prefer to skip this patch, instead run \"git rebase --skip\".
41To restore the original branch and stop rebasing run \"git rebase --abort\".
42"
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080043unset newbase
Junio C Hamanoa06f6782006-09-24 19:49:47 -070044strategy=recursive
Eric Wong58634db2006-06-21 03:04:41 -070045do_merge=
Johannes Schindelin28ed6e72008-07-16 03:33:44 +020046dotest="$GIT_DIR"/rebase-merge
Eric Wong58634db2006-06-21 03:04:41 -070047prec=4
Robert Shearmanb7587892006-10-03 17:29:31 +010048verbose=
Tor Arne Vestbøa9c38212009-03-01 23:11:38 +010049diffstat=$(git config --bool rebase.stat)
Michael S. Tsirkin67dad682007-02-08 15:57:08 +020050git_am_opt=
Thomas Rast190f5322009-01-05 18:35:16 +010051rebase_root=
Sverre Rabbelierb2f82e02009-02-13 23:48:01 +010052force_rebase=
Eric Wong58634db2006-06-21 03:04:41 -070053
54continue_merge () {
55 test -n "$prev_head" || die "prev_head must be defined"
56 test -d "$dotest" || die "$dotest directory does not exist"
57
Junio C Hamano5be60072007-07-02 22:52:14 -070058 unmerged=$(git ls-files -u)
Eric Wong58634db2006-06-21 03:04:41 -070059 if test -n "$unmerged"
60 then
61 echo "You still have unmerged paths in your index"
Jonas Fonseca9b078732007-06-02 19:59:49 +020062 echo "did you forget to use git add?"
Eric Wong66eb64c2006-06-28 02:11:06 -070063 die "$RESOLVEMSG"
Eric Wong58634db2006-06-21 03:04:41 -070064 fi
65
Jonathan del Strother889a50e2007-10-17 10:31:35 +010066 cmt=`cat "$dotest/current"`
Johannes Schindelin6848d582008-05-14 18:03:59 +010067 if ! git diff-index --quiet --ignore-submodules HEAD --
Eric Wong58634db2006-06-21 03:04:41 -070068 then
Junio C Hamanoe6371222008-03-16 00:50:22 -070069 if ! git commit --no-verify -C "$cmt"
Eric Wongf0ef0592006-06-28 03:24:23 -070070 then
71 echo "Commit failed, please do not call \"git commit\""
72 echo "directly, but instead do one of the following: "
73 die "$RESOLVEMSG"
74 fi
Stephen Boyd0e987a12009-06-16 15:33:01 -070075 if test -z "$GIT_QUIET"
76 then
77 printf "Committed: %0${prec}d " $msgnum
78 fi
Eric Wong58634db2006-06-21 03:04:41 -070079 else
Stephen Boyd0e987a12009-06-16 15:33:01 -070080 if test -z "$GIT_QUIET"
81 then
82 printf "Already applied: %0${prec}d " $msgnum
83 fi
Eric Wong58634db2006-06-21 03:04:41 -070084 fi
Stephen Boyd0e987a12009-06-16 15:33:01 -070085 if test -z "$GIT_QUIET"
86 then
87 git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
88 fi
Eric Wong58634db2006-06-21 03:04:41 -070089
Junio C Hamano5be60072007-07-02 22:52:14 -070090 prev_head=`git rev-parse HEAD^0`
Eric Wong58634db2006-06-21 03:04:41 -070091 # save the resulting commit so we can read-tree on it later
Eric Wong58634db2006-06-21 03:04:41 -070092 echo "$prev_head" > "$dotest/prev_head"
93
94 # onto the next patch:
95 msgnum=$(($msgnum + 1))
Junio C Hamano5887ac82006-06-22 01:44:54 -070096 echo "$msgnum" >"$dotest/msgnum"
Eric Wong58634db2006-06-21 03:04:41 -070097}
98
99call_merge () {
Jonathan del Strother889a50e2007-10-17 10:31:35 +0100100 cmt="$(cat "$dotest/cmt.$1")"
Eric Wong58634db2006-06-21 03:04:41 -0700101 echo "$cmt" > "$dotest/current"
Junio C Hamano5be60072007-07-02 22:52:14 -0700102 hd=$(git rev-parse --verify HEAD)
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000103 cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
Jonathan del Strother889a50e2007-10-17 10:31:35 +0100104 msgnum=$(cat "$dotest/msgnum")
105 end=$(cat "$dotest/end")
Shawn O. Pearce0bb733c2006-12-28 02:34:56 -0500106 eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
Jonathan del Strother889a50e2007-10-17 10:31:35 +0100107 eval GITHEAD_$hd='$(cat "$dotest/onto_name")'
Shawn O. Pearce0bb733c2006-12-28 02:34:56 -0500108 export GITHEAD_$cmt GITHEAD_$hd
Stephen Boyd0e987a12009-06-16 15:33:01 -0700109 if test -n "$GIT_QUIET"
110 then
111 export GIT_MERGE_VERBOSITY=1
112 fi
Shawn O. Pearce0bb733c2006-12-28 02:34:56 -0500113 git-merge-$strategy "$cmt^" -- "$hd" "$cmt"
Eric Wong58634db2006-06-21 03:04:41 -0700114 rv=$?
115 case "$rv" in
116 0)
Shawn O. Pearce0bb733c2006-12-28 02:34:56 -0500117 unset GITHEAD_$cmt GITHEAD_$hd
Eric Wong9e4bc7d2006-06-24 18:29:48 -0700118 return
Eric Wong58634db2006-06-21 03:04:41 -0700119 ;;
120 1)
Johannes Schindelinb4372ef2007-07-06 13:05:59 +0100121 git rerere
Eric Wong66eb64c2006-06-28 02:11:06 -0700122 die "$RESOLVEMSG"
Eric Wong58634db2006-06-21 03:04:41 -0700123 ;;
124 2)
125 echo "Strategy: $rv $strategy failed, try another" 1>&2
Eric Wong66eb64c2006-06-28 02:11:06 -0700126 die "$RESOLVEMSG"
Eric Wong58634db2006-06-21 03:04:41 -0700127 ;;
128 *)
129 die "Unknown exit code ($rv) from command:" \
130 "git-merge-$strategy $cmt^ -- HEAD $cmt"
131 ;;
132 esac
133}
134
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000135move_to_original_branch () {
136 test -z "$head_name" &&
137 head_name="$(cat "$dotest"/head-name)" &&
138 onto="$(cat "$dotest"/onto)" &&
139 orig_head="$(cat "$dotest"/orig-head)"
140 case "$head_name" in
141 refs/*)
142 message="rebase finished: $head_name onto $onto"
143 git update-ref -m "$message" \
144 $head_name $(git rev-parse HEAD) $orig_head &&
145 git symbolic-ref HEAD $head_name ||
146 die "Could not move back to $head_name"
147 ;;
148 esac
149}
150
Eric Wong58634db2006-06-21 03:04:41 -0700151finish_rb_merge () {
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000152 move_to_original_branch
Eric Wong58634db2006-06-21 03:04:41 -0700153 rm -r "$dotest"
Stephen Boyd0e987a12009-06-16 15:33:01 -0700154 say All done.
Eric Wong58634db2006-06-21 03:04:41 -0700155}
156
Johannes Schindelin1b1dce42007-06-25 01:11:14 +0100157is_interactive () {
Andreas Ericssonf8cca012008-09-29 22:28:57 +0200158 while test $# != 0
159 do
160 case "$1" in
161 -i|--interactive)
162 interactive_rebase=explicit
163 break
164 ;;
165 -p|--preserve-merges)
166 interactive_rebase=implied
167 ;;
168 esac
Johannes Schindelin1b1dce42007-06-25 01:11:14 +0100169 shift
Andreas Ericssonf8cca012008-09-29 22:28:57 +0200170 done
171
172 if [ "$interactive_rebase" = implied ]; then
173 GIT_EDITOR=:
174 export GIT_EDITOR
175 fi
176
177 test -n "$interactive_rebase" || test -f "$dotest"/interactive
Johannes Schindelin1b1dce42007-06-25 01:11:14 +0100178}
179
Nanako Shiraishid70b4a82008-10-06 14:14:24 +0900180run_pre_rebase_hook () {
Nanako Shiraishic4427652008-10-06 14:14:29 +0900181 if test -z "$OK_TO_SKIP_PRE_REBASE" &&
182 test -x "$GIT_DIR/hooks/pre-rebase"
Nanako Shiraishid70b4a82008-10-06 14:14:24 +0900183 then
Stephen Boydbc2bbc42009-06-14 16:08:56 -0700184 "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} ||
185 die "The pre-rebase hook refused to rebase."
Nanako Shiraishid70b4a82008-10-06 14:14:24 +0900186 fi
187}
188
Stephan Beyer9b752a62008-08-17 06:25:43 +0200189test -f "$GIT_DIR"/rebase-apply/applying &&
190 die 'It looks like git-am is in progress. Cannot rebase.'
191
Johannes Schindelin1b1dce42007-06-25 01:11:14 +0100192is_interactive "$@" && exec git-rebase--interactive "$@"
193
Stephan Beyer9b752a62008-08-17 06:25:43 +0200194if test $# -eq 0
195then
196 test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply || usage
197 test -d "$dotest" -o -f "$GIT_DIR"/rebase-apply/rebasing &&
198 die 'A rebase is in progress, try --continue, --skip or --abort.'
199 die "No arguments given and $GIT_DIR/rebase-apply already exists."
200fi
201
David Kastrup822f7c72007-09-23 22:42:08 +0200202while test $# != 0
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800203do
204 case "$1" in
Nanako Shiraishic4427652008-10-06 14:14:29 +0900205 --no-verify)
206 OK_TO_SKIP_PRE_REBASE=yes
207 ;;
sean031321c2006-04-26 10:49:38 -0400208 --continue)
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200209 test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
Stephan Beyercd5320f2008-06-22 16:07:02 +0200210 die "No rebase in progress?"
211
Johannes Schindelin6848d582008-05-14 18:03:59 +0100212 git diff-files --quiet --ignore-submodules || {
Alex Riesen06aff472007-03-25 01:56:13 +0100213 echo "You must edit all merge conflicts and then"
Jonas Fonseca9b078732007-06-02 19:59:49 +0200214 echo "mark them as resolved using git add"
sean031321c2006-04-26 10:49:38 -0400215 exit 1
Alex Riesen06aff472007-03-25 01:56:13 +0100216 }
Eric Wong58634db2006-06-21 03:04:41 -0700217 if test -d "$dotest"
218 then
Jonathan del Strother889a50e2007-10-17 10:31:35 +0100219 prev_head=$(cat "$dotest/prev_head")
220 end=$(cat "$dotest/end")
221 msgnum=$(cat "$dotest/msgnum")
222 onto=$(cat "$dotest/onto")
Stephen Boyd0e987a12009-06-16 15:33:01 -0700223 GIT_QUIET=$(cat "$dotest/quiet")
Eric Wong58634db2006-06-21 03:04:41 -0700224 continue_merge
225 while test "$msgnum" -le "$end"
226 do
227 call_merge "$msgnum"
228 continue_merge
229 done
230 finish_rb_merge
231 exit
232 fi
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200233 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
234 onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
235 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
Stephen Boyd0e987a12009-06-16 15:33:01 -0700236 GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
Johannes Schindelin3f735b62007-11-12 13:11:46 +0000237 git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
238 move_to_original_branch
Seancc120052006-05-13 23:34:08 -0400239 exit
240 ;;
241 --skip)
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200242 test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
Stephan Beyercd5320f2008-06-22 16:07:02 +0200243 die "No rebase in progress?"
244
Mike Hommeyfb6e4e12007-11-08 08:03:06 +0100245 git reset --hard HEAD || exit $?
Eric Wong58634db2006-06-21 03:04:41 -0700246 if test -d "$dotest"
247 then
Johannes Schindelinb4372ef2007-07-06 13:05:59 +0100248 git rerere clear
Jonathan del Strother889a50e2007-10-17 10:31:35 +0100249 prev_head=$(cat "$dotest/prev_head")
250 end=$(cat "$dotest/end")
251 msgnum=$(cat "$dotest/msgnum")
Eric Wongd5e673b2006-06-24 18:29:49 -0700252 msgnum=$(($msgnum + 1))
Jonathan del Strother889a50e2007-10-17 10:31:35 +0100253 onto=$(cat "$dotest/onto")
Stephen Boyd0e987a12009-06-16 15:33:01 -0700254 GIT_QUIET=$(cat "$dotest/quiet")
Eric Wongd5e673b2006-06-24 18:29:49 -0700255 while test "$msgnum" -le "$end"
256 do
257 call_merge "$msgnum"
258 continue_merge
259 done
260 finish_rb_merge
261 exit
Eric Wong58634db2006-06-21 03:04:41 -0700262 fi
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200263 head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
264 onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
265 orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
Stephen Boyd0e987a12009-06-16 15:33:01 -0700266 GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000267 git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
268 move_to_original_branch
sean031321c2006-04-26 10:49:38 -0400269 exit
270 ;;
271 --abort)
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200272 test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
Stephan Beyercd5320f2008-06-22 16:07:02 +0200273 die "No rebase in progress?"
274
Johannes Schindelinb4372ef2007-07-06 13:05:59 +0100275 git rerere clear
Eric Wong58634db2006-06-21 03:04:41 -0700276 if test -d "$dotest"
277 then
Stephen Boyd0e987a12009-06-16 15:33:01 -0700278 GIT_QUIET=$(cat "$dotest/quiet")
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000279 move_to_original_branch
Stephan Beyercd5320f2008-06-22 16:07:02 +0200280 else
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200281 dotest="$GIT_DIR"/rebase-apply
Stephen Boyd0e987a12009-06-16 15:33:01 -0700282 GIT_QUIET=$(cat "$dotest/quiet")
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000283 move_to_original_branch
Eric Wong58634db2006-06-21 03:04:41 -0700284 fi
Bryan Donlan97b88dd2008-05-04 01:37:51 -0400285 git reset --hard $(cat "$dotest/orig-head")
Mike Hommey48411d22008-03-01 11:32:14 +0100286 rm -r "$dotest"
sean031321c2006-04-26 10:49:38 -0400287 exit
288 ;;
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800289 --onto)
290 test 2 -le "$#" || usage
291 newbase="$2"
292 shift
293 ;;
Eric Wong58634db2006-06-21 03:04:41 -0700294 -M|-m|--m|--me|--mer|--merg|--merge)
295 do_merge=t
296 ;;
297 -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
298 --strateg=*|--strategy=*|\
299 -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
300 case "$#,$1" in
301 *,*=*)
Dennis Stosberg8096fae2006-06-27 18:54:26 +0200302 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
Eric Wong58634db2006-06-21 03:04:41 -0700303 1,*)
304 usage ;;
305 *)
306 strategy="$2"
307 shift ;;
308 esac
309 do_merge=t
310 ;;
Tor Arne Vestbøa9c38212009-03-01 23:11:38 +0100311 -n|--no-stat)
312 diffstat=
313 ;;
314 --stat)
315 diffstat=t
316 ;;
Robert Shearmanb7587892006-10-03 17:29:31 +0100317 -v|--verbose)
318 verbose=t
Tor Arne Vestbøa9c38212009-03-01 23:11:38 +0100319 diffstat=t
Stephen Boyd0e987a12009-06-16 15:33:01 -0700320 GIT_QUIET=
321 ;;
322 -q|--quiet)
323 GIT_QUIET=t
324 git_am_opt="$git_am_opt -q"
325 verbose=
326 diffstat=
Robert Shearmanb7587892006-10-03 17:29:31 +0100327 ;;
J. Bruce Fields059f4462007-09-07 10:20:50 -0400328 --whitespace=*)
329 git_am_opt="$git_am_opt $1"
Sverre Rabbelierb2f82e02009-02-13 23:48:01 +0100330 case "$1" in
331 --whitespace=fix|--whitespace=strip)
332 force_rebase=t
333 ;;
334 esac
J. Bruce Fields059f4462007-09-07 10:20:50 -0400335 ;;
Michele Ballabio570ccad2009-03-18 21:53:49 +0100336 --committer-date-is-author-date|--ignore-date)
337 git_am_opt="$git_am_opt $1"
338 force_rebase=t
339 ;;
Michael S. Tsirkin67dad682007-02-08 15:57:08 +0200340 -C*)
J. Bruce Fields059f4462007-09-07 10:20:50 -0400341 git_am_opt="$git_am_opt $1"
Michael S. Tsirkin67dad682007-02-08 15:57:08 +0200342 ;;
Thomas Rast190f5322009-01-05 18:35:16 +0100343 --root)
344 rebase_root=t
345 ;;
Michele Ballabio3f7d9922009-03-18 19:05:56 +0100346 -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
Sverre Rabbelierb2f82e02009-02-13 23:48:01 +0100347 force_rebase=t
348 ;;
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800349 -*)
350 usage
351 ;;
352 *)
353 break
354 ;;
355 esac
356 shift
357done
Jay Soffian51b2ead2009-02-18 08:44:02 -0500358test $# -gt 2 && usage
Junio C Hamano2db8aae2005-12-14 03:11:37 -0800359
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200360# Make sure we do not have $GIT_DIR/rebase-apply
Eric Wong58634db2006-06-21 03:04:41 -0700361if test -z "$do_merge"
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800362then
Stephan Beyer9b752a62008-08-17 06:25:43 +0200363 if mkdir "$GIT_DIR"/rebase-apply 2>/dev/null
Eric Wong58634db2006-06-21 03:04:41 -0700364 then
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200365 rmdir "$GIT_DIR"/rebase-apply
Eric Wong58634db2006-06-21 03:04:41 -0700366 else
367 echo >&2 '
Stephan Beyer9b752a62008-08-17 06:25:43 +0200368It seems that I cannot create a rebase-apply directory, and
369I wonder if you are in the middle of patch application or another
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200370rebase. If that is not the case, please
371 rm -fr '"$GIT_DIR"'/rebase-apply
Stephan Beyer9b752a62008-08-17 06:25:43 +0200372and run me again. I am stopping in case you still have something
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200373valuable there.'
Eric Wong58634db2006-06-21 03:04:41 -0700374 exit 1
375 fi
376else
377 if test -d "$dotest"
378 then
Johannes Schindelin28ed6e72008-07-16 03:33:44 +0200379 die "previous rebase directory $dotest still exists." \
Stephan Beyer9b752a62008-08-17 06:25:43 +0200380 'Try git rebase (--continue | --abort | --skip)'
Eric Wong58634db2006-06-21 03:04:41 -0700381 fi
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800382fi
383
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800384# The tree must be really really clean.
Jeff King07e62b72008-12-10 04:25:19 -0500385if ! git update-index --ignore-submodules --refresh; then
Stephen Boydbc2bbc42009-06-14 16:08:56 -0700386 die "cannot rebase: you have unstaged changes"
Jeff King07e62b72008-12-10 04:25:19 -0500387fi
Johannes Schindelin6848d582008-05-14 18:03:59 +0100388diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --)
Lukas Sandström32d99542005-12-15 00:36:35 +0100389case "$diff" in
Jeff King07e62b72008-12-10 04:25:19 -0500390?*) echo >&2 "cannot rebase: your index contains uncommitted changes"
391 echo >&2 "$diff"
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800392 exit 1
393 ;;
Junio C Hamano59e6b232005-06-25 02:23:43 -0700394esac
395
Thomas Rast190f5322009-01-05 18:35:16 +0100396if test -z "$rebase_root"
397then
398 # The upstream head must be given. Make sure it is valid.
399 upstream_name="$1"
400 shift
401 upstream=`git rev-parse --verify "${upstream_name}^0"` ||
402 die "invalid upstream $upstream_name"
403 unset root_flag
404 upstream_arg="$upstream_name"
405else
406 test -z "$newbase" && die "--root must be used with --onto"
407 unset upstream_name
408 unset upstream
409 root_flag="--root"
410 upstream_arg="$root_flag"
411fi
Lukas Sandström32d99542005-12-15 00:36:35 +0100412
Junio C Hamanoa1bf91e2007-03-22 02:54:59 -0700413# Make sure the branch to rebase onto is valid.
414onto_name=${newbase-"$upstream_name"}
Junio C Hamano5be60072007-07-02 22:52:14 -0700415onto=$(git rev-parse --verify "${onto_name}^0") || exit
Junio C Hamanoa1bf91e2007-03-22 02:54:59 -0700416
Junio C Hamano9a111c92006-02-12 23:17:04 -0800417# If a hook exists, give it a chance to interrupt
Thomas Rast190f5322009-01-05 18:35:16 +0100418run_pre_rebase_hook "$upstream_arg" "$@"
Junio C Hamano9a111c92006-02-12 23:17:04 -0800419
Junio C Hamano0cb06642008-03-15 13:17:42 -0700420# If the branch to rebase is given, that is the branch we will rebase
421# $branch_name -- branch being rebased, or HEAD (already detached)
422# $orig_head -- commit object name of tip of the branch before rebasing
423# $head_name -- refs/heads/<that-branch> or "detached HEAD"
424switch_to=
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800425case "$#" in
Thomas Rast190f5322009-01-05 18:35:16 +01004261)
Junio C Hamano0cb06642008-03-15 13:17:42 -0700427 # Is it "rebase other $branchname" or "rebase other $commit"?
Thomas Rast190f5322009-01-05 18:35:16 +0100428 branch_name="$1"
429 switch_to="$1"
Junio C Hamano0cb06642008-03-15 13:17:42 -0700430
Thomas Rast190f5322009-01-05 18:35:16 +0100431 if git show-ref --verify --quiet -- "refs/heads/$1" &&
432 branch=$(git rev-parse -q --verify "refs/heads/$1")
Junio C Hamanobcf31612007-01-20 19:11:29 -0800433 then
Thomas Rast190f5322009-01-05 18:35:16 +0100434 head_name="refs/heads/$1"
435 elif branch=$(git rev-parse -q --verify "$1")
Junio C Hamano0cb06642008-03-15 13:17:42 -0700436 then
437 head_name="detached HEAD"
Junio C Hamanobcf31612007-01-20 19:11:29 -0800438 else
Junio C Hamano0cb06642008-03-15 13:17:42 -0700439 usage
Junio C Hamanobcf31612007-01-20 19:11:29 -0800440 fi
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800441 ;;
Junio C Hamano0cb06642008-03-15 13:17:42 -0700442*)
443 # Do not need to switch branches, we are already on it.
444 if branch_name=`git symbolic-ref -q HEAD`
445 then
446 head_name=$branch_name
447 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
448 else
449 head_name="detached HEAD"
450 branch_name=HEAD ;# detached
451 fi
452 branch=$(git rev-parse --verify "${branch_name}^0") || exit
453 ;;
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800454esac
Junio C Hamano0cb06642008-03-15 13:17:42 -0700455orig_head=$branch
Junio C Hamano99a92f92005-08-17 15:19:57 -0700456
Thomas Rast190f5322009-01-05 18:35:16 +0100457# Now we are rebasing commits $upstream..$branch (or with --root,
458# everything leading up to $branch) on top of $onto
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800459
Johannes Sixt1308c172007-07-04 22:09:10 +0200460# Check if we are already based on $onto with linear history,
461# but this should be done only when upstream and onto are the same.
Junio C Hamano5be60072007-07-02 22:52:14 -0700462mb=$(git merge-base "$onto" "$branch")
Johannes Sixt1308c172007-07-04 22:09:10 +0200463if test "$upstream" = "$onto" && test "$mb" = "$onto" &&
464 # linear history?
Jeff Kingbbf08122008-05-14 00:01:22 -0400465 ! (git rev-list --parents "$onto".."$branch" | grep " .* ") > /dev/null
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800466then
Sverre Rabbelierb2f82e02009-02-13 23:48:01 +0100467 if test -z "$force_rebase"
468 then
469 # Lazily switch to the target branch if needed...
470 test -z "$switch_to" || git checkout "$switch_to"
Stephen Boyd0e987a12009-06-16 15:33:01 -0700471 say "Current branch $branch_name is up to date."
Sverre Rabbelierb2f82e02009-02-13 23:48:01 +0100472 exit 0
473 else
Stephen Boyd0e987a12009-06-16 15:33:01 -0700474 say "Current branch $branch_name is up to date, rebase forced."
Sverre Rabbelierb2f82e02009-02-13 23:48:01 +0100475 fi
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800476fi
477
Junio C Hamano0cb06642008-03-15 13:17:42 -0700478# Detach HEAD and reset the tree
Stephen Boyd0e987a12009-06-16 15:33:01 -0700479say "First, rewinding head to replay your work on top of it..."
Junio C Hamano324c2c32008-07-14 14:05:35 -0700480git checkout -q "$onto^0" || die "could not detach HEAD"
Junio C Hamano22e40792008-07-07 00:16:38 -0700481git update-ref ORIG_HEAD $branch
Lukas Sandström32d99542005-12-15 00:36:35 +0100482
Tor Arne Vestbøa9c38212009-03-01 23:11:38 +0100483if test -n "$diffstat"
484then
485 if test -n "$verbose"
486 then
487 echo "Changes from $mb to $onto:"
488 fi
489 # We want color (if set), but no pager
490 GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
491fi
492
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800493# If the $onto is a proper descendant of the tip of the branch, then
Lukas Sandström32d99542005-12-15 00:36:35 +0100494# we just fast forwarded.
Robert Shearman83c31612006-07-27 10:32:25 +0100495if test "$mb" = "$branch"
Lukas Sandström32d99542005-12-15 00:36:35 +0100496then
Stephen Boyd0e987a12009-06-16 15:33:01 -0700497 say "Fast-forwarded $branch_name to $onto_name."
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000498 move_to_original_branch
Lukas Sandström32d99542005-12-15 00:36:35 +0100499 exit 0
500fi
501
Thomas Rast190f5322009-01-05 18:35:16 +0100502if test -n "$rebase_root"
503then
504 revisions="$onto..$orig_head"
505else
506 revisions="$upstream..$orig_head"
507fi
508
Eric Wong58634db2006-06-21 03:04:41 -0700509if test -z "$do_merge"
510then
Junio C Hamano0cb06642008-03-15 13:17:42 -0700511 git format-patch -k --stdout --full-index --ignore-if-in-upstream \
Thomas Rast190f5322009-01-05 18:35:16 +0100512 $root_flag "$revisions" |
Junio C Hamano3041c322008-03-04 00:25:06 -0800513 git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000514 move_to_original_branch
515 ret=$?
Johannes Schindelin51ef1da2008-07-21 12:51:02 +0200516 test 0 != $ret -a -d "$GIT_DIR"/rebase-apply &&
517 echo $head_name > "$GIT_DIR"/rebase-apply/head-name &&
518 echo $onto > "$GIT_DIR"/rebase-apply/onto &&
Stephen Boyd0e987a12009-06-16 15:33:01 -0700519 echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head &&
520 echo "$GIT_QUIET" > "$GIT_DIR"/rebase-apply/quiet
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000521 exit $ret
Eric Wong58634db2006-06-21 03:04:41 -0700522fi
Seancc120052006-05-13 23:34:08 -0400523
Eric Wong58634db2006-06-21 03:04:41 -0700524# start doing a rebase with git-merge
525# this is rename-aware if the recursive (default) strategy is used
526
527mkdir -p "$dotest"
528echo "$onto" > "$dotest/onto"
Shawn O. Pearce0bb733c2006-12-28 02:34:56 -0500529echo "$onto_name" > "$dotest/onto_name"
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000530prev_head=$orig_head
Eric Wong58634db2006-06-21 03:04:41 -0700531echo "$prev_head" > "$dotest/prev_head"
Johannes Schindelin6fd2f5e2007-11-08 18:19:08 +0000532echo "$orig_head" > "$dotest/orig-head"
533echo "$head_name" > "$dotest/head-name"
Stephen Boyd0e987a12009-06-16 15:33:01 -0700534echo "$GIT_QUIET" > "$dotest/quiet"
Eric Wong58634db2006-06-21 03:04:41 -0700535
536msgnum=0
Thomas Rast190f5322009-01-05 18:35:16 +0100537for cmt in `git rev-list --reverse --no-merges "$revisions"`
Eric Wong58634db2006-06-21 03:04:41 -0700538do
539 msgnum=$(($msgnum + 1))
Junio C Hamano5887ac82006-06-22 01:44:54 -0700540 echo "$cmt" > "$dotest/cmt.$msgnum"
Eric Wong58634db2006-06-21 03:04:41 -0700541done
542
Junio C Hamano5887ac82006-06-22 01:44:54 -0700543echo 1 >"$dotest/msgnum"
544echo $msgnum >"$dotest/end"
Eric Wong58634db2006-06-21 03:04:41 -0700545
546end=$msgnum
547msgnum=1
548
549while test "$msgnum" -le "$end"
550do
551 call_merge "$msgnum"
552 continue_merge
553done
554
555finish_rb_merge