rebase: operate on a detached HEAD
[git/dkf.git] / git-rebase.sh
blobc02be31f33179dcd87238ec77ad32d572b1da510
1 #!/bin/sh
3 # Copyright (c) 2005 Junio C Hamano.
6 USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]'
7 LONG_USAGE='git-rebase replaces <branch> with a new branch of the
8 same name. When the --onto option is provided the new branch starts
9 out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
10 It then attempts to create a new commit for each commit from the original
11 <branch> that does not exist in the <upstream> branch.
13 It is possible that a merge failure will prevent this process from being
14 completely automatic. You will have to resolve any such merge failure
15 and run git rebase --continue. Another option is to bypass the commit
16 that caused the merge failure with git rebase --skip. To restore the
17 original <branch> and remove the .dotest working files, use the command
18 git rebase --abort instead.
20 Note that if <branch> is not specified on the command line, the
21 currently checked out branch is used. You must be in the top
22 directory of your project to start (or continue) a rebase.
24 Example: git-rebase master~1 topic
26 A---B---C topic A'\''--B'\''--C'\'' topic
27 / --> /
28 D---E---F---G master D---E---F---G master
31 SUBDIRECTORY_OK=Yes
32 . git-sh-setup
33 set_reflog_action rebase
34 require_work_tree
35 cd_to_toplevel
37 RESOLVEMSG="
38 When you have resolved this problem run \"git rebase --continue\".
39 If you would prefer to skip this patch, instead run \"git rebase --skip\".
40 To restore the original branch and stop rebasing run \"git rebase --abort\".
42 unset newbase
43 strategy=recursive
44 do_merge=
45 dotest=$GIT_DIR/.dotest-merge
46 prec=4
47 verbose=
48 git_am_opt=
50 continue_merge () {
51 test -n "$prev_head" || die "prev_head must be defined"
52 test -d "$dotest" || die "$dotest directory does not exist"
54 unmerged=$(git ls-files -u)
55 if test -n "$unmerged"
56 then
57 echo "You still have unmerged paths in your index"
58 echo "did you forget to use git add?"
59 die "$RESOLVEMSG"
62 cmt=`cat "$dotest/current"`
63 if ! git diff-index --quiet HEAD
64 then
65 if ! git-commit -C "$cmt"
66 then
67 echo "Commit failed, please do not call \"git commit\""
68 echo "directly, but instead do one of the following: "
69 die "$RESOLVEMSG"
71 printf "Committed: %0${prec}d " $msgnum
72 else
73 printf "Already applied: %0${prec}d " $msgnum
75 git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
77 prev_head=`git rev-parse HEAD^0`
78 # save the resulting commit so we can read-tree on it later
79 echo "$prev_head" > "$dotest/prev_head"
81 # onto the next patch:
82 msgnum=$(($msgnum + 1))
83 echo "$msgnum" >"$dotest/msgnum"
86 call_merge () {
87 cmt="$(cat "$dotest/cmt.$1")"
88 echo "$cmt" > "$dotest/current"
89 hd=$(git rev-parse --verify HEAD)
90 cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
91 msgnum=$(cat "$dotest/msgnum")
92 end=$(cat "$dotest/end")
93 eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
94 eval GITHEAD_$hd='$(cat "$dotest/onto_name")'
95 export GITHEAD_$cmt GITHEAD_$hd
96 git-merge-$strategy "$cmt^" -- "$hd" "$cmt"
97 rv=$?
98 case "$rv" in
100 unset GITHEAD_$cmt GITHEAD_$hd
101 return
104 git rerere
105 die "$RESOLVEMSG"
108 echo "Strategy: $rv $strategy failed, try another" 1>&2
109 die "$RESOLVEMSG"
112 die "Unknown exit code ($rv) from command:" \
113 "git-merge-$strategy $cmt^ -- HEAD $cmt"
115 esac
118 move_to_original_branch () {
119 test -z "$head_name" &&
120 head_name="$(cat "$dotest"/head-name)" &&
121 onto="$(cat "$dotest"/onto)" &&
122 orig_head="$(cat "$dotest"/orig-head)"
123 case "$head_name" in
124 refs/*)
125 message="rebase finished: $head_name onto $onto"
126 git update-ref -m "$message" \
127 $head_name $(git rev-parse HEAD) $orig_head &&
128 git symbolic-ref HEAD $head_name ||
129 die "Could not move back to $head_name"
131 esac
134 finish_rb_merge () {
135 move_to_original_branch
136 rm -r "$dotest"
137 echo "All done."
140 is_interactive () {
141 test -f "$dotest"/interactive ||
142 while :; do case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac
143 shift
144 done && test -n "$1"
147 is_interactive "$@" && exec git-rebase--interactive "$@"
149 while test $# != 0
151 case "$1" in
152 --continue)
153 git diff-files --quiet || {
154 echo "You must edit all merge conflicts and then"
155 echo "mark them as resolved using git add"
156 exit 1
158 if test -d "$dotest"
159 then
160 prev_head=$(cat "$dotest/prev_head")
161 end=$(cat "$dotest/end")
162 msgnum=$(cat "$dotest/msgnum")
163 onto=$(cat "$dotest/onto")
164 continue_merge
165 while test "$msgnum" -le "$end"
167 call_merge "$msgnum"
168 continue_merge
169 done
170 finish_rb_merge
171 exit
173 git am --resolved --3way --resolvemsg="$RESOLVEMSG"
174 exit
176 --skip)
177 if test -d "$dotest"
178 then
179 git rerere clear
180 prev_head=$(cat "$dotest/prev_head")
181 end=$(cat "$dotest/end")
182 msgnum=$(cat "$dotest/msgnum")
183 msgnum=$(($msgnum + 1))
184 onto=$(cat "$dotest/onto")
185 while test "$msgnum" -le "$end"
187 call_merge "$msgnum"
188 continue_merge
189 done
190 finish_rb_merge
191 exit
193 head_name=$(cat .dotest/head-name) &&
194 onto=$(cat .dotest/onto) &&
195 orig_head=$(cat .dotest/orig-head) &&
196 git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
197 move_to_original_branch
198 exit
200 --abort)
201 git rerere clear
202 if test -d "$dotest"
203 then
204 move_to_original_branch
205 rm -r "$dotest"
206 elif test -d .dotest
207 then
208 dotest=.dotest
209 move_to_original_branch
210 rm -r .dotest
211 else
212 die "No rebase in progress?"
214 git reset --hard ORIG_HEAD
215 exit
217 --onto)
218 test 2 -le "$#" || usage
219 newbase="$2"
220 shift
222 -M|-m|--m|--me|--mer|--merg|--merge)
223 do_merge=t
225 -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
226 --strateg=*|--strategy=*|\
227 -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
228 case "$#,$1" in
229 *,*=*)
230 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
231 1,*)
232 usage ;;
234 strategy="$2"
235 shift ;;
236 esac
237 do_merge=t
239 -v|--verbose)
240 verbose=t
242 --whitespace=*)
243 git_am_opt="$git_am_opt $1"
245 -C*)
246 git_am_opt="$git_am_opt $1"
249 usage
252 break
254 esac
255 shift
256 done
258 # Make sure we do not have .dotest
259 if test -z "$do_merge"
260 then
261 if mkdir .dotest
262 then
263 rmdir .dotest
264 else
265 echo >&2 '
266 It seems that I cannot create a .dotest directory, and I wonder if you
267 are in the middle of patch application or another rebase. If that is not
268 the case, please rm -fr .dotest and run me again. I am stopping in case
269 you still have something valuable there.'
270 exit 1
272 else
273 if test -d "$dotest"
274 then
275 die "previous dotest directory $dotest still exists." \
276 'try git-rebase < --continue | --abort >'
280 # The tree must be really really clean.
281 git update-index --refresh || exit
282 diff=$(git diff-index --cached --name-status -r HEAD)
283 case "$diff" in
284 ?*) echo "cannot rebase: your index is not up-to-date"
285 echo "$diff"
286 exit 1
288 esac
290 # The upstream head must be given. Make sure it is valid.
291 upstream_name="$1"
292 upstream=`git rev-parse --verify "${upstream_name}^0"` ||
293 die "invalid upstream $upstream_name"
295 # Make sure the branch to rebase onto is valid.
296 onto_name=${newbase-"$upstream_name"}
297 onto=$(git rev-parse --verify "${onto_name}^0") || exit
299 # If a hook exists, give it a chance to interrupt
300 if test -x "$GIT_DIR/hooks/pre-rebase"
301 then
302 "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
303 echo >&2 "The pre-rebase hook refused to rebase."
304 exit 1
308 # If the branch to rebase is given, first switch to it.
309 case "$#" in
311 branch_name="$2"
312 git-checkout "$2" || usage
315 if branch_name=`git symbolic-ref -q HEAD`
316 then
317 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
318 else
319 branch_name=HEAD ;# detached
322 esac
323 branch=$(git rev-parse --verify "${branch_name}^0") || exit
325 # Now we are rebasing commits $upstream..$branch on top of $onto
327 # Check if we are already based on $onto with linear history,
328 # but this should be done only when upstream and onto are the same.
329 mb=$(git merge-base "$onto" "$branch")
330 if test "$upstream" = "$onto" && test "$mb" = "$onto" &&
331 # linear history?
332 ! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null
333 then
334 echo >&2 "Current branch $branch_name is up to date."
335 exit 0
338 if test -n "$verbose"
339 then
340 echo "Changes from $mb to $onto:"
341 # We want color (if set), but no pager
342 GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
345 # move to a detached HEAD
346 orig_head=$(git rev-parse HEAD^0)
347 head_name=$(git symbolic-ref HEAD 2> /dev/null)
348 case "$head_name" in
350 head_name="detached HEAD"
353 git checkout "$orig_head" > /dev/null 2>&1 ||
354 die "could not detach HEAD"
356 esac
358 # Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
359 echo "First, rewinding head to replay your work on top of it..."
360 git-reset --hard "$onto"
362 # If the $onto is a proper descendant of the tip of the branch, then
363 # we just fast forwarded.
364 if test "$mb" = "$branch"
365 then
366 echo >&2 "Fast-forwarded $branch_name to $onto_name."
367 move_to_original_branch
368 exit 0
371 if test -z "$do_merge"
372 then
373 git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD |
374 git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" &&
375 move_to_original_branch
376 ret=$?
377 test 0 != $ret -a -d .dotest &&
378 echo $head_name > .dotest/head-name &&
379 echo $onto > .dotest/onto &&
380 echo $orig_head > .dotest/orig-head
381 exit $ret
384 # start doing a rebase with git-merge
385 # this is rename-aware if the recursive (default) strategy is used
387 mkdir -p "$dotest"
388 echo "$onto" > "$dotest/onto"
389 echo "$onto_name" > "$dotest/onto_name"
390 prev_head=$orig_head
391 echo "$prev_head" > "$dotest/prev_head"
392 echo "$orig_head" > "$dotest/orig-head"
393 echo "$head_name" > "$dotest/head-name"
395 msgnum=0
396 for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD`
398 msgnum=$(($msgnum + 1))
399 echo "$cmt" > "$dotest/cmt.$msgnum"
400 done
402 echo 1 >"$dotest/msgnum"
403 echo $msgnum >"$dotest/end"
405 end=$msgnum
406 msgnum=1
408 while test "$msgnum" -le "$end"
410 call_merge "$msgnum"
411 continue_merge
412 done
414 finish_rb_merge