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