blob: 3945e067141ec1bc87456179a59de8f692bdf9fa [file] [log] [blame]
Junio C Hamano59e6b232005-06-25 02:23:43 -07001#!/bin/sh
2#
3# Copyright (c) 2005 Junio C Hamano.
4#
5
Junio C Hamanoe646c9c2006-02-14 14:42:05 -08006USAGE='[--onto <newbase>] <upstream> [<branch>]'
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
17original <branch> and remove the .dotest working files, use the command
18git 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
21currently checked out branch is used. You must be in the top
22directory of your project to start (or continue) a rebase.
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080023
sean031321c2006-04-26 10:49:38 -040024Example: git-rebase master~1 topic
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080025
sean031321c2006-04-26 10:49:38 -040026 A---B---C topic A'\''--B'\''--C'\'' topic
27 / --> /
28 D---E---F---G master D---E---F---G master
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080029'
Junio C Hamanoae2b0f12005-11-24 00:12:11 -080030. git-sh-setup
Junio C Hamano4282c4f2005-08-07 15:51:09 -070031
Seancc120052006-05-13 23:34:08 -040032RESOLVEMSG="
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"
Junio C Hamanoe646c9c2006-02-14 14:42:05 -080037unset newbase
Eric Wong58634db2006-06-21 03:04:41 -070038strategy=recursive
39do_merge=
40dotest=$GIT_DIR/.dotest-merge
41prec=4
42
43continue_merge () {
44 test -n "$prev_head" || die "prev_head must be defined"
45 test -d "$dotest" || die "$dotest directory does not exist"
46
47 unmerged=$(git-ls-files -u)
48 if test -n "$unmerged"
49 then
50 echo "You still have unmerged paths in your index"
51 echo "did you forget update-index?"
Eric Wong66eb64c2006-06-28 02:11:06 -070052 die "$RESOLVEMSG"
Eric Wong58634db2006-06-21 03:04:41 -070053 fi
54
55 if test -n "`git-diff-index HEAD`"
56 then
Eric Wongf0ef0592006-06-28 03:24:23 -070057 if ! git-commit -C "`cat $dotest/current`"
58 then
59 echo "Commit failed, please do not call \"git commit\""
60 echo "directly, but instead do one of the following: "
61 die "$RESOLVEMSG"
62 fi
Eric Wong9e4bc7d2006-06-24 18:29:48 -070063 printf "Committed: %0${prec}d" $msgnum
Eric Wong58634db2006-06-21 03:04:41 -070064 else
Eric Wong9e4bc7d2006-06-24 18:29:48 -070065 printf "Already applied: %0${prec}d" $msgnum
Eric Wong58634db2006-06-21 03:04:41 -070066 fi
Eric Wong9e4bc7d2006-06-24 18:29:48 -070067 echo ' '`git-rev-list --pretty=oneline -1 HEAD | \
68 sed 's/^[a-f0-9]\+ //'`
Eric Wong58634db2006-06-21 03:04:41 -070069
70 prev_head=`git-rev-parse HEAD^0`
Eric Wong58634db2006-06-21 03:04:41 -070071 # save the resulting commit so we can read-tree on it later
Eric Wong58634db2006-06-21 03:04:41 -070072 echo "$prev_head" > "$dotest/prev_head"
73
74 # onto the next patch:
75 msgnum=$(($msgnum + 1))
Junio C Hamano5887ac82006-06-22 01:44:54 -070076 echo "$msgnum" >"$dotest/msgnum"
Eric Wong58634db2006-06-21 03:04:41 -070077}
78
79call_merge () {
Junio C Hamano5887ac82006-06-22 01:44:54 -070080 cmt="$(cat $dotest/cmt.$1)"
Eric Wong58634db2006-06-21 03:04:41 -070081 echo "$cmt" > "$dotest/current"
82 git-merge-$strategy "$cmt^" -- HEAD "$cmt"
83 rv=$?
84 case "$rv" in
85 0)
Eric Wong9e4bc7d2006-06-24 18:29:48 -070086 return
Eric Wong58634db2006-06-21 03:04:41 -070087 ;;
88 1)
89 test -d "$GIT_DIR/rr-cache" && git-rerere
Eric Wong66eb64c2006-06-28 02:11:06 -070090 die "$RESOLVEMSG"
Eric Wong58634db2006-06-21 03:04:41 -070091 ;;
92 2)
93 echo "Strategy: $rv $strategy failed, try another" 1>&2
Eric Wong66eb64c2006-06-28 02:11:06 -070094 die "$RESOLVEMSG"
Eric Wong58634db2006-06-21 03:04:41 -070095 ;;
96 *)
97 die "Unknown exit code ($rv) from command:" \
98 "git-merge-$strategy $cmt^ -- HEAD $cmt"
99 ;;
100 esac
101}
102
103finish_rb_merge () {
Eric Wong58634db2006-06-21 03:04:41 -0700104 rm -r "$dotest"
105 echo "All done."
106}
107
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800108while case "$#" in 0) break ;; esac
109do
110 case "$1" in
sean031321c2006-04-26 10:49:38 -0400111 --continue)
112 diff=$(git-diff-files)
113 case "$diff" in
114 ?*) echo "You must edit all merge conflicts and then"
115 echo "mark them as resolved using git update-index"
116 exit 1
117 ;;
118 esac
Eric Wong58634db2006-06-21 03:04:41 -0700119 if test -d "$dotest"
120 then
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
126 while test "$msgnum" -le "$end"
127 do
128 call_merge "$msgnum"
129 continue_merge
130 done
131 finish_rb_merge
132 exit
133 fi
Seancc120052006-05-13 23:34:08 -0400134 git am --resolved --3way --resolvemsg="$RESOLVEMSG"
135 exit
136 ;;
137 --skip)
Eric Wong58634db2006-06-21 03:04:41 -0700138 if test -d "$dotest"
139 then
Eric Wongd5e673b2006-06-24 18:29:49 -0700140 prev_head="`cat $dotest/prev_head`"
141 end="`cat $dotest/end`"
142 msgnum="`cat $dotest/msgnum`"
143 msgnum=$(($msgnum + 1))
144 onto="`cat $dotest/onto`"
145 while test "$msgnum" -le "$end"
146 do
147 call_merge "$msgnum"
148 continue_merge
149 done
150 finish_rb_merge
151 exit
Eric Wong58634db2006-06-21 03:04:41 -0700152 fi
Seancc120052006-05-13 23:34:08 -0400153 git am -3 --skip --resolvemsg="$RESOLVEMSG"
sean031321c2006-04-26 10:49:38 -0400154 exit
155 ;;
156 --abort)
Eric Wong58634db2006-06-21 03:04:41 -0700157 if test -d "$dotest"
158 then
159 rm -r "$dotest"
160 elif test -d .dotest
161 then
162 rm -r .dotest
163 else
164 die "No rebase in progress?"
165 fi
sean031321c2006-04-26 10:49:38 -0400166 git reset --hard ORIG_HEAD
sean031321c2006-04-26 10:49:38 -0400167 exit
168 ;;
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800169 --onto)
170 test 2 -le "$#" || usage
171 newbase="$2"
172 shift
173 ;;
Eric Wong58634db2006-06-21 03:04:41 -0700174 -M|-m|--m|--me|--mer|--merg|--merge)
175 do_merge=t
176 ;;
177 -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
178 --strateg=*|--strategy=*|\
179 -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
180 case "$#,$1" in
181 *,*=*)
Dennis Stosberg8096fae2006-06-27 18:54:26 +0200182 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
Eric Wong58634db2006-06-21 03:04:41 -0700183 1,*)
184 usage ;;
185 *)
186 strategy="$2"
187 shift ;;
188 esac
189 do_merge=t
190 ;;
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800191 -*)
192 usage
193 ;;
194 *)
195 break
196 ;;
197 esac
198 shift
199done
Junio C Hamano2db8aae2005-12-14 03:11:37 -0800200
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800201# Make sure we do not have .dotest
Eric Wong58634db2006-06-21 03:04:41 -0700202if test -z "$do_merge"
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800203then
Eric Wong58634db2006-06-21 03:04:41 -0700204 if mkdir .dotest
205 then
206 rmdir .dotest
207 else
208 echo >&2 '
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800209It seems that I cannot create a .dotest directory, and I wonder if you
210are in the middle of patch application or another rebase. If that is not
211the case, please rm -fr .dotest and run me again. I am stopping in case
212you still have something valuable there.'
Eric Wong58634db2006-06-21 03:04:41 -0700213 exit 1
214 fi
215else
216 if test -d "$dotest"
217 then
218 die "previous dotest directory $dotest still exists." \
219 'try git-rebase < --continue | --abort >'
220 fi
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800221fi
222
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800223# The tree must be really really clean.
Junio C Hamano215a7ad2005-09-07 17:26:23 -0700224git-update-index --refresh || exit
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800225diff=$(git-diff-index --cached --name-status -r HEAD)
Lukas Sandström32d99542005-12-15 00:36:35 +0100226case "$diff" in
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800227?*) echo "$diff"
228 exit 1
229 ;;
Junio C Hamano59e6b232005-06-25 02:23:43 -0700230esac
231
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800232# The upstream head must be given. Make sure it is valid.
233upstream_name="$1"
234upstream=`git rev-parse --verify "${upstream_name}^0"` ||
Jason Riedyd0080b32006-02-21 12:56:14 -0800235 die "invalid upstream $upstream_name"
Lukas Sandström32d99542005-12-15 00:36:35 +0100236
Junio C Hamano9a111c92006-02-12 23:17:04 -0800237# If a hook exists, give it a chance to interrupt
238if test -x "$GIT_DIR/hooks/pre-rebase"
239then
240 "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
241 echo >&2 "The pre-rebase hook refused to rebase."
242 exit 1
243 }
244fi
245
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800246# If the branch to rebase is given, first switch to it.
247case "$#" in
2482)
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800249 branch_name="$2"
freku045@student.liu.se3ae39ab2005-12-13 23:30:32 +0100250 git-checkout "$2" || usage
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800251 ;;
252*)
253 branch_name=`git symbolic-ref HEAD` || die "No current branch"
Mark Woodingf327dbc2006-04-13 22:01:24 +0000254 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800255 ;;
Junio C Hamano7f59dbb2005-11-14 00:41:53 -0800256esac
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800257branch=$(git-rev-parse --verify "${branch_name}^0") || exit
Junio C Hamano99a92f92005-08-17 15:19:57 -0700258
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800259# Make sure the branch to rebase onto is valid.
260onto_name=${newbase-"$upstream_name"}
261onto=$(git-rev-parse --verify "${onto_name}^0") || exit
Lukas Sandström32d99542005-12-15 00:36:35 +0100262
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800263# Now we are rebasing commits $upstream..$branch on top of $onto
264
265# Check if we are already based on $onto, but this should be
266# done only when upstream and onto are the same.
Junio C Hamanob176e6b2006-04-26 12:07:42 -0700267if test "$upstream" = "$onto"
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800268then
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800269 mb=$(git-merge-base "$onto" "$branch")
270 if test "$mb" = "$onto"
271 then
272 echo >&2 "Current branch $branch_name is up to date."
273 exit 0
274 fi
Junio C Hamano7f4bd5d2005-11-28 13:00:31 -0800275fi
276
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800277# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
278git-reset --hard "$onto"
Lukas Sandström32d99542005-12-15 00:36:35 +0100279
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800280# If the $onto is a proper descendant of the tip of the branch, then
Lukas Sandström32d99542005-12-15 00:36:35 +0100281# we just fast forwarded.
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800282if test "$mb" = "$onto"
Lukas Sandström32d99542005-12-15 00:36:35 +0100283then
Junio C Hamanoe646c9c2006-02-14 14:42:05 -0800284 echo >&2 "Fast-forwarded $branch to $newbase."
Lukas Sandström32d99542005-12-15 00:36:35 +0100285 exit 0
286fi
287
Eric Wong58634db2006-06-21 03:04:41 -0700288if test -z "$do_merge"
289then
290 git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD |
291 git am --binary -3 -k --resolvemsg="$RESOLVEMSG"
292 exit $?
293fi
Seancc120052006-05-13 23:34:08 -0400294
Eric Wong693c15d2006-06-21 03:04:42 -0700295if test "@@NO_PYTHON@@" && test "$strategy" = "recursive"
296then
297 die 'The recursive merge strategy currently relies on Python,
298which this installation of git was not configured with. Please consider
299a different merge strategy (e.g. octopus, resolve, stupid, ours)
300or install Python and git with Python support.'
301
302fi
303
Eric Wong58634db2006-06-21 03:04:41 -0700304# start doing a rebase with git-merge
305# this is rename-aware if the recursive (default) strategy is used
306
307mkdir -p "$dotest"
308echo "$onto" > "$dotest/onto"
309prev_head=`git-rev-parse HEAD^0`
310echo "$prev_head" > "$dotest/prev_head"
311
312msgnum=0
313for cmt in `git-rev-list --no-merges "$upstream"..ORIG_HEAD \
314 | perl -e 'print reverse <>'`
315do
316 msgnum=$(($msgnum + 1))
Junio C Hamano5887ac82006-06-22 01:44:54 -0700317 echo "$cmt" > "$dotest/cmt.$msgnum"
Eric Wong58634db2006-06-21 03:04:41 -0700318done
319
Junio C Hamano5887ac82006-06-22 01:44:54 -0700320echo 1 >"$dotest/msgnum"
321echo $msgnum >"$dotest/end"
Eric Wong58634db2006-06-21 03:04:41 -0700322
323end=$msgnum
324msgnum=1
325
326while test "$msgnum" -le "$end"
327do
328 call_merge "$msgnum"
329 continue_merge
330done
331
332finish_rb_merge