]> git.ipfire.org Git - thirdparty/git.git/blame - git-rebase.sh
t5318: avoid unnecessary command substitutions
[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
23no-ff! cherry-pick all commits, even if unchanged
24m,merge! use merging strategies to rebase
25i,interactive! let the user edit the list of commits to rebase
c2145384 26x,exec=! add exec lines after each commit of the editable list
90e1818f 27k,keep-empty preserve empty commits during rebase
a6c612b5 28allow-empty-message allow rebasing commits with empty messages
45e2acf3
MZ
29f,force-rebase! force rebase even if branch is up to date
30X,strategy-option=! pass the argument through to the merge strategy
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
37committer-date-is-author-date! passed to 'git am'
38ignore-date! passed to 'git am'
9f79524a 39signoff passed to 'git am'
45e2acf3
MZ
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=
a6c612b5 98allow_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
NV
330 --strategy-option=*)
331 strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--${1#--strategy-option=}")"
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
a852ec7f
PW
524if test -n "$signoff"
525then
b79966aa
PW
526 test -n "$preserve_merges" &&
527 die "$(gettext "error: cannot combine '--signoff' with '--preserve-merges'")"
a852ec7f
PW
528 git_am_opt="$git_am_opt $signoff"
529 force_rebase=t
530fi
531
190f5323
TR
532if test -z "$rebase_root"
533then
15a147e6
MZ
534 case "$#" in
535 0)
536 if ! upstream_name=$(git rev-parse --symbolic-full-name \
537 --verify -q @{upstream} 2>/dev/null)
538 then
539 . git-parse-remote
540 error_on_missing_default_upstream "rebase" "rebase" \
c36d8eee 541 "against" "git rebase $(gettext '<branch>')"
15a147e6 542 fi
ad8261d2
JK
543
544 test "$fork_point" = auto && fork_point=t
15a147e6
MZ
545 ;;
546 *) upstream_name="$1"
4f407407
BG
547 if test "$upstream_name" = "-"
548 then
549 upstream_name="@{-1}"
550 fi
15a147e6
MZ
551 shift
552 ;;
553 esac
2e6e276d 554 upstream=$(peel_committish "${upstream_name}") ||
ca7de7b1 555 die "$(eval_gettext "invalid upstream '\$upstream_name'")"
190f5323
TR
556 upstream_arg="$upstream_name"
557else
df5df20c
CW
558 if test -z "$onto"
559 then
728fc79c
EP
560 empty_tree=$(git hash-object -t tree /dev/null)
561 onto=$(git commit-tree $empty_tree </dev/null)
df5df20c
CW
562 squash_onto="$onto"
563 fi
190f5323
TR
564 unset upstream_name
565 unset upstream
f2b6a199 566 test $# -gt 1 && usage
46df82d5 567 upstream_arg=--root
190f5323 568fi
32d99544 569
a1bf91e0 570# Make sure the branch to rebase onto is valid.
6bb4e485 571onto_name=${onto-"$upstream_name"}
9f21e97d
NS
572case "$onto_name" in
573*...*)
574 if left=${onto_name%...*} right=${onto_name#*...} &&
575 onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})
576 then
577 case "$onto" in
578 ?*"$LF"?*)
c7108bf9 579 die "$(eval_gettext "\$onto_name: there are more than one merge bases")"
9f21e97d
NS
580 ;;
581 '')
c7108bf9 582 die "$(eval_gettext "\$onto_name: there is no merge base")"
9f21e97d
NS
583 ;;
584 esac
585 else
c7108bf9 586 die "$(eval_gettext "\$onto_name: there is no merge base")"
9f21e97d
NS
587 fi
588 ;;
589*)
2e6e276d 590 onto=$(peel_committish "$onto_name") ||
c7108bf9 591 die "$(eval_gettext "Does not point to a valid commit: \$onto_name")"
9f21e97d
NS
592 ;;
593esac
a1bf91e0 594
0cb06644 595# If the branch to rebase is given, that is the branch we will rebase
3a9156ad 596# $branch_name -- branch/commit being rebased, or HEAD (already detached)
0cb06644
JH
597# $orig_head -- commit object name of tip of the branch before rebasing
598# $head_name -- refs/heads/<that-branch> or "detached HEAD"
599switch_to=
59e6b23a 600case "$#" in
190f5323 6011)
0cb06644 602 # Is it "rebase other $branchname" or "rebase other $commit"?
190f5323
TR
603 branch_name="$1"
604 switch_to="$1"
0cb06644 605
3a9156ad
KS
606 # Is it a local branch?
607 if git show-ref --verify --quiet -- "refs/heads/$branch_name" &&
608 orig_head=$(git rev-parse -q --verify "refs/heads/$branch_name")
0cb06644 609 then
3a9156ad
KS
610 head_name="refs/heads/$branch_name"
611 # If not is it a valid ref (branch or commit)?
612 elif orig_head=$(git rev-parse -q --verify "$branch_name")
0cb06644
JH
613 then
614 head_name="detached HEAD"
3a9156ad 615
0cb06644 616 else
ca7de7b1 617 die "$(eval_gettext "fatal: no such branch/commit '\$branch_name'")"
0cb06644 618 fi
e646c9c8 619 ;;
f2b6a199 6200)
0cb06644 621 # Do not need to switch branches, we are already on it.
728fc79c 622 if branch_name=$(git symbolic-ref -q HEAD)
bcf31618 623 then
0cb06644 624 head_name=$branch_name
728fc79c 625 branch_name=$(expr "z$branch_name" : 'zrefs/heads/\(.*\)')
bcf31618 626 else
0cb06644 627 head_name="detached HEAD"
3a9156ad 628 branch_name=HEAD
bcf31618 629 fi
ea709800 630 orig_head=$(git rev-parse --verify HEAD) || exit
e646c9c8 631 ;;
f2b6a199
MZ
632*)
633 die "BUG: unexpected number of arguments left to parse"
634 ;;
59e6b23a
JH
635esac
636
ad8261d2
JK
637if test "$fork_point" = t
638then
bb3f4583
JK
639 new_upstream=$(git merge-base --fork-point "$upstream_name" \
640 "${switch_to:-HEAD}")
ad8261d2
JK
641 if test -n "$new_upstream"
642 then
1e0dacdb 643 restrict_revision=$new_upstream
ad8261d2
JK
644 fi
645fi
646
58794775
RR
647if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
648then
649 stash_sha1=$(git stash create "autostash") ||
650 die "$(gettext 'Cannot autostash')"
651
652 mkdir -p "$state_dir" &&
653 echo $stash_sha1 >"$state_dir/autostash" &&
654 stash_abbrev=$(git rev-parse --short $stash_sha1) &&
655 echo "$(eval_gettext 'Created autostash: $stash_abbrev')" &&
656 git reset --hard
657fi
658
c7108bf9 659require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")"
8f9bfb64 660
cb82a05d
MZ
661# Now we are rebasing commits $upstream..$orig_head (or with --root,
662# everything leading up to $orig_head) on top of $onto
e646c9c8 663
1308c17b 664# Check if we are already based on $onto with linear history,
cc1453e1
MZ
665# but this should be done only when upstream and onto are the same
666# and if this is not an interactive rebase.
cb82a05d 667mb=$(git merge-base "$onto" "$orig_head")
6d98d0c0 668if test -z "$interactive_rebase" && test "$upstream" = "$onto" &&
1e0dacdb 669 test "$mb" = "$onto" && test -z "$restrict_revision" &&
1308c17b 670 # linear history?
cb82a05d 671 ! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
7f4bd5d8 672then
b2f82e05
SR
673 if test -z "$force_rebase"
674 then
675 # Lazily switch to the target branch if needed...
4b03df21
RR
676 test -z "$switch_to" ||
677 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" \
22946a94 678 git checkout -q "$switch_to" --
08e66700
KS
679 if test "$branch_name" = "HEAD" &&
680 ! git symbolic-ref -q HEAD
681 then
682 say "$(eval_gettext "HEAD is up to date.")"
683 else
684 say "$(eval_gettext "Current branch \$branch_name is up to date.")"
685 fi
96e2b99e 686 finish_rebase
b2f82e05
SR
687 exit 0
688 else
08e66700
KS
689 if test "$branch_name" = "HEAD" &&
690 ! git symbolic-ref -q HEAD
691 then
692 say "$(eval_gettext "HEAD is up to date, rebase forced.")"
693 else
694 say "$(eval_gettext "Current branch \$branch_name is up to date, rebase forced.")"
695 fi
b2f82e05 696 fi
7f4bd5d8
JH
697fi
698
8f9bfb64
MZ
699# If a hook exists, give it a chance to interrupt
700run_pre_rebase_hook "$upstream_arg" "$@"
701
a9c3821c
TAV
702if test -n "$diffstat"
703then
704 if test -n "$verbose"
705 then
c7108bf9 706 echo "$(eval_gettext "Changes from \$mb to \$onto:")"
a9c3821c
TAV
707 fi
708 # We want color (if set), but no pager
709 GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
710fi
711
6d98d0c0 712test -n "$interactive_rebase" && run_specific_rebase
f4107d9c
MZ
713
714# Detach HEAD and reset the tree
c7108bf9 715say "$(gettext "First, rewinding head to replay your work on top of it...")"
4b03df21
RR
716
717GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
718 git checkout -q "$onto^0" || die "could not detach HEAD"
cb82a05d 719git update-ref ORIG_HEAD $orig_head
f4107d9c 720
e646c9c8 721# If the $onto is a proper descendant of the tip of the branch, then
a75d7b54 722# we just fast-forwarded.
cb82a05d 723if test "$mb" = "$orig_head"
32d99544 724then
c7108bf9 725 say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
6fd2f5e6 726 move_to_original_branch
af2f0ebc 727 finish_rebase
32d99544
LS
728 exit 0
729fi
730
190f5323
TR
731if test -n "$rebase_root"
732then
733 revisions="$onto..$orig_head"
734else
1e0dacdb 735 revisions="${restrict_revision-$upstream}..$orig_head"
190f5323
TR
736fi
737
fa99c1e1 738run_specific_rebase