]> git.ipfire.org Git - thirdparty/git.git/blame_incremental - git-rebase.sh
git-rebase: Use --ignore-if-in-upstream option when executing git-format-patch.
[thirdparty/git.git] / git-rebase.sh
... / ...
CommitLineData
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 () {
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?"
52 die "$RESOLVEMSG"
53 fi
54
55 if test -n "`git-diff-index HEAD`"
56 then
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
63 printf "Committed: %0${prec}d" $msgnum
64 else
65 printf "Already applied: %0${prec}d" $msgnum
66 fi
67 echo ' '`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
72 echo "$prev_head" > "$dotest/prev_head"
73
74 # onto the next patch:
75 msgnum=$(($msgnum + 1))
76 echo "$msgnum" >"$dotest/msgnum"
77}
78
79call_merge () {
80 cmt="$(cat $dotest/cmt.$1)"
81 echo "$cmt" > "$dotest/current"
82 git-merge-$strategy "$cmt^" -- HEAD "$cmt"
83 rv=$?
84 case "$rv" in
85 0)
86 return
87 ;;
88 1)
89 test -d "$GIT_DIR/rr-cache" && git-rerere
90 die "$RESOLVEMSG"
91 ;;
92 2)
93 echo "Strategy: $rv $strategy failed, 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 ;;
100 esac
101}
102
103finish_rb_merge () {
104 rm -r "$dotest"
105 echo "All done."
106}
107
108while case "$#" in 0) break ;; esac
109do
110 case "$1" in
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
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
134 git am --resolved --3way --resolvemsg="$RESOLVEMSG" \
135 --reflog-action=rebase
136 exit
137 ;;
138 --skip)
139 if test -d "$dotest"
140 then
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
153 fi
154 git am -3 --skip --resolvemsg="$RESOLVEMSG" \
155 --reflog-action=rebase
156 exit
157 ;;
158 --abort)
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
168 git reset --hard ORIG_HEAD
169 exit
170 ;;
171 --onto)
172 test 2 -le "$#" || usage
173 newbase="$2"
174 shift
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)
182 case "$#,$1" in
183 *,*=*)
184 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
185 1,*)
186 usage ;;
187 *)
188 strategy="$2"
189 shift ;;
190 esac
191 do_merge=t
192 ;;
193 -*)
194 usage
195 ;;
196 *)
197 break
198 ;;
199 esac
200 shift
201done
202
203# Make sure we do not have .dotest
204if test -z "$do_merge"
205then
206 if mkdir .dotest
207 then
208 rmdir .dotest
209 else
210 echo >&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.'
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
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"
230 exit 1
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
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
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.
269mb=$(git-merge-base "$onto" "$branch")
270if test "$upstream" = "$onto" && test "$mb" = "$onto"
271then
272 echo >&2 "Current branch $branch_name is up to date."
273 exit 0
274fi
275
276# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
277git-reset --hard "$onto"
278
279# If the $onto is a proper descendant of the tip of the branch, then
280# we just fast forwarded.
281if test "$mb" = "$branch"
282then
283 echo >&2 "Fast-forwarded $branch_name to $onto_name."
284 exit 0
285fi
286
287if test -z "$do_merge"
288then
289 git-format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD |
290 git am --binary -3 -k --resolvemsg="$RESOLVEMSG" \
291 --reflog-action=rebase
292 exit $?
293fi
294
295if test "@@NO_PYTHON@@" && test "$strategy" = "recursive-old"
296then
297 die 'The recursive-old merge strategy is written in Python,
298which this installation of git was not configured with. Please consider
299a different merge strategy (e.g. recursive, resolve, or stupid)
300or install Python and git with Python support.'
301
302fi
303
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 \
314 | @@PERL@@ -e 'print reverse <>'`
315do
316 msgnum=$(($msgnum + 1))
317 echo "$cmt" > "$dotest/cmt.$msgnum"
318done
319
320echo 1 >"$dotest/msgnum"
321echo $msgnum >"$dotest/end"
322
323end=$msgnum
324msgnum=1
325
326while test "$msgnum" -le "$end"
327do
328 call_merge "$msgnum"
329 continue_merge
330done
331
332finish_rb_merge