]> git.ipfire.org Git - thirdparty/git.git/blame - git-rebase--interactive.sh
l10n: zh_CN: review for git 2.18.0
[thirdparty/git.git] / git-rebase--interactive.sh
CommitLineData
11d62145
JN
1# This shell script fragment is sourced by git-rebase to implement
2# its interactive mode. "git rebase --interactive" makes it easy
3# to fix up commits in the middle of a series and rearrange commits.
1b1dce4b
JS
4#
5# Copyright (c) 2006 Johannes E. Schindelin
1b1dce4b
JS
6#
7# The original idea comes from Eric W. Biederman, in
5840eb9d 8# https://public-inbox.org/git/m1odwkyuf5.fsf_-_@ebiederm.dsl.xmission.com/
572a7c52 9#
80883bb3
MH
10# The file containing rebase commands, comments, and empty lines.
11# This file is created by "git rebase -i" then edited by the user. As
12# the lines are processed, they are removed from the front of this
6bb4e485 13# file and written to the tail of $done.
431b7e78 14todo="$state_dir"/git-rebase-todo
80883bb3
MH
15
16# The rebase command lines that have already been processed. A line
17# is moved here when it is first handled, before any associated user
18# actions.
431b7e78 19done="$state_dir"/done
80883bb3
MH
20
21# The commit message that is planned to be used for any changes that
22# need to be committed following a user interaction.
431b7e78 23msg="$state_dir"/message
80883bb3
MH
24
25# The file into which is accumulated the suggested commit message for
26# squash/fixup commands. When the first of a series of squash/fixups
27# is seen, the file is created and the commit message from the
28# previous commit and from the first squash/fixup commit are written
29# to it. The commit message for each subsequent squash/fixup commit
30# is appended to the file as it is processed.
31#
32# The first line of the file is of the form
6bb4e485
MZ
33# # This is a combination of $count commits.
34# where $count is the number of commits whose messages have been
80883bb3
MH
35# written to the file so far (including the initial "pick" commit).
36# Each time that a commit message is processed, this line is read and
37# updated. It is deleted just before the combined commit is made.
431b7e78 38squash_msg="$state_dir"/message-squash
80883bb3 39
a25eb139
MH
40# If the current series of squash/fixups has not yet included a squash
41# command, then this file exists and holds the commit message of the
42# original "pick" commit. (If the series ends without a "squash"
43# command, then this can be used as the commit message of the combined
44# commit without opening the editor.)
431b7e78 45fixup_msg="$state_dir"/message-fixup
a25eb139 46
6bb4e485
MZ
47# $rewritten is the name of a directory containing files for each
48# commit that is reachable by at least one merge base of $head and
49# $upstream. They are not necessarily rewritten, but their children
80883bb3
MH
50# might be. This ensures that commits on merged, but otherwise
51# unrelated side branches are left alone. (Think "X" in the man page's
52# example.)
431b7e78 53rewritten="$state_dir"/rewritten
80883bb3 54
431b7e78 55dropped="$state_dir"/dropped
0aac0de4 56
b71dc3e1
ZK
57end="$state_dir"/end
58msgnum="$state_dir"/msgnum
59
0aac0de4
MH
60# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
61# GIT_AUTHOR_DATE that will be used for the commit that is currently
62# being rebased.
431b7e78 63author_script="$state_dir"/author-script
0aac0de4 64
a4049ae7
MH
65# When an "edit" rebase command is being processed, the SHA1 of the
66# commit to be edited is recorded in this file. When "git rebase
67# --continue" is executed, if there are any staged changes then they
68# will be amended to the HEAD commit, but only provided the HEAD
69# commit is still the commit to be edited. When any other rebase
70# command is processed, this file is deleted.
431b7e78 71amend="$state_dir"/amend
a4049ae7 72
b079feed
TR
73# For the post-rewrite hook, we make a list of rewritten commits and
74# their new sha1s. The rewritten-pending list keeps the sha1s of
75# commits that have been processed, but not committed yet,
76# e.g. because they are waiting for a 'squash' command.
431b7e78
MZ
77rewritten_list="$state_dir"/rewritten-list
78rewritten_pending="$state_dir"/rewritten-pending
6bb4e485 79
39743cf5
JH
80# Work around Git for Windows' Bash whose "read" does not strip CRLF
81# and leaves CR at the end instead.
82cr=$(printf "\015")
83
03a7f388 84empty_tree=$(git hash-object -t tree /dev/null)
85
040fd39e 86strategy_args=${strategy:+--strategy=$strategy}
8e98b35f 87test -n "$strategy_opts" &&
040fd39e
FR
88eval '
89 for strategy_opt in '"$strategy_opts"'
90 do
91 strategy_args="$strategy_args -X$(git rev-parse --sq-quote "${strategy_opt#--}")"
92 done
93'
db2b3b82 94
89c7ae9c 95GIT_CHERRY_PICK_HELP="$resolvemsg"
804c7174
WC
96export GIT_CHERRY_PICK_HELP
97
882cd237
JS
98comment_char=$(git config --get core.commentchar 2>/dev/null)
99case "$comment_char" in
100'' | auto)
101 comment_char="#"
102 ;;
103?)
104 ;;
105*)
106 comment_char=$(echo "$comment_char" | cut -c1)
107 ;;
108esac
180bad3d 109
1b1dce4b 110warn () {
938791cd 111 printf '%s\n' "$*" >&2
1b1dce4b
JS
112}
113
ee0a4afb
MH
114# Output the commit message for the specified commit.
115commit_message () {
116 git cat-file commit "$1" | sed "1,/^$/d"
117}
118
6bb4e485 119orig_reflog_action="$GIT_REFLOG_ACTION"
1b1dce4b
JS
120
121comment_for_reflog () {
6bb4e485 122 case "$orig_reflog_action" in
1b1dce4b
JS
123 ''|rebase*)
124 GIT_REFLOG_ACTION="rebase -i ($1)"
125 export GIT_REFLOG_ACTION
376ccb8c 126 ;;
1b1dce4b
JS
127 esac
128}
129
4e673877 130last_count=
1b1dce4b 131mark_action_done () {
6bb4e485
MZ
132 sed -e 1q < "$todo" >> "$done"
133 sed -e 1d < "$todo" >> "$todo".new
134 mv -f "$todo".new "$todo"
d9497518 135 new_count=$(( $(git stripspace --strip-comments <"$done" | wc -l) ))
b71dc3e1 136 echo $new_count >"$msgnum"
180bad3d 137 total=$(($new_count + $(git stripspace --strip-comments <"$todo" | wc -l)))
b71dc3e1 138 echo $total >"$end"
6bb4e485 139 if test "$last_count" != "$new_count"
4e673877 140 then
6bb4e485 141 last_count=$new_count
9588c52b 142 eval_gettext "Rebasing (\$new_count/\$total)"; printf "\r"
6bb4e485 143 test -z "$verbose" || echo
4e673877 144 fi
1b1dce4b
JS
145}
146
8cbc57ca
PH
147# Put the last action marked done at the beginning of the todo list
148# again. If there has not been an action marked done yet, leave the list of
149# items on the todo list unchanged.
150reschedule_last_action () {
151 tail -n 1 "$done" | cat - "$todo" >"$todo".new
152 sed -e \$d <"$done" >"$done".new
153 mv -f "$todo".new "$todo"
154 mv -f "$done".new "$done"
155}
156
fcc5ef1c 157append_todo_help () {
b8fc9e43 158 gettext "
180bad3d 159Commands:
f431d73d
SB
160p, pick <commit> = use commit
161r, reword <commit> = use commit, but edit the commit message
162e, edit <commit> = use commit, but stop for amending
163s, squash <commit> = use commit, but meld into previous commit
164f, fixup <commit> = like \"squash\", but discard this commit's log message
35d515b5 165x, exec <command> = run command (the rest of the line) using shell
f431d73d 166d, drop <commit> = remove commit
9055e401
JS
167l, label <label> = label current HEAD with a name
168t, reset <label> = reset HEAD to a label
4c68e7dd
JS
169m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
170. create a merge commit using the original merge commit's
171. message (or the oneline, if no original merge commit was
172. specified). Use -c <commit> to reword the commit message.
180bad3d
JK
173
174These lines can be re-ordered; they are executed from top to bottom.
b8fc9e43 175" | git stripspace --comment-lines >>"$todo"
180bad3d 176
37079959
GR
177 if test $(get_missing_commit_check_level) = error
178 then
b8fc9e43 179 gettext "
37079959 180Do not remove any line. Use 'drop' explicitly to remove a commit.
b8fc9e43 181" | git stripspace --comment-lines >>"$todo"
37079959 182 else
b8fc9e43 183 gettext "
180bad3d 184If you remove a line here THAT COMMIT WILL BE LOST.
b8fc9e43 185" | git stripspace --comment-lines >>"$todo"
37079959 186 fi
fcc5ef1c
AW
187}
188
1b1dce4b 189make_patch () {
4fb1a19d
JS
190 sha1_and_parents="$(git rev-list --parents -1 "$1")"
191 case "$sha1_and_parents" in
192 ?*' '?*' '?*)
193 git diff --cc $sha1_and_parents
194 ;;
195 ?*' '?*)
196 git diff-tree -p "$1^!"
197 ;;
198 *)
199 echo "Root commit"
200 ;;
431b7e78 201 esac > "$state_dir"/patch
6bb4e485
MZ
202 test -f "$msg" ||
203 commit_message "$1" > "$msg"
204 test -f "$author_script" ||
205 get_author_ident_from_commit "$1" > "$author_script"
1b1dce4b
JS
206}
207
208die_with_patch () {
431b7e78 209 echo "$1" > "$state_dir"/stopped-sha
fbd7a232 210 git update-ref REBASE_HEAD "$1"
1b1dce4b
JS
211 make_patch "$1"
212 die "$2"
213}
214
0becb3e4
AW
215exit_with_patch () {
216 echo "$1" > "$state_dir"/stopped-sha
fbd7a232 217 git update-ref REBASE_HEAD "$1"
0becb3e4
AW
218 make_patch $1
219 git rev-parse --verify HEAD > "$amend"
3ee5e540 220 gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")}
9588c52b
VA
221 warn "$(eval_gettext "\
222You can amend the commit now, with
223
224 git commit --amend \$gpg_sign_opt_quoted
225
226Once you are satisfied with your changes, run
227
228 git rebase --continue")"
0becb3e4
AW
229 warn
230 exit $2
231}
232
c54b7817 233die_abort () {
33ba9c64 234 apply_autostash
431b7e78 235 rm -rf "$state_dir"
c54b7817
JS
236 die "$1"
237}
238
376ccb8c 239has_action () {
180bad3d 240 test -n "$(git stripspace --strip-comments <"$1")"
376ccb8c
JS
241}
242
90e1818f 243is_empty_commit() {
9588c52b
VA
244 tree=$(git rev-parse -q --verify "$1"^{tree} 2>/dev/null) || {
245 sha1=$1
246 die "$(eval_gettext "\$sha1: not a commit that can be picked")"
247 }
248 ptree=$(git rev-parse -q --verify "$1"^^{tree} 2>/dev/null) ||
03a7f388 249 ptree=$empty_tree
90e1818f
NH
250 test "$tree" = "$ptree"
251}
252
98697784
PH
253is_merge_commit()
254{
255 git rev-parse --verify --quiet "$1"^2 >/dev/null 2>&1
256}
257
7756ecff
MH
258# Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
259# GIT_AUTHOR_DATE exported from the current environment.
260do_with_author () {
76c9c0db
JH
261 (
262 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
263 "$@"
264 )
7756ecff
MH
265}
266
821881d8
PO
267git_sequence_editor () {
268 if test -z "$GIT_SEQUENCE_EDITOR"
269 then
270 GIT_SEQUENCE_EDITOR="$(git config sequence.editor)"
271 if [ -z "$GIT_SEQUENCE_EDITOR" ]
272 then
273 GIT_SEQUENCE_EDITOR="$(git var GIT_EDITOR)" || return $?
274 fi
275 fi
276
277 eval "$GIT_SEQUENCE_EDITOR" '"$@"'
278}
279
1b1dce4b 280pick_one () {
8e75abfd 281 ff=--ff
90e1818f 282
8e75abfd 283 case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac
6bb4e485 284 case "$force_rebase" in '') ;; ?*) ff= ;; esac
9588c52b 285 output git rev-parse --verify $sha1 || die "$(eval_gettext "Invalid commit name: \$sha1")"
90e1818f
NH
286
287 if is_empty_commit "$sha1"
288 then
289 empty_args="--allow-empty"
290 fi
291
6bb4e485 292 test -d "$rewritten" &&
f09c9b8c 293 pick_one_preserving_merges "$@" && return
a6c612b5 294 output eval git cherry-pick $allow_rerere_autoupdate $allow_empty_message \
3ee5e540 295 ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
a852ec7f 296 $signoff "$strategy_args" $empty_args $ff "$@"
8cbc57ca
PH
297
298 # If cherry-pick dies it leaves the to-be-picked commit unrecorded. Reschedule
299 # previous task so this commit is not lost.
300 ret=$?
301 case "$ret" in [01]) ;; *) reschedule_last_action ;; esac
302 return $ret
1b1dce4b
JS
303}
304
f09c9b8c 305pick_one_preserving_merges () {
71d9451e
TR
306 fast_forward=t
307 case "$1" in
308 -n)
309 fast_forward=f
310 sha1=$2
311 ;;
312 *)
313 sha1=$1
314 ;;
315 esac
f09c9b8c
JS
316 sha1=$(git rev-parse $sha1)
317
0c4030ca 318 if test -f "$state_dir"/current-commit && test "$fast_forward" = t
f09c9b8c 319 then
0c4030ca
WS
320 while read current_commit
321 do
322 git rev-parse HEAD > "$rewritten"/$current_commit
323 done <"$state_dir"/current-commit
324 rm "$state_dir"/current-commit ||
325 die "$(gettext "Cannot write current commit's replacement sha1")"
f09c9b8c
JS
326 fi
327
431b7e78 328 echo $sha1 >> "$state_dir"/current-commit
a96dc01e 329
f09c9b8c 330 # rewrite parents; if none were rewritten, we can fast-forward.
f09c9b8c 331 new_parents=
d911d146
TR
332 pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)"
333 if test "$pend" = " "
334 then
335 pend=" root"
336 fi
faae853c 337 while [ "$pend" != "" ]
f09c9b8c 338 do
faae853c
SH
339 p=$(expr "$pend" : ' \([^ ]*\)')
340 pend="${pend# $p}"
341
6bb4e485 342 if test -f "$rewritten"/$p
f09c9b8c 343 then
6bb4e485 344 new_p=$(cat "$rewritten"/$p)
80fe82e4
SH
345
346 # If the todo reordered commits, and our parent is marked for
347 # rewriting, but hasn't been gotten to yet, assume the user meant to
348 # drop it on top of the current HEAD
349 if test -z "$new_p"
350 then
351 new_p=$(git rev-parse HEAD)
352 fi
353
f09c9b8c
JS
354 test $p != $new_p && fast_forward=f
355 case "$new_parents" in
356 *$new_p*)
357 ;; # do nothing; that parent is already there
358 *)
359 new_parents="$new_parents $new_p"
376ccb8c 360 ;;
f09c9b8c 361 esac
1c5fa0a1 362 else
6bb4e485 363 if test -f "$dropped"/$p
faae853c
SH
364 then
365 fast_forward=f
6bb4e485 366 replacement="$(cat "$dropped"/$p)"
d911d146
TR
367 test -z "$replacement" && replacement=root
368 pend=" $replacement$pend"
faae853c
SH
369 else
370 new_parents="$new_parents $p"
371 fi
f09c9b8c
JS
372 fi
373 done
374 case $fast_forward in
375 t)
9588c52b 376 output warn "$(eval_gettext "Fast-forward to \$sha1")"
71d9451e 377 output git reset --hard $sha1 ||
9588c52b 378 die "$(eval_gettext "Cannot fast-forward to \$sha1")"
f09c9b8c
JS
379 ;;
380 f)
376ccb8c 381 first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
a4f25e36
SH
382
383 if [ "$1" != "-n" ]
384 then
385 # detach HEAD to current parent
386 output git checkout $first_parent 2> /dev/null ||
9588c52b 387 die "$(eval_gettext "Cannot move HEAD to \$first_parent")"
a4f25e36 388 fi
f09c9b8c 389
f09c9b8c 390 case "$new_parents" in
376ccb8c 391 ' '*' '*)
9588c52b 392 test "a$1" = a-n && die "$(eval_gettext "Refusing to squash a merge: \$sha1")"
a4f25e36 393
f09c9b8c 394 # redo merge
6bb4e485
MZ
395 author_script_content=$(get_author_ident_from_commit $sha1)
396 eval "$author_script_content"
397 msg_content="$(commit_message $sha1)"
f91333d6
BS
398 # No point in merging the first parent, that's HEAD
399 new_parents=${new_parents# $first_parent}
a9f739c1 400 merge_args="--no-log --no-ff"
db2b3b82 401 if ! do_with_author output eval \
dd6fb005
JS
402 git merge ${gpg_sign_opt:+$(git rev-parse \
403 --sq-quote "$gpg_sign_opt")} \
404 $allow_rerere_autoupdate "$merge_args" \
405 "$strategy_args" \
ed5144d7 406 -m "$(git rev-parse --sq-quote "$msg_content")" \
dd6fb005 407 "$new_parents"
f09c9b8c 408 then
6bb4e485 409 printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG
9588c52b 410 die_with_patch $sha1 "$(eval_gettext "Error redoing merge \$sha1")"
f09c9b8c 411 fi
6bb4e485 412 echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
f09c9b8c
JS
413 ;;
414 *)
9b6d7a62 415 output eval git cherry-pick $allow_rerere_autoupdate \
a6c612b5 416 $allow_empty_message \
3ee5e540
NV
417 ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
418 "$strategy_args" "$@" ||
9588c52b 419 die_with_patch $sha1 "$(eval_gettext "Could not pick \$sha1")"
376ccb8c 420 ;;
f09c9b8c 421 esac
376ccb8c 422 ;;
f09c9b8c
JS
423 esac
424}
425
f2d17068
VA
426this_nth_commit_message () {
427 n=$1
8aa6dc1d 428 eval_gettext "This is the commit message #\${n}:"
f2d17068 429}
8aa6dc1d 430
f2d17068
VA
431skip_nth_commit_message () {
432 n=$1
8aa6dc1d 433 eval_gettext "The commit message #\${n} will be skipped:"
6368f3f8
JS
434}
435
a25eb139 436update_squash_messages () {
6bb4e485
MZ
437 if test -f "$squash_msg"; then
438 mv "$squash_msg" "$squash_msg".bak || exit
439 count=$(($(sed -n \
356b8ecf 440 -e "1s/^$comment_char[^0-9]*\([0-9][0-9]*\).*/\1/p" \
6bb4e485 441 -e "q" < "$squash_msg".bak)+1))
bde1a686 442 {
f2d17068
VA
443 printf '%s\n' "$comment_char $(eval_ngettext \
444 "This is a combination of \$count commit." \
445 "This is a combination of \$count commits." \
446 $count)"
bde1a686
MH
447 sed -e 1d -e '2,/^./{
448 /^$/d
6bb4e485
MZ
449 }' <"$squash_msg".bak
450 } >"$squash_msg"
6368f3f8 451 else
acefe2be
JH
452 commit_message HEAD >"$fixup_msg" ||
453 die "$(eval_gettext "Cannot write \$fixup_msg")"
6bb4e485 454 count=2
bde1a686 455 {
f2d17068
VA
456 printf '%s\n' "$comment_char $(gettext "This is a combination of 2 commits.")"
457 printf '%s\n' "$comment_char $(gettext "This is the 1st commit message:")"
bde1a686 458 echo
6bb4e485
MZ
459 cat "$fixup_msg"
460 } >"$squash_msg"
6368f3f8 461 fi
0205e72f
MH
462 case $1 in
463 squash)
6bb4e485 464 rm -f "$fixup_msg"
0205e72f 465 echo
f2d17068 466 printf '%s\n' "$comment_char $(this_nth_commit_message $count)"
0205e72f 467 echo
ee0a4afb 468 commit_message $2
0205e72f
MH
469 ;;
470 fixup)
471 echo
f2d17068 472 printf '%s\n' "$comment_char $(skip_nth_commit_message $count)"
0205e72f 473 echo
180bad3d
JK
474 # Change the space after the comment character to TAB:
475 commit_message $2 | git stripspace --comment-lines | sed -e 's/ / /'
0205e72f 476 ;;
6bb4e485 477 esac >>"$squash_msg"
6368f3f8
JS
478}
479
480peek_next_command () {
180bad3d 481 git stripspace --strip-comments <"$todo" | sed -n -e 's/ .*//p' -e q
6368f3f8
JS
482}
483
6bdcd0d2
MH
484# A squash/fixup has failed. Prepare the long version of the squash
485# commit message, then die_with_patch. This code path requires the
486# user to edit the combined commit message for all commits that have
487# been squashed/fixedup so far. So also erase the old squash
488# messages, effectively causing the combined commit to be used as the
489# new basis for any further squash/fixups. Args: sha1 rest
490die_failed_squash() {
9588c52b
VA
491 sha1=$1
492 rest=$2
6bb4e485
MZ
493 mv "$squash_msg" "$msg" || exit
494 rm -f "$fixup_msg"
495 cp "$msg" "$GIT_DIR"/MERGE_MSG || exit
6bdcd0d2 496 warn
9588c52b
VA
497 warn "$(eval_gettext "Could not apply \$sha1... \$rest")"
498 die_with_patch $sha1 ""
6bdcd0d2
MH
499}
500
b079feed 501flush_rewritten_pending() {
6bb4e485 502 test -s "$rewritten_pending" || return
b079feed 503 newsha1="$(git rev-parse HEAD^0)"
6bb4e485
MZ
504 sed "s/$/ $newsha1/" < "$rewritten_pending" >> "$rewritten_list"
505 rm -f "$rewritten_pending"
b079feed
TR
506}
507
508record_in_rewritten() {
509 oldsha1="$(git rev-parse $1)"
6bb4e485 510 echo "$oldsha1" >> "$rewritten_pending"
b079feed
TR
511
512 case "$(peek_next_command)" in
41f556b9 513 squash|s|fixup|f)
b079feed 514 ;;
41f556b9 515 *)
b079feed
TR
516 flush_rewritten_pending
517 ;;
518 esac
519}
520
df5df20c 521do_pick () {
9588c52b
VA
522 sha1=$1
523 rest=$2
df5df20c
CW
524 if test "$(git rev-parse HEAD)" = "$squash_onto"
525 then
526 # Set the correct commit message and author info on the
527 # sentinel root before cherry-picking the original changes
528 # without committing (-n). Finally, update the sentinel again
529 # to include these changes. If the cherry-pick results in a
530 # conflict, this means our behaviour is similar to a standard
531 # failed cherry-pick during rebase, with a dirty index to
532 # resolve before manually running git commit --amend then git
533 # rebase --continue.
534 git commit --allow-empty --allow-empty-message --amend \
a852ec7f 535 --no-post-rewrite -n -q -C $sha1 $signoff &&
9588c52b 536 pick_one -n $sha1 &&
df5df20c 537 git commit --allow-empty --allow-empty-message \
a852ec7f 538 --amend --no-post-rewrite -n -q -C $sha1 $signoff \
3ee5e540 539 ${gpg_sign_opt:+"$gpg_sign_opt"} ||
9588c52b 540 die_with_patch $sha1 "$(eval_gettext "Could not apply \$sha1... \$rest")"
df5df20c 541 else
9588c52b
VA
542 pick_one $sha1 ||
543 die_with_patch $sha1 "$(eval_gettext "Could not apply \$sha1... \$rest")"
df5df20c
CW
544 fi
545}
546
1b1dce4b 547do_next () {
b12d3e90 548 rm -f "$msg" "$author_script" "$amend" "$state_dir"/stopped-sha || exit
6bb4e485 549 read -r command sha1 rest < "$todo"
1b1dce4b 550 case "$command" in
c9266d58 551 "$comment_char"*|''|noop|drop|d)
1b1dce4b 552 mark_action_done
1b1dce4b 553 ;;
39743cf5
JH
554 "$cr")
555 # Work around CR left by "read" (e.g. with Git for Windows' Bash).
556 mark_action_done
557 ;;
f8babc4d 558 pick|p)
1b1dce4b
JS
559 comment_for_reflog pick
560
561 mark_action_done
df5df20c 562 do_pick $sha1 "$rest"
b079feed 563 record_in_rewritten $sha1
1b1dce4b 564 ;;
6741aa6c
BG
565 reword|r)
566 comment_for_reflog reword
567
568 mark_action_done
df5df20c 569 do_pick $sha1 "$rest"
a6c612b5
GS
570 git commit --amend --no-post-rewrite ${gpg_sign_opt:+"$gpg_sign_opt"} \
571 $allow_empty_message || {
9588c52b
VA
572 warn "$(eval_gettext "\
573Could not amend commit after successfully picking \$sha1... \$rest
574This is most likely due to an empty commit message, or the pre-commit hook
575failed. If the pre-commit hook failed, you may need to resolve the issue before
576you are able to reword the commit.")"
0becb3e4
AW
577 exit_with_patch $sha1 1
578 }
b079feed 579 record_in_rewritten $sha1
6741aa6c 580 ;;
f8babc4d 581 edit|e)
1b1dce4b
JS
582 comment_for_reflog edit
583
584 mark_action_done
df5df20c 585 do_pick $sha1 "$rest"
14c793e8 586 sha1_abbrev=$(git rev-parse --short $sha1)
9588c52b 587 warn "$(eval_gettext "Stopped at \$sha1_abbrev... \$rest")"
0becb3e4 588 exit_with_patch $sha1 0
1b1dce4b 589 ;;
0205e72f
MH
590 squash|s|fixup|f)
591 case "$command" in
592 squash|s)
593 squash_style=squash
594 ;;
595 fixup|f)
596 squash_style=fixup
597 ;;
598 esac
599 comment_for_reflog $squash_style
1b1dce4b 600
6bb4e485 601 test -f "$done" && has_action "$done" ||
9588c52b 602 die "$(eval_gettext "Cannot '\$squash_style' without a previous commit")"
1b1dce4b
JS
603
604 mark_action_done
a25eb139 605 update_squash_messages $squash_style $sha1
6bb4e485
MZ
606 author_script_content=$(get_author_ident_from_commit HEAD)
607 echo "$author_script_content" > "$author_script"
608 eval "$author_script_content"
2147f844
CW
609 if ! pick_one -n $sha1
610 then
611 git rev-parse --verify HEAD >"$amend"
612 die_failed_squash $sha1 "$rest"
613 fi
6368f3f8 614 case "$(peek_next_command)" in
0205e72f 615 squash|s|fixup|f)
a25eb139
MH
616 # This is an intermediate commit; its message will only be
617 # used in case of trouble. So use the long version:
3ee5e540 618 do_with_author output git commit --amend --no-verify -F "$squash_msg" \
a6c612b5 619 ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
6bdcd0d2 620 die_failed_squash $sha1 "$rest"
376ccb8c 621 ;;
6368f3f8 622 *)
a25eb139 623 # This is the final command of this squash/fixup group
6bb4e485 624 if test -f "$fixup_msg"
a25eb139 625 then
3ee5e540 626 do_with_author git commit --amend --no-verify -F "$fixup_msg" \
a6c612b5 627 ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
6bdcd0d2
MH
628 die_failed_squash $sha1 "$rest"
629 else
6bb4e485 630 cp "$squash_msg" "$GIT_DIR"/SQUASH_MSG || exit
6bdcd0d2 631 rm -f "$GIT_DIR"/MERGE_MSG
3ee5e540 632 do_with_author git commit --amend --no-verify -F "$GIT_DIR"/SQUASH_MSG -e \
a6c612b5 633 ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
6bdcd0d2 634 die_failed_squash $sha1 "$rest"
a25eb139 635 fi
6bb4e485 636 rm -f "$squash_msg" "$fixup_msg"
376ccb8c 637 ;;
6368f3f8 638 esac
b079feed 639 record_in_rewritten $sha1
1b1dce4b 640 ;;
cd035b1c 641 x|"exec")
6bb4e485 642 read -r command rest < "$todo"
cd035b1c 643 mark_action_done
9588c52b 644 eval_gettextln "Executing: \$rest"
fe9394ad 645 "${SHELL:-@SHELL_PATH@}" -c "$rest" # Actual execution
cd035b1c 646 status=$?
1686519a
JH
647 # Run in subshell because require_clean_work_tree can die.
648 dirty=f
649 (require_clean_work_tree "rebase" 2>/dev/null) || dirty=t
cd035b1c
MM
650 if test "$status" -ne 0
651 then
9588c52b 652 warn "$(eval_gettext "Execution failed: \$rest")"
1686519a 653 test "$dirty" = f ||
9588c52b 654 warn "$(gettext "and made changes to the index and/or the working tree")"
1686519a 655
9588c52b
VA
656 warn "$(gettext "\
657You can fix the problem, and then run
658
659 git rebase --continue")"
cd035b1c 660 warn
ecfe1ea9
JS
661 if test $status -eq 127 # command not found
662 then
663 status=1
664 fi
cd035b1c 665 exit "$status"
1686519a 666 elif test "$dirty" = t
cd035b1c 667 then
9588c52b
VA
668 # TRANSLATORS: after these lines is a command to be issued by the user
669 warn "$(eval_gettext "\
670Execution succeeded: \$rest
671but left changes to the index and/or the working tree
672Commit or stash your changes, and then run
673
674 git rebase --continue")"
cd035b1c
MM
675 warn
676 exit 1
677 fi
678 ;;
1b1dce4b 679 *)
9588c52b
VA
680 warn "$(eval_gettext "Unknown command: \$command \$sha1 \$rest")"
681 fixtodo="$(gettext "Please fix this using 'git rebase --edit-todo'.")"
f1be316a
JK
682 if git rev-parse --verify -q "$sha1" >/dev/null
683 then
9c8e1011 684 die_with_patch $sha1 "$fixtodo"
f1be316a 685 else
9c8e1011 686 die "$fixtodo"
f1be316a 687 fi
376ccb8c 688 ;;
1b1dce4b 689 esac
6bb4e485 690 test -s "$todo" && return
1b1dce4b 691
68a163c9 692 comment_for_reflog finish &&
6bb4e485 693 newhead=$(git rev-parse HEAD) &&
431b7e78 694 case $head_name in
73697a0b 695 refs/*)
1af221ef 696 message="$GIT_REFLOG_ACTION: $head_name onto $onto" &&
431b7e78 697 git update-ref -m "$message" $head_name $newhead $orig_head &&
53f2ffa8
JK
698 git symbolic-ref \
699 -m "$GIT_REFLOG_ACTION: returning to $head_name" \
700 HEAD $head_name
73697a0b
JS
701 ;;
702 esac && {
431b7e78 703 test ! -f "$state_dir"/verbose ||
2959c283 704 git diff-tree --stat $orig_head..HEAD
3df0a859 705 } &&
eb2151bb 706 {
6bb4e485
MZ
707 test -s "$rewritten_list" &&
708 git notes copy --for-rewrite=rebase < "$rewritten_list" ||
eb2151bb
TR
709 true # we don't care if this copying failed
710 } &&
b849b954
NTND
711 hook="$(git rev-parse --git-path hooks/post-rewrite)"
712 if test -x "$hook" && test -s "$rewritten_list"; then
713 "$hook" rebase < "$rewritten_list"
b079feed
TR
714 true # we don't care if this hook failed
715 fi &&
9588c52b 716 warn "$(eval_gettext "Successfully rebased and updated \$head_name.")"
1b1dce4b 717
15d4bf2e 718 return 1 # not failure; just to break the do_rest loop
1b1dce4b
JS
719}
720
15d4bf2e 721# can only return 0, when the infinite loop breaks
1b1dce4b
JS
722do_rest () {
723 while :
724 do
15d4bf2e 725 do_next || break
1b1dce4b 726 done
1b1dce4b
JS
727}
728
75c69766 729expand_todo_ids() {
3546c8d9 730 git rebase--helper --expand-ids
75c69766
JH
731}
732
733collapse_todo_ids() {
3546c8d9 734 git rebase--helper --shorten-ids
f59baa50
NS
735}
736
37079959
GR
737# Switch to the branch in $into and notify it in the reflog
738checkout_onto () {
739 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
9588c52b 740 output git checkout $onto || die_abort "$(gettext "could not detach HEAD")"
37079959
GR
741 git update-ref ORIG_HEAD $orig_head
742}
743
744get_missing_commit_check_level () {
745 check_level=$(git config --get rebase.missingCommitsCheck)
746 check_level=${check_level:-ignore}
747 # Don't be case sensitive
748 printf '%s' "$check_level" | tr 'A-Z' 'a-z'
749}
750
27c499bf
WS
751# Initiate an action. If the cannot be any
752# further action it may exec a command
753# or exit and not return.
754#
755# TODO: Consider a cleaner return model so it
756# never exits and always return 0 if process
757# is complete.
758#
759# Parameter 1 is the action to initiate.
760#
761# Returns 0 if the action was able to complete
762# and if 1 if further processing is required.
763initiate_action () {
764 case "$1" in
d48f97aa
WS
765 continue)
766 if test ! -d "$rewritten"
ffaaed88 767 then
d48f97aa
WS
768 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
769 --continue
770 fi
771 # do we have anything to commit?
772 if git diff-index --cached --quiet HEAD --
773 then
774 # Nothing to commit -- skip this commit
775
776 test ! -f "$GIT_DIR"/CHERRY_PICK_HEAD ||
777 rm "$GIT_DIR"/CHERRY_PICK_HEAD ||
778 die "$(gettext "Could not remove CHERRY_PICK_HEAD")"
779 else
780 if ! test -f "$author_script"
781 then
782 gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")}
783 die "$(eval_gettext "\
9588c52b
VA
784You have staged changes in your working tree.
785If these changes are meant to be
ffaaed88
MM
786squashed into the previous commit, run:
787
9588c52b 788 git commit --amend \$gpg_sign_opt_quoted
ffaaed88
MM
789
790If they are meant to go into a new commit, run:
791
9588c52b 792 git commit \$gpg_sign_opt_quoted
ffaaed88 793
7c406bd8 794In both cases, once you're done, continue with:
ffaaed88
MM
795
796 git rebase --continue
9588c52b 797")"
d48f97aa
WS
798 fi
799 . "$author_script" ||
800 die "$(gettext "Error trying to find the author identity to amend commit")"
801 if test -f "$amend"
802 then
803 current_head=$(git rev-parse --verify HEAD)
804 test "$current_head" = $(cat "$amend") ||
805 die "$(gettext "\
9588c52b
VA
806You have uncommitted changes in your working tree. Please commit them
807first and then run 'git rebase --continue' again.")"
d48f97aa
WS
808 do_with_author git commit --amend --no-verify -F "$msg" -e \
809 ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
810 die "$(gettext "Could not commit staged changes.")"
811 else
812 do_with_author git commit --no-verify -F "$msg" -e \
813 ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
814 die "$(gettext "Could not commit staged changes.")"
815 fi
03270628 816 fi
18640d99 817
d48f97aa
WS
818 if test -r "$state_dir"/stopped-sha
819 then
820 record_in_rewritten "$(cat "$state_dir"/stopped-sha)"
821 fi
0acb62f2 822
d48f97aa
WS
823 require_clean_work_tree "rebase"
824 do_rest
825 return 0
826 ;;
827 skip)
828 git rerere clear
cf432ca0 829
d48f97aa
WS
830 if test ! -d "$rewritten"
831 then
832 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
833 --continue
834 fi
835 do_rest
836 return 0
837 ;;
838 edit-todo)
839 git stripspace --strip-comments <"$todo" >"$todo".new
840 mv -f "$todo".new "$todo"
841 collapse_todo_ids
842 append_todo_help
843 gettext "
180bad3d
JK
844You are editing the todo file of an ongoing interactive rebase.
845To continue rebase after editing, run:
846 git rebase --continue
847
b8fc9e43 848" | git stripspace --comment-lines >>"$todo"
eb9a7cb4 849
d48f97aa
WS
850 git_sequence_editor "$todo" ||
851 die "$(gettext "Could not execute editor")"
852 expand_todo_ids
34262322 853
d48f97aa
WS
854 exit
855 ;;
856 show-current-patch)
857 exec git show REBASE_HEAD --
858 ;;
27c499bf
WS
859 *)
860 return 1 # continue
861 ;;
d48f97aa 862 esac
27c499bf 863}
26cd160c 864
27c499bf 865setup_reflog_action () {
26cd160c 866 comment_for_reflog start
34262322 867
d48f97aa 868 if test ! -z "$switch_to"
34262322 869 then
d48f97aa
WS
870 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to"
871 output git checkout "$switch_to" -- ||
872 die "$(eval_gettext "Could not checkout \$switch_to")"
873
874 comment_for_reflog start
34262322 875 fi
27c499bf 876}
62db5247 877
27c499bf 878init_basic_state () {
d48f97aa
WS
879 orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")"
880 mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")"
881 rm -f "$(git rev-parse --git-path REBASE_HEAD)"
90e1818f 882
d48f97aa
WS
883 : > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")"
884 write_basic_state
27c499bf
WS
885}
886
887init_revisions_and_shortrevisions () {
888 shorthead=$(git rev-parse --short $orig_head)
889 shortonto=$(git rev-parse --short $onto)
890 if test -z "$rebase_root"
891 # this is now equivalent to ! -z "$upstream"
892 then
893 shortupstream=$(git rev-parse --short $upstream)
894 revisions=$upstream...$orig_head
895 shortrevisions=$shortupstream..$shorthead
896 else
897 revisions=$onto...$orig_head
898 shortrevisions=$shorthead
21d0764c
JS
899 test -z "$squash_onto" ||
900 echo "$squash_onto" >"$state_dir"/squash-onto
27c499bf
WS
901 fi
902}
903
904complete_action() {
905 test -s "$todo" || echo noop >> "$todo"
906 test -z "$autosquash" || git rebase--helper --rearrange-squash || exit
907 test -n "$cmd" && git rebase--helper --add-exec-commands "$cmd"
908
909 todocount=$(git stripspace --strip-comments <"$todo" | wc -l)
910 todocount=${todocount##* }
911
912cat >>"$todo" <<EOF
913
914$comment_char $(eval_ngettext \
915 "Rebase \$shortrevisions onto \$shortonto (\$todocount command)" \
916 "Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \
917 "$todocount")
918EOF
919 append_todo_help
920 gettext "
921 However, if you remove everything, the rebase will be aborted.
922
923 " | git stripspace --comment-lines >>"$todo"
924
925 if test -z "$keep_empty"
926 then
927 printf '%s\n' "$comment_char $(gettext "Note that empty commits are commented out")" >>"$todo"
928 fi
929
930
931 has_action "$todo" ||
932 return 2
933
934 cp "$todo" "$todo".backup
935 collapse_todo_ids
936 git_sequence_editor "$todo" ||
937 die_abort "$(gettext "Could not execute editor")"
938
939 has_action "$todo" ||
940 return 2
941
942 git rebase--helper --check-todo-list || {
943 ret=$?
944 checkout_onto
945 exit $ret
946 }
947
948 expand_todo_ids
949
950 test -d "$rewritten" || test -n "$force_rebase" ||
951 onto="$(git rebase--helper --skip-unnecessary-picks)" ||
952 die "Could not skip unnecessary pick commands"
953
954 checkout_onto
21d0764c 955 if test ! -d "$rewritten"
27c499bf
WS
956 then
957 require_clean_work_tree "rebase"
958 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
959 --continue
960 fi
961 do_rest
962}
963
964git_rebase__interactive () {
965 initiate_action "$action"
966 ret=$?
967 if test $ret = 0; then
968 return 0
969 fi
970
971 setup_reflog_action
972 init_basic_state
973
27c499bf
WS
974 init_revisions_and_shortrevisions
975
c04549b2 976 git rebase--helper --make-script ${keep_empty:+--keep-empty} \
8f6aed71 977 ${rebase_merges:+--rebase-merges} \
7543f6f4 978 ${rebase_cousins:+--rebase-cousins} \
c04549b2
WS
979 $revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
980 die "$(gettext "Could not generate todo list")"
950b487c
WS
981
982 complete_action
983}
984
985git_rebase__interactive__preserve_merges () {
986 initiate_action "$action"
987 ret=$?
988 if test $ret = 0; then
989 return 0
990 fi
991
992 setup_reflog_action
993 init_basic_state
994
ca3d446e 995 if test -z "$rebase_root"
950b487c 996 then
ca3d446e
WS
997 mkdir "$rewritten" &&
998 for c in $(git merge-base --all $orig_head $upstream)
999 do
1000 echo $onto > "$rewritten"/$c ||
950b487c 1001 die "$(gettext "Could not init rewritten commits")"
ca3d446e 1002 done
950b487c 1003 else
ca3d446e
WS
1004 mkdir "$rewritten" &&
1005 echo $onto > "$rewritten"/root ||
1006 die "$(gettext "Could not init rewritten commits")"
950b487c
WS
1007 fi
1008
1009 init_revisions_and_shortrevisions
1010
ca3d446e
WS
1011 format=$(git config --get rebase.instructionFormat)
1012 # the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to parse
f24cd418 1013 git rev-list --format="%m%H ${format:-%s}" \
ca3d446e
WS
1014 --reverse --left-right --topo-order \
1015 $revisions ${restrict_revision+^$restrict_revision} | \
1016 sed -n "s/^>//p" |
1017 while read -r sha1 rest
1018 do
ca3d446e
WS
1019 if test -z "$keep_empty" && is_empty_commit $sha1 && ! is_merge_commit $sha1
1020 then
1021 comment_out="$comment_char "
1022 else
1023 comment_out=
1024 fi
d48f97aa 1025
ca3d446e
WS
1026 if test -z "$rebase_root"
1027 then
1028 preserve=t
1029 for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
1030 do
1031 if test -f "$rewritten"/$p
1032 then
1033 preserve=f
1034 fi
1035 done
1036 else
1037 preserve=f
1038 fi
1039 if test f = "$preserve"
1040 then
1041 touch "$rewritten"/$sha1
1042 printf '%s\n' "${comment_out}pick $sha1 $rest" >>"$todo"
1043 fi
1044 done
d48f97aa
WS
1045
1046 # Watch for commits that been dropped by --cherry-pick
ca3d446e
WS
1047 mkdir "$dropped"
1048 # Save all non-cherry-picked changes
1049 git rev-list $revisions --left-right --cherry-pick | \
1050 sed -n "s/^>//p" > "$state_dir"/not-cherry-picks
1051 # Now all commits and note which ones are missing in
1052 # not-cherry-picks and hence being dropped
1053 git rev-list $revisions |
1054 while read rev
1055 do
1056 if test -f "$rewritten"/$rev &&
1057 ! sane_grep "$rev" "$state_dir"/not-cherry-picks >/dev/null
1058 then
1059 # Use -f2 because if rev-list is telling us this commit is
1060 # not worthwhile, we don't want to track its multiple heads,
1061 # just the history of its first-parent for others that will
1062 # be rebasing on top of it
1063 git rev-list --parents -1 $rev | cut -d' ' -s -f2 > "$dropped"/$rev
1064 sha1=$(git rev-list -1 $rev)
1065 sane_grep -v "^[a-z][a-z]* $sha1" <"$todo" > "${todo}2" ; mv "${todo}2" "$todo"
1066 rm "$rewritten"/$rev
1067 fi
1068 done
34262322 1069
27c499bf 1070 complete_action
9f50d32b 1071}