]> git.ipfire.org Git - thirdparty/git.git/blame - git-rebase.sh
Merge branch 'sg/t3420-autostash-fix'
[thirdparty/git.git] / git-rebase.sh
CommitLineData
59e6b23a
JH
1#!/bin/sh
2#
3# Copyright (c) 2005 Junio C Hamano.
4#
5
533b7039 6SUBDIRECTORY_OK=Yes
45e2acf3 7OPTIONS_KEEPDASHDASH=
b6e9e73e 8OPTIONS_STUCKLONG=t
45e2acf3 9OPTIONS_SPEC="\
c2145384 10git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]
0cd993a7 11git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]
82cb775c 12git rebase --continue | --abort | --skip | --edit-todo
45e2acf3
MZ
13--
14 Available options are
15v,verbose! display a diffstat of what changed upstream
16q,quiet! be quiet. implies --no-stat
619e3604 17autostash automatically stash/stash pop before and after
ad8261d2 18fork-point use 'merge-base --fork-point' to refine upstream
45e2acf3 19onto=! rebase onto given branch instead of upstream
7543f6f4 20r,rebase-merges? try to rebase merges instead of skipping them
45e2acf3
MZ
21p,preserve-merges! try to recreate merges instead of ignoring them
22s,strategy=! use the given merge strategy
d4e80629 23X,strategy-option=! pass the argument through to the merge strategy
45e2acf3 24no-ff! cherry-pick all commits, even if unchanged
d4e80629 25f,force-rebase! cherry-pick all commits, even if unchanged
45e2acf3
MZ
26m,merge! use merging strategies to rebase
27i,interactive! let the user edit the list of commits to rebase
c2145384 28x,exec=! add exec lines after each commit of the editable list
90e1818f 29k,keep-empty preserve empty commits during rebase
a6c612b5 30allow-empty-message allow rebasing commits with empty messages
45e2acf3
MZ
31stat! display a diffstat of what changed upstream
32n,no-stat! do not show diffstat of what changed upstream
33verify allow pre-rebase hook to run
34rerere-autoupdate allow rerere to update index with resolved conflicts
35root! rebase all reachable commits up to the root(s)
36autosquash move commits that begin with squash!/fixup! under -i
d4e80629 37signoff add a Signed-off-by: line to each commit
45e2acf3
MZ
38committer-date-is-author-date! passed to 'git am'
39ignore-date! passed to 'git am'
40whitespace=! passed to 'git apply'
41ignore-whitespace! passed to 'git apply'
42C=! passed to 'git apply'
3ee5e540 43S,gpg-sign? GPG-sign commits
45e2acf3 44 Actions:
5960bc9d
MZ
45continue! continue
46abort! abort and check out the original branch
47skip! skip current patch and continue
eb9a7cb4 48edit-todo! edit the todo list during an interactive rebase
9512177b 49quit! abort but keep HEAD where it is
66335298 50show-current-patch! show the patch file being applied or merged
45e2acf3 51"
ae2b0f15 52. git-sh-setup
f9474132 53set_reflog_action rebase
035b5bf6 54require_work_tree_exists
533b7039 55cd_to_toplevel
4282c4fb 56
61dfa1bb
JH
57LF='
58'
6bb4e485
MZ
59ok_to_skip_pre_rebase=
60resolvemsg="
5fdacc17
WD
61$(gettext 'Resolve all conflicts manually, mark them as resolved with
62"git add/rm <conflicted_files>", then run "git rebase --continue".
63You can instead skip this commit: run "git rebase --skip".
64To abort and get back to the state before "git rebase", run "git rebase --abort".')
cc120056 65"
bb2ac4fc 66squash_onto=
6bb4e485 67unset onto
1e0dacdb 68unset restrict_revision
c2145384 69cmd=
9765b6ab 70strategy=
93ce190c 71strategy_opts=
58634dbf 72do_merge=
69a636ad
MZ
73merge_dir="$GIT_DIR"/rebase-merge
74apply_dir="$GIT_DIR"/rebase-apply
b758789c 75verbose=
9474a029
MZ
76diffstat=
77test "$(git config --bool rebase.stat)" = true && diffstat=t
58794775 78autostash="$(git config --bool rebase.autostash || echo false)"
ad8261d2 79fork_point=auto
67dad687 80git_am_opt=
9eaa858e 81git_format_patch_opt=
190f5323 82rebase_root=
b2f82e05 83force_rebase=
cb6020bb 84allow_rerere_autoupdate=
99de0640
MZ
85# Non-empty if a rebase was in progress when 'git rebase' was invoked
86in_progress=
87# One of {am, merge, interactive}
88type=
89# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}
90state_dir=
34262322
MZ
91# One of {'', continue, skip, abort}, as parsed from command line
92action=
8f6aed71 93rebase_merges=
7543f6f4 94rebase_cousins=
cf432ca0
MZ
95preserve_merges=
96autosquash=
90e1818f 97keep_empty=
b00bf1c9 98allow_empty_message=--allow-empty-message
a852ec7f 99signoff=
cf432ca0 100test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
66948561
JH
101case "$(git config --bool commit.gpgsign)" in
102true) gpg_sign_opt=-S ;;
103*) gpg_sign_opt= ;;
104esac
58634dbf 105
fa99c1e1 106read_basic_state () {
dc8ca912
RR
107 test -f "$state_dir/head-name" &&
108 test -f "$state_dir/onto" &&
02ac45fa
MZ
109 head_name=$(cat "$state_dir"/head-name) &&
110 onto=$(cat "$state_dir"/onto) &&
84df4560
MZ
111 # We always write to orig-head, but interactive rebase used to write to
112 # head. Fall back to reading from head to cover for the case that the
113 # user upgraded git with an ongoing interactive rebase.
114 if test -f "$state_dir"/orig-head
2959c283 115 then
2959c283 116 orig_head=$(cat "$state_dir"/orig-head)
84df4560
MZ
117 else
118 orig_head=$(cat "$state_dir"/head)
2959c283 119 fi &&
7b37a7c6
MZ
120 GIT_QUIET=$(cat "$state_dir"/quiet) &&
121 test -f "$state_dir"/verbose && verbose=t
80ff4795
MZ
122 test -f "$state_dir"/strategy && strategy="$(cat "$state_dir"/strategy)"
123 test -f "$state_dir"/strategy_opts &&
124 strategy_opts="$(cat "$state_dir"/strategy_opts)"
b3e4847e
MZ
125 test -f "$state_dir"/allow_rerere_autoupdate &&
126 allow_rerere_autoupdate="$(cat "$state_dir"/allow_rerere_autoupdate)"
3ee5e540
NV
127 test -f "$state_dir"/gpg_sign_opt &&
128 gpg_sign_opt="$(cat "$state_dir"/gpg_sign_opt)"
a852ec7f
PW
129 test -f "$state_dir"/signoff && {
130 signoff="$(cat "$state_dir"/signoff)"
131 force_rebase=t
132 }
02ac45fa
MZ
133}
134
84df4560
MZ
135write_basic_state () {
136 echo "$head_name" > "$state_dir"/head-name &&
137 echo "$onto" > "$state_dir"/onto &&
138 echo "$orig_head" > "$state_dir"/orig-head &&
7b37a7c6
MZ
139 echo "$GIT_QUIET" > "$state_dir"/quiet &&
140 test t = "$verbose" && : > "$state_dir"/verbose
80ff4795
MZ
141 test -n "$strategy" && echo "$strategy" > "$state_dir"/strategy
142 test -n "$strategy_opts" && echo "$strategy_opts" > \
143 "$state_dir"/strategy_opts
b3e4847e
MZ
144 test -n "$allow_rerere_autoupdate" && echo "$allow_rerere_autoupdate" > \
145 "$state_dir"/allow_rerere_autoupdate
3ee5e540 146 test -n "$gpg_sign_opt" && echo "$gpg_sign_opt" > "$state_dir"/gpg_sign_opt
a852ec7f 147 test -n "$signoff" && echo "$signoff" >"$state_dir"/signoff
84df4560
MZ
148}
149
4974c2ca
MZ
150output () {
151 case "$verbose" in
152 '')
153 output=$("$@" 2>&1 )
154 status=$?
155 test $status != 0 && printf "%s\n" "$output"
156 return $status
157 ;;
158 *)
159 "$@"
160 ;;
161 esac
162}
163
6fd2f5e6 164move_to_original_branch () {
6fd2f5e6
JS
165 case "$head_name" in
166 refs/*)
167 message="rebase finished: $head_name onto $onto"
168 git update-ref -m "$message" \
169 $head_name $(git rev-parse HEAD) $orig_head &&
53f2ffa8
JK
170 git symbolic-ref \
171 -m "rebase finished: returning to $head_name" \
172 HEAD $head_name ||
24a6df48 173 die "$(eval_gettext "Could not move back to \$head_name")"
6fd2f5e6
JS
174 ;;
175 esac
176}
177
e4244eb3 178apply_autostash () {
58794775
RR
179 if test -f "$state_dir/autostash"
180 then
181 stash_sha1=$(cat "$state_dir/autostash")
eadf1c8f 182 if git stash apply $stash_sha1 >/dev/null 2>&1
58794775 183 then
cdb866b3 184 echo "$(gettext 'Applied autostash.')" >&2
58794775 185 else
20351bb0
RR
186 git stash store -m "autostash" -q $stash_sha1 ||
187 die "$(eval_gettext "Cannot store \$stash_sha1")"
58794775
RR
188 gettext 'Applying autostash resulted in conflicts.
189Your changes are safe in the stash.
ac1998de 190You can run "git stash pop" or "git stash drop" at any time.
cdb866b3 191' >&2
58794775
RR
192 fi
193 fi
e4244eb3
RR
194}
195
196finish_rebase () {
fbd7a232 197 rm -f "$(git rev-parse --git-path REBASE_HEAD)"
e4244eb3 198 apply_autostash &&
8c24f5b0 199 { git gc --auto || true; } &&
58794775
RR
200 rm -rf "$state_dir"
201}
202
8cd65967 203run_specific_rebase () {
f8cca019
AE
204 if [ "$interactive_rebase" = implied ]; then
205 GIT_EDITOR=:
206 export GIT_EDITOR
8a6dae10 207 autosquash=
f8cca019 208 fi
46df82d5 209 . git-rebase--$type
6d98d0c0
AG
210
211 if test -z "$preserve_merges"
212 then
213 git_rebase__$type
214 else
215 git_rebase__preserve_merges
216 fi
217
f5f758a5
RR
218 ret=$?
219 if test $ret -eq 0
220 then
58794775 221 finish_rebase
e4244eb3
RR
222 elif test $ret -eq 2 # special exit status for rebase -i
223 then
224 apply_autostash &&
225 rm -rf "$state_dir" &&
226 die "Nothing to do"
f5f758a5
RR
227 fi
228 exit $ret
1b1dce4b
JS
229}
230
d70b4a8f 231run_pre_rebase_hook () {
6bb4e485 232 if test -z "$ok_to_skip_pre_rebase" &&
b849b954 233 test -x "$(git rev-parse --git-path hooks/pre-rebase)"
d70b4a8f 234 then
b849b954 235 "$(git rev-parse --git-path hooks/pre-rebase)" ${1+"$@"} ||
c7108bf9 236 die "$(gettext "The pre-rebase hook refused to rebase.")"
d70b4a8f
NS
237 fi
238}
239
69a636ad 240test -f "$apply_dir"/applying &&
82cb775c 241 die "$(gettext "It looks like 'git am' is in progress. Cannot rebase.")"
9b752a6e 242
99de0640
MZ
243if test -d "$apply_dir"
244then
245 type=am
246 state_dir="$apply_dir"
247elif test -d "$merge_dir"
248then
6d98d0c0
AG
249 if test -d "$merge_dir"/rewritten
250 then
251 type=preserve-merges
252 interactive_rebase=explicit
253 preserve_merges=t
254 elif test -f "$merge_dir"/interactive
99de0640
MZ
255 then
256 type=interactive
257 interactive_rebase=explicit
258 else
259 type=merge
260 fi
261 state_dir="$merge_dir"
262fi
263test -n "$type" && in_progress=t
264
95135b06 265total_argc=$#
822f7c73 266while test $# != 0
e646c9c8
JH
267do
268 case "$1" in
c4427656 269 --no-verify)
6bb4e485 270 ok_to_skip_pre_rebase=yes
c4427656 271 ;;
7baf9c4b 272 --verify)
6bb4e485 273 ok_to_skip_pre_rebase=
7baf9c4b 274 ;;
66335298 275 --continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)
45e2acf3 276 test $total_argc -eq 2 || usage
34262322 277 action=${1##--}
031321c6 278 ;;
b6e9e73e
NV
279 --onto=*)
280 onto="${1#--onto=}"
e646c9c8 281 ;;
b6e9e73e
NV
282 --exec=*)
283 cmd="${cmd}exec ${1#--exec=}${LF}"
78ec2400 284 test -z "$interactive_rebase" && interactive_rebase=implied
c2145384 285 ;;
b6e9e73e 286 --interactive)
cf432ca0
MZ
287 interactive_rebase=explicit
288 ;;
b6e9e73e 289 --keep-empty)
90e1818f
NH
290 keep_empty=yes
291 ;;
a6c612b5
GS
292 --allow-empty-message)
293 allow_empty_message=--allow-empty-message
294 ;;
3d946165
PW
295 --no-keep-empty)
296 keep_empty=
297 ;;
8f6aed71
JS
298 --rebase-merges)
299 rebase_merges=t
300 test -z "$interactive_rebase" && interactive_rebase=implied
301 ;;
7543f6f4
JS
302 --rebase-merges=*)
303 rebase_merges=t
304 case "${1#*=}" in
305 rebase-cousins) rebase_cousins=t;;
306 no-rebase-cousins) rebase_cousins=;;
307 *) die "Unknown mode: $1";;
308 esac
309 test -z "$interactive_rebase" && interactive_rebase=implied
310 ;;
b6e9e73e 311 --preserve-merges)
cf432ca0
MZ
312 preserve_merges=t
313 test -z "$interactive_rebase" && interactive_rebase=implied
314 ;;
315 --autosquash)
316 autosquash=t
317 ;;
318 --no-autosquash)
319 autosquash=
320 ;;
ad8261d2
JK
321 --fork-point)
322 fork_point=t
323 ;;
324 --no-fork-point)
325 fork_point=
326 ;;
b6e9e73e 327 --merge)
58634dbf
EW
328 do_merge=t
329 ;;
b6e9e73e 330 --strategy-option=*)
0060041d 331 strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--${1#--strategy-option=}" | sed -e s/^.//)"
93ce190c 332 do_merge=t
9765b6ab 333 test -z "$strategy" && strategy=recursive
93ce190c 334 ;;
b6e9e73e
NV
335 --strategy=*)
336 strategy="${1#--strategy=}"
58634dbf
EW
337 do_merge=t
338 ;;
b6e9e73e 339 --no-stat)
a9c3821c
TAV
340 diffstat=
341 ;;
342 --stat)
343 diffstat=t
344 ;;
58794775
RR
345 --autostash)
346 autostash=true
347 ;;
619e3604
JK
348 --no-autostash)
349 autostash=false
350 ;;
b6e9e73e 351 --verbose)
b758789c 352 verbose=t
a9c3821c 353 diffstat=t
0e987a12
SB
354 GIT_QUIET=
355 ;;
b6e9e73e 356 --quiet)
0e987a12
SB
357 GIT_QUIET=t
358 git_am_opt="$git_am_opt -q"
359 verbose=
360 diffstat=
b758789c 361 ;;
b6e9e73e
NV
362 --whitespace=*)
363 git_am_opt="$git_am_opt --whitespace=${1#--whitespace=}"
364 case "${1#--whitespace=}" in
45e2acf3 365 fix|strip)
b2f82e05
SR
366 force_rebase=t
367 ;;
368 esac
059f446d 369 ;;
86c91f91
GB
370 --ignore-whitespace)
371 git_am_opt="$git_am_opt $1"
372 ;;
a852ec7f
PW
373 --signoff)
374 signoff=--signoff
375 ;;
376 --no-signoff)
377 signoff=
378 ;;
379 --committer-date-is-author-date|--ignore-date)
570ccad3
MB
380 git_am_opt="$git_am_opt $1"
381 force_rebase=t
382 ;;
b6e9e73e
NV
383 -C*)
384 git_am_opt="$git_am_opt $1"
67dad687 385 ;;
190f5323
TR
386 --root)
387 rebase_root=t
388 ;;
b6e9e73e 389 --force-rebase|--no-ff)
b2f82e05
SR
390 force_rebase=t
391 ;;
cb6020bb
JH
392 --rerere-autoupdate|--no-rerere-autoupdate)
393 allow_rerere_autoupdate="$1"
394 ;;
3ee5e540
NV
395 --gpg-sign)
396 gpg_sign_opt=-S
397 ;;
398 --gpg-sign=*)
399 gpg_sign_opt="-S${1#--gpg-sign=}"
400 ;;
45e2acf3
MZ
401 --)
402 shift
e646c9c8
JH
403 break
404 ;;
697bc885
BC
405 *)
406 usage
407 ;;
e646c9c8
JH
408 esac
409 shift
410done
51b2ead0 411test $# -gt 2 && usage
2db8aaec 412
cf432ca0
MZ
413if test -n "$action"
414then
c7108bf9 415 test -z "$in_progress" && die "$(gettext "No rebase in progress?")"
2959c283 416 # Only interactive rebase uses detailed reflog messages
6d98d0c0 417 if test -n "$interactive_rebase" && test "$GIT_REFLOG_ACTION" = rebase
2959c283
MZ
418 then
419 GIT_REFLOG_ACTION="rebase -i ($action)"
420 export GIT_REFLOG_ACTION
421 fi
cf432ca0 422fi
34262322 423
6d98d0c0 424if test "$action" = "edit-todo" && test -z "$interactive_rebase"
eb9a7cb4
AW
425then
426 die "$(gettext "The --edit-todo action can only be used during interactive rebase.")"
427fi
428
34262322
MZ
429case "$action" in
430continue)
2959c283
MZ
431 # Sanity check
432 git rev-parse --verify HEAD >/dev/null ||
c7108bf9 433 die "$(gettext "Cannot read HEAD")"
34262322
MZ
434 git update-index --ignore-submodules --refresh &&
435 git diff-files --quiet --ignore-submodules || {
c7108bf9
JX
436 echo "$(gettext "You must edit all merge conflicts and then
437mark them as resolved using git add")"
34262322
MZ
438 exit 1
439 }
fa99c1e1
MZ
440 read_basic_state
441 run_specific_rebase
34262322
MZ
442 ;;
443skip)
4974c2ca 444 output git reset --hard HEAD || exit $?
fa99c1e1
MZ
445 read_basic_state
446 run_specific_rebase
34262322
MZ
447 ;;
448abort)
449 git rerere clear
fa99c1e1 450 read_basic_state
34262322
MZ
451 case "$head_name" in
452 refs/*)
ea69619c 453 git symbolic-ref -m "rebase: aborting" HEAD $head_name ||
c7108bf9 454 die "$(eval_gettext "Could not move back to \$head_name")"
34262322
MZ
455 ;;
456 esac
4974c2ca 457 output git reset --hard $orig_head
58794775 458 finish_rebase
34262322
MZ
459 exit
460 ;;
9512177b
NTND
461quit)
462 exec rm -rf "$state_dir"
463 ;;
eb9a7cb4
AW
464edit-todo)
465 run_specific_rebase
466 ;;
66335298
NTND
467show-current-patch)
468 run_specific_rebase
469 die "BUG: run_specific_rebase is not supposed to return here"
470 ;;
34262322
MZ
471esac
472
99de0640
MZ
473# Make sure no rebase is in progress
474if test -n "$in_progress"
7f4bd5d8 475then
c7108bf9
JX
476 state_dir_base=${state_dir##*/}
477 cmd_live_rebase="git rebase (--continue | --abort | --skip)"
478 cmd_clear_stale_rebase="rm -fr \"$state_dir\""
479 die "
480$(eval_gettext 'It seems that there is already a $state_dir_base directory, and
e39beac6 481I wonder if you are in the middle of another rebase. If that is the
99de0640 482case, please try
c7108bf9 483 $cmd_live_rebase
99de0640 484If that is not the case, please
c7108bf9 485 $cmd_clear_stale_rebase
9b752a6e 486and run me again. I am stopping in case you still have something
c7108bf9 487valuable there.')"
7f4bd5d8
JH
488fi
489
df5df20c
CW
490if test -n "$rebase_root" && test -z "$onto"
491then
492 test -z "$interactive_rebase" && interactive_rebase=implied
493fi
494
da27a6fb
PW
495if test -n "$keep_empty"
496then
497 test -z "$interactive_rebase" && interactive_rebase=implied
df5df20c
CW
498fi
499
cf432ca0
MZ
500if test -n "$interactive_rebase"
501then
6d98d0c0
AG
502 if test -z "$preserve_merges"
503 then
504 type=interactive
505 else
506 type=preserve-merges
507 fi
508
cf432ca0
MZ
509 state_dir="$merge_dir"
510elif test -n "$do_merge"
511then
512 type=merge
513 state_dir="$merge_dir"
514else
515 type=am
516 state_dir="$apply_dir"
517fi
518
9eaa858e
KW
519if test -t 2 && test -z "$GIT_QUIET"
520then
521 git_format_patch_opt="$git_format_patch_opt --progress"
522fi
523
c840e1af
EN
524if test -n "$git_am_opt"; then
525 incompatible_opts=$(echo " $git_am_opt " | \
526 sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
527 if test -n "$interactive_rebase"
528 then
529 if test -n "$incompatible_opts"
530 then
531 die "$(gettext "error: cannot combine interactive options (--interactive, --exec, --rebase-merges, --preserve-merges, --keep-empty, --root + --onto) with am options ($incompatible_opts)")"
532 fi
533 fi
534 if test -n "$do_merge"; then
535 if test -n "$incompatible_opts"
536 then
537 die "$(gettext "error: cannot combine merge options (--merge, --strategy, --strategy-option) with am options ($incompatible_opts)")"
538 fi
539 fi
540fi
541
a852ec7f
PW
542if test -n "$signoff"
543then
b79966aa
PW
544 test -n "$preserve_merges" &&
545 die "$(gettext "error: cannot combine '--signoff' with '--preserve-merges'")"
a852ec7f
PW
546 git_am_opt="$git_am_opt $signoff"
547 force_rebase=t
548fi
549
c840e1af
EN
550if test -n "$preserve_merges"
551then
552 # Note: incompatibility with --signoff handled in signoff block above
553 # Note: incompatibility with --interactive is just a strong warning;
554 # git-rebase.txt caveats with "unless you know what you are doing"
555 test -n "$rebase_merges" &&
556 die "$(gettext "error: cannot combine '--preserve_merges' with '--rebase-merges'")"
557fi
558
559if test -n "$rebase_merges"
560then
561 test -n "$strategy_opts" &&
562 die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy-option'")"
563 test -n "$strategy" &&
564 die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy'")"
565fi
566
190f5323
TR
567if test -z "$rebase_root"
568then
15a147e6
MZ
569 case "$#" in
570 0)
571 if ! upstream_name=$(git rev-parse --symbolic-full-name \
572 --verify -q @{upstream} 2>/dev/null)
573 then
574 . git-parse-remote
575 error_on_missing_default_upstream "rebase" "rebase" \
c36d8eee 576 "against" "git rebase $(gettext '<branch>')"
15a147e6 577 fi
ad8261d2
JK
578
579 test "$fork_point" = auto && fork_point=t
15a147e6
MZ
580 ;;
581 *) upstream_name="$1"
4f407407
BG
582 if test "$upstream_name" = "-"
583 then
584 upstream_name="@{-1}"
585 fi
15a147e6
MZ
586 shift
587 ;;
588 esac
2e6e276d 589 upstream=$(peel_committish "${upstream_name}") ||
ca7de7b1 590 die "$(eval_gettext "invalid upstream '\$upstream_name'")"
190f5323
TR
591 upstream_arg="$upstream_name"
592else
df5df20c
CW
593 if test -z "$onto"
594 then
728fc79c
EP
595 empty_tree=$(git hash-object -t tree /dev/null)
596 onto=$(git commit-tree $empty_tree </dev/null)
df5df20c
CW
597 squash_onto="$onto"
598 fi
190f5323
TR
599 unset upstream_name
600 unset upstream
f2b6a199 601 test $# -gt 1 && usage
46df82d5 602 upstream_arg=--root
190f5323 603fi
32d99544 604
a1bf91e0 605# Make sure the branch to rebase onto is valid.
6bb4e485 606onto_name=${onto-"$upstream_name"}
9f21e97d
NS
607case "$onto_name" in
608*...*)
609 if left=${onto_name%...*} right=${onto_name#*...} &&
610 onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})
611 then
612 case "$onto" in
613 ?*"$LF"?*)
c7108bf9 614 die "$(eval_gettext "\$onto_name: there are more than one merge bases")"
9f21e97d
NS
615 ;;
616 '')
c7108bf9 617 die "$(eval_gettext "\$onto_name: there is no merge base")"
9f21e97d
NS
618 ;;
619 esac
620 else
c7108bf9 621 die "$(eval_gettext "\$onto_name: there is no merge base")"
9f21e97d
NS
622 fi
623 ;;
624*)
2e6e276d 625 onto=$(peel_committish "$onto_name") ||
c7108bf9 626 die "$(eval_gettext "Does not point to a valid commit: \$onto_name")"
9f21e97d
NS
627 ;;
628esac
a1bf91e0 629
0cb06644 630# If the branch to rebase is given, that is the branch we will rebase
3a9156ad 631# $branch_name -- branch/commit being rebased, or HEAD (already detached)
0cb06644
JH
632# $orig_head -- commit object name of tip of the branch before rebasing
633# $head_name -- refs/heads/<that-branch> or "detached HEAD"
634switch_to=
59e6b23a 635case "$#" in
190f5323 6361)
0cb06644 637 # Is it "rebase other $branchname" or "rebase other $commit"?
190f5323
TR
638 branch_name="$1"
639 switch_to="$1"
0cb06644 640
3a9156ad
KS
641 # Is it a local branch?
642 if git show-ref --verify --quiet -- "refs/heads/$branch_name" &&
643 orig_head=$(git rev-parse -q --verify "refs/heads/$branch_name")
0cb06644 644 then
3a9156ad
KS
645 head_name="refs/heads/$branch_name"
646 # If not is it a valid ref (branch or commit)?
647 elif orig_head=$(git rev-parse -q --verify "$branch_name")
0cb06644
JH
648 then
649 head_name="detached HEAD"
3a9156ad 650
0cb06644 651 else
ca7de7b1 652 die "$(eval_gettext "fatal: no such branch/commit '\$branch_name'")"
0cb06644 653 fi
e646c9c8 654 ;;
f2b6a199 6550)
0cb06644 656 # Do not need to switch branches, we are already on it.
728fc79c 657 if branch_name=$(git symbolic-ref -q HEAD)
bcf31618 658 then
0cb06644 659 head_name=$branch_name
728fc79c 660 branch_name=$(expr "z$branch_name" : 'zrefs/heads/\(.*\)')
bcf31618 661 else
0cb06644 662 head_name="detached HEAD"
3a9156ad 663 branch_name=HEAD
bcf31618 664 fi
ea709800 665 orig_head=$(git rev-parse --verify HEAD) || exit
e646c9c8 666 ;;
f2b6a199
MZ
667*)
668 die "BUG: unexpected number of arguments left to parse"
669 ;;
59e6b23a
JH
670esac
671
ad8261d2
JK
672if test "$fork_point" = t
673then
bb3f4583
JK
674 new_upstream=$(git merge-base --fork-point "$upstream_name" \
675 "${switch_to:-HEAD}")
ad8261d2
JK
676 if test -n "$new_upstream"
677 then
1e0dacdb 678 restrict_revision=$new_upstream
ad8261d2
JK
679 fi
680fi
681
58794775
RR
682if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
683then
684 stash_sha1=$(git stash create "autostash") ||
685 die "$(gettext 'Cannot autostash')"
686
687 mkdir -p "$state_dir" &&
688 echo $stash_sha1 >"$state_dir/autostash" &&
689 stash_abbrev=$(git rev-parse --short $stash_sha1) &&
690 echo "$(eval_gettext 'Created autostash: $stash_abbrev')" &&
691 git reset --hard
692fi
693
c7108bf9 694require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")"
8f9bfb64 695
cb82a05d
MZ
696# Now we are rebasing commits $upstream..$orig_head (or with --root,
697# everything leading up to $orig_head) on top of $onto
e646c9c8 698
1308c17b 699# Check if we are already based on $onto with linear history,
cc1453e1
MZ
700# but this should be done only when upstream and onto are the same
701# and if this is not an interactive rebase.
cb82a05d 702mb=$(git merge-base "$onto" "$orig_head")
6d98d0c0 703if test -z "$interactive_rebase" && test "$upstream" = "$onto" &&
1e0dacdb 704 test "$mb" = "$onto" && test -z "$restrict_revision" &&
1308c17b 705 # linear history?
cb82a05d 706 ! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
7f4bd5d8 707then
b2f82e05
SR
708 if test -z "$force_rebase"
709 then
710 # Lazily switch to the target branch if needed...
4b03df21
RR
711 test -z "$switch_to" ||
712 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" \
22946a94 713 git checkout -q "$switch_to" --
08e66700
KS
714 if test "$branch_name" = "HEAD" &&
715 ! git symbolic-ref -q HEAD
716 then
717 say "$(eval_gettext "HEAD is up to date.")"
718 else
719 say "$(eval_gettext "Current branch \$branch_name is up to date.")"
720 fi
96e2b99e 721 finish_rebase
b2f82e05
SR
722 exit 0
723 else
08e66700
KS
724 if test "$branch_name" = "HEAD" &&
725 ! git symbolic-ref -q HEAD
726 then
727 say "$(eval_gettext "HEAD is up to date, rebase forced.")"
728 else
729 say "$(eval_gettext "Current branch \$branch_name is up to date, rebase forced.")"
730 fi
b2f82e05 731 fi
7f4bd5d8
JH
732fi
733
8f9bfb64
MZ
734# If a hook exists, give it a chance to interrupt
735run_pre_rebase_hook "$upstream_arg" "$@"
736
a9c3821c
TAV
737if test -n "$diffstat"
738then
739 if test -n "$verbose"
740 then
c7108bf9 741 echo "$(eval_gettext "Changes from \$mb to \$onto:")"
a9c3821c
TAV
742 fi
743 # We want color (if set), but no pager
744 GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
745fi
746
6d98d0c0 747test -n "$interactive_rebase" && run_specific_rebase
f4107d9c
MZ
748
749# Detach HEAD and reset the tree
c7108bf9 750say "$(gettext "First, rewinding head to replay your work on top of it...")"
4b03df21
RR
751
752GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
753 git checkout -q "$onto^0" || die "could not detach HEAD"
cb82a05d 754git update-ref ORIG_HEAD $orig_head
f4107d9c 755
e646c9c8 756# If the $onto is a proper descendant of the tip of the branch, then
a75d7b54 757# we just fast-forwarded.
cb82a05d 758if test "$mb" = "$orig_head"
32d99544 759then
c7108bf9 760 say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
6fd2f5e6 761 move_to_original_branch
af2f0ebc 762 finish_rebase
32d99544
LS
763 exit 0
764fi
765
190f5323
TR
766if test -n "$rebase_root"
767then
768 revisions="$onto..$orig_head"
769else
1e0dacdb 770 revisions="${restrict_revision-$upstream}..$orig_head"
190f5323
TR
771fi
772
fa99c1e1 773run_specific_rebase