]> git.ipfire.org Git - thirdparty/git.git/blame - git-rebase.sh
builtin-mv: fix use of uninitialized memory.
[thirdparty/git.git] / git-rebase.sh
CommitLineData
59e6b23a
JH
1#!/bin/sh
2#
3# Copyright (c) 2005 Junio C Hamano.
4#
5
e646c9c8 6USAGE='[--onto <newbase>] <upstream> [<branch>]'
031321c6
SE
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.
69a60af5 12
031321c6
SE
13It is possible that a merge failure will prevent this process from being
14completely automatic. You will have to resolve any such merge failure
cc120056
SE
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.
69a60af5 19
031321c6
SE
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.
e646c9c8 23
031321c6 24Example: git-rebase master~1 topic
e646c9c8 25
031321c6
SE
26 A---B---C topic A'\''--B'\''--C'\'' topic
27 / --> /
28 D---E---F---G master D---E---F---G master
e646c9c8 29'
ae2b0f15 30. git-sh-setup
4282c4fb 31
cc120056
SE
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"
e646c9c8 37unset newbase
58634dbf
EW
38strategy=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?"
66eb64cb 52 die "$RESOLVEMSG"
58634dbf
EW
53 fi
54
55 if test -n "`git-diff-index HEAD`"
56 then
f0ef0596
EW
57 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
9e4bc7dd 63 printf "Committed: %0${prec}d" $msgnum
58634dbf 64 else
9e4bc7dd 65 printf "Already applied: %0${prec}d" $msgnum
58634dbf 66 fi
9e4bc7dd
EW
67 echo ' '`git-rev-list --pretty=oneline -1 HEAD | \
68 sed 's/^[a-f0-9]\+ //'`
58634dbf
EW
69
70 prev_head=`git-rev-parse HEAD^0`
58634dbf 71 # save the resulting commit so we can read-tree on it later
58634dbf
EW
72 echo "$prev_head" > "$dotest/prev_head"
73
74 # onto the next patch:
75 msgnum=$(($msgnum + 1))
5887ac82 76 echo "$msgnum" >"$dotest/msgnum"
58634dbf
EW
77}
78
79call_merge () {
5887ac82 80 cmt="$(cat $dotest/cmt.$1)"
58634dbf
EW
81 echo "$cmt" > "$dotest/current"
82 git-merge-$strategy "$cmt^" -- HEAD "$cmt"
83 rv=$?
84 case "$rv" in
85 0)
9e4bc7dd 86 return
58634dbf
EW
87 ;;
88 1)
89 test -d "$GIT_DIR/rr-cache" && git-rerere
66eb64cb 90 die "$RESOLVEMSG"
58634dbf
EW
91 ;;
92 2)
93 echo "Strategy: $rv $strategy failed, try another" 1>&2
66eb64cb 94 die "$RESOLVEMSG"
58634dbf
EW
95 ;;
96 *)
97 die "Unknown exit code ($rv) from command:" \
98 "git-merge-$strategy $cmt^ -- HEAD $cmt"
99 ;;
100 esac
101}
102
103finish_rb_merge () {
58634dbf
EW
104 rm -r "$dotest"
105 echo "All done."
106}
107
e646c9c8
JH
108while case "$#" in 0) break ;; esac
109do
110 case "$1" in
031321c6
SE
111 --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
58634dbf
EW
119 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
8ef1c7c7
SP
134 git am --resolved --3way --resolvemsg="$RESOLVEMSG" \
135 --reflog-action=rebase
cc120056
SE
136 exit
137 ;;
138 --skip)
58634dbf
EW
139 if test -d "$dotest"
140 then
d5e673b6
EW
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`"
146 while test "$msgnum" -le "$end"
147 do
148 call_merge "$msgnum"
149 continue_merge
150 done
151 finish_rb_merge
152 exit
58634dbf 153 fi
8ef1c7c7
SP
154 git am -3 --skip --resolvemsg="$RESOLVEMSG" \
155 --reflog-action=rebase
031321c6
SE
156 exit
157 ;;
158 --abort)
58634dbf
EW
159 if test -d "$dotest"
160 then
161 rm -r "$dotest"
162 elif test -d .dotest
163 then
164 rm -r .dotest
165 else
166 die "No rebase in progress?"
167 fi
031321c6 168 git reset --hard ORIG_HEAD
031321c6
SE
169 exit
170 ;;
e646c9c8
JH
171 --onto)
172 test 2 -le "$#" || usage
173 newbase="$2"
174 shift
175 ;;
58634dbf
EW
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)
182 case "$#,$1" in
183 *,*=*)
8096fae7 184 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
58634dbf
EW
185 1,*)
186 usage ;;
187 *)
188 strategy="$2"
189 shift ;;
190 esac
191 do_merge=t
192 ;;
e646c9c8
JH
193 -*)
194 usage
195 ;;
196 *)
197 break
198 ;;
199 esac
200 shift
201done
2db8aaec 202
7f4bd5d8 203# Make sure we do not have .dotest
58634dbf 204if test -z "$do_merge"
7f4bd5d8 205then
58634dbf
EW
206 if mkdir .dotest
207 then
208 rmdir .dotest
209 else
210 echo >&2 '
7f4bd5d8
JH
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.'
58634dbf
EW
215 exit 1
216 fi
217else
218 if test -d "$dotest"
219 then
220 die "previous dotest directory $dotest still exists." \
221 'try git-rebase < --continue | --abort >'
222 fi
7f4bd5d8
JH
223fi
224
7f59dbbb 225# The tree must be really really clean.
215a7ad1 226git-update-index --refresh || exit
7f59dbbb 227diff=$(git-diff-index --cached --name-status -r HEAD)
32d99544 228case "$diff" in
7f59dbbb
JH
229?*) echo "$diff"
230 exit 1
231 ;;
232esac
99a92f92 233
e646c9c8
JH
234# The upstream head must be given. Make sure it is valid.
235upstream_name="$1"
236upstream=`git rev-parse --verify "${upstream_name}^0"` ||
d0080b3c 237 die "invalid upstream $upstream_name"
32d99544 238
9a111c91
JH
239# If a hook exists, give it a chance to interrupt
240if test -x "$GIT_DIR/hooks/pre-rebase"
241then
242 "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
243 echo >&2 "The pre-rebase hook refused to rebase."
244 exit 1
245 }
246fi
247
7f59dbbb 248# If the branch to rebase is given, first switch to it.
59e6b23a 249case "$#" in
7f59dbbb 2502)
e646c9c8 251 branch_name="$2"
3ae39ab2 252 git-checkout "$2" || usage
e646c9c8
JH
253 ;;
254*)
255 branch_name=`git symbolic-ref HEAD` || die "No current branch"
f327dbce 256 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
e646c9c8 257 ;;
59e6b23a 258esac
e646c9c8 259branch=$(git-rev-parse --verify "${branch_name}^0") || exit
59e6b23a 260
e646c9c8
JH
261# Make sure the branch to rebase onto is valid.
262onto_name=${newbase-"$upstream_name"}
263onto=$(git-rev-parse --verify "${onto_name}^0") || exit
32d99544 264
e646c9c8
JH
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.
83c31614
RS
269mb=$(git-merge-base "$onto" "$branch")
270if test "$upstream" = "$onto" && test "$mb" = "$onto"
7f4bd5d8 271then
83c31614
RS
272 echo >&2 "Current branch $branch_name is up to date."
273 exit 0
7f4bd5d8
JH
274fi
275
e646c9c8
JH
276# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
277git-reset --hard "$onto"
32d99544 278
e646c9c8 279# If the $onto is a proper descendant of the tip of the branch, then
32d99544 280# we just fast forwarded.
83c31614 281if test "$mb" = "$branch"
32d99544 282then
d587ed13 283 echo >&2 "Fast-forwarded $branch_name to $onto_name."
32d99544
LS
284 exit 0
285fi
286
58634dbf
EW
287if test -z "$do_merge"
288then
289 git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD |
8ef1c7c7
SP
290 git am --binary -3 -k --resolvemsg="$RESOLVEMSG" \
291 --reflog-action=rebase
58634dbf
EW
292 exit $?
293fi
294
693c15dc
EW
295if 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
58634dbf
EW
304# 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 \
d9bffc08 314 | @@PERL@@ -e 'print reverse <>'`
58634dbf
EW
315do
316 msgnum=$(($msgnum + 1))
5887ac82 317 echo "$cmt" > "$dotest/cmt.$msgnum"
58634dbf
EW
318done
319
5887ac82
JH
320echo 1 >"$dotest/msgnum"
321echo $msgnum >"$dotest/end"
58634dbf
EW
322
323end=$msgnum
324msgnum=1
325
326while test "$msgnum" -le "$end"
327do
328 call_merge "$msgnum"
329 continue_merge
330done
cc120056 331
58634dbf 332finish_rb_merge