die_with_patch () {
echo "$1" > "$state_dir"/stopped-sha
+ git update-ref REBASE_HEAD "$1"
make_patch "$1"
die "$2"
}
exit_with_patch () {
echo "$1" > "$state_dir"/stopped-sha
+ git update-ref REBASE_HEAD "$1"
make_patch $1
git rev-parse --verify HEAD > "$amend"
gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")}
test -d "$rewritten" &&
pick_one_preserving_merges "$@" && return
- output eval git cherry-pick \
+ output eval git cherry-pick $allow_rerere_autoupdate $allow_empty_message \
${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
"$strategy_args" $empty_args $ff "$@"
new_parents=${new_parents# $first_parent}
merge_args="--no-log --no-ff"
if ! do_with_author output eval \
- 'git merge ${gpg_sign_opt:+"$gpg_sign_opt"} \
- $merge_args $strategy_args -m "$msg_content" $new_parents'
+ git merge ${gpg_sign_opt:+$(git rev-parse \
+ --sq-quote "$gpg_sign_opt")} \
+ $allow_rerere_autoupdate "$merge_args" \
+ "$strategy_args" \
+ -m "$(git rev-parse --sq-quote "$msg_content")" \
+ "$new_parents"
then
printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG
die_with_patch $sha1 "$(eval_gettext "Error redoing merge \$sha1")"
echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
;;
*)
- output eval git cherry-pick \
+ output eval git cherry-pick $allow_rerere_autoupdate \
+ $allow_empty_message \
${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
"$strategy_args" "$@" ||
die_with_patch $sha1 "$(eval_gettext "Could not pick \$sha1")"
mark_action_done
do_pick $sha1 "$rest"
- git commit --amend --no-post-rewrite ${gpg_sign_opt:+"$gpg_sign_opt"} || {
+ git commit --amend --no-post-rewrite ${gpg_sign_opt:+"$gpg_sign_opt"} \
+ $allow_empty_message || {
warn "$(eval_gettext "\
Could not amend commit after successfully picking \$sha1... \$rest
This is most likely due to an empty commit message, or the pre-commit hook
# This is an intermediate commit; its message will only be
# used in case of trouble. So use the long version:
do_with_author output git commit --amend --no-verify -F "$squash_msg" \
- ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+ ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
die_failed_squash $sha1 "$rest"
;;
*)
if test -f "$fixup_msg"
then
do_with_author git commit --amend --no-verify -F "$fixup_msg" \
- ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+ ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
die_failed_squash $sha1 "$rest"
else
cp "$squash_msg" "$GIT_DIR"/SQUASH_MSG || exit
rm -f "$GIT_DIR"/MERGE_MSG
do_with_author git commit --amend --no-verify -F "$GIT_DIR"/SQUASH_MSG -e \
- ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+ ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
die_failed_squash $sha1 "$rest"
fi
rm -f "$squash_msg" "$fixup_msg"
git rebase--helper --shorten-ids
}
-# Rearrange the todo list that has both "pick sha1 msg" and
-# "pick sha1 fixup!/squash! msg" appears in it so that the latter
-# comes immediately after the former, and change "pick" to
-# "fixup"/"squash".
-#
-# Note that if the config has specified a custom instruction format
-# each log message will be re-retrieved in order to normalize the
-# autosquash arrangement
-rearrange_squash () {
- format=$(git config --get rebase.instructionFormat)
- # extract fixup!/squash! lines and resolve any referenced sha1's
- while read -r pick sha1 message
- do
- test -z "${format}" || message=$(git log -n 1 --format="%s" ${sha1})
- case "$message" in
- "squash! "*|"fixup! "*)
- action="${message%%!*}"
- rest=$message
- prefix=
- # skip all squash! or fixup! (but save for later)
- while :
- do
- case "$rest" in
- "squash! "*|"fixup! "*)
- prefix="$prefix${rest%%!*},"
- rest="${rest#*! }"
- ;;
- *)
- break
- ;;
- esac
- done
- printf '%s %s %s %s\n' "$sha1" "$action" "$prefix" "$rest"
- # if it's a single word, try to resolve to a full sha1 and
- # emit a second copy. This allows us to match on both message
- # and on sha1 prefix
- if test "${rest#* }" = "$rest"; then
- fullsha="$(git rev-parse -q --verify "$rest" 2>/dev/null)"
- if test -n "$fullsha"; then
- # prefix the action to uniquely identify this line as
- # intended for full sha1 match
- echo "$sha1 +$action $prefix $fullsha"
- fi
- fi
- esac
- done >"$1.sq" <"$1"
- test -s "$1.sq" || return
-
- used=
- while read -r pick sha1 message
- do
- case " $used" in
- *" $sha1 "*) continue ;;
- esac
- printf '%s\n' "$pick $sha1 $message"
- test -z "${format}" || message=$(git log -n 1 --format="%s" ${sha1})
- used="$used$sha1 "
- while read -r squash action msg_prefix msg_content
- do
- case " $used" in
- *" $squash "*) continue ;;
- esac
- emit=0
- case "$action" in
- +*)
- action="${action#+}"
- # full sha1 prefix test
- case "$msg_content" in "$sha1"*) emit=1;; esac ;;
- *)
- # message prefix test
- case "$message" in "$msg_content"*) emit=1;; esac ;;
- esac
- if test $emit = 1; then
- if test -n "${format}"
- then
- msg_content=$(git log -n 1 --format="${format}" ${squash})
- else
- msg_content="$(echo "$msg_prefix" | sed "s/,/! /g")$msg_content"
- fi
- printf '%s\n' "$action $squash $msg_content"
- used="$used$squash "
- fi
- done <"$1.sq"
- done >"$1.rearranged" <"$1"
- cat "$1.rearranged" >"$1"
- rm -f "$1.sq" "$1.rearranged"
-}
-
-# Add commands after a pick or after a squash/fixup serie
-# in the todo list.
-add_exec_commands () {
- {
- first=t
- while read -r insn rest
- do
- case $insn in
- pick)
- test -n "$first" ||
- printf "%s" "$cmd"
- ;;
- esac
- printf "%s %s\n" "$insn" "$rest"
- first=
- done
- printf "%s" "$cmd"
- } <"$1" >"$1.new" &&
- mv "$1.new" "$1"
-}
-
# Switch to the branch in $into and notify it in the reflog
checkout_onto () {
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
continue)
if test ! -d "$rewritten"
then
- exec git rebase--helper ${force_rebase:+--no-ff} --continue
+ exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+ --continue
fi
# do we have anything to commit?
if git diff-index --cached --quiet HEAD --
You have uncommitted changes in your working tree. Please commit them
first and then run 'git rebase --continue' again.")"
do_with_author git commit --amend --no-verify -F "$msg" -e \
- ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+ ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
die "$(gettext "Could not commit staged changes.")"
else
do_with_author git commit --no-verify -F "$msg" -e \
- ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+ ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
die "$(gettext "Could not commit staged changes.")"
fi
fi
if test ! -d "$rewritten"
then
- exec git rebase--helper ${force_rebase:+--no-ff} --continue
+ exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+ --continue
fi
do_rest
return 0
exit
;;
+show-current-patch)
+ exec git show REBASE_HEAD --
+ ;;
esac
comment_for_reflog start
orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")"
mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")"
+rm -f "$(git rev-parse --git-path REBASE_HEAD)"
: > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")"
write_basic_state
if test t != "$preserve_merges"
then
git rebase--helper --make-script ${keep_empty:+--keep-empty} \
- $revisions ${restrict_revision+^$restrict_revision} >"$todo"
+ $revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
+ die "$(gettext "Could not generate todo list")"
else
format=$(git config --get rebase.instructionFormat)
# the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to parse
fi
test -s "$todo" || echo noop >> "$todo"
-test -n "$autosquash" && rearrange_squash "$todo"
-test -n "$cmd" && add_exec_commands "$todo"
+test -z "$autosquash" || git rebase--helper --rearrange-squash || exit
+test -n "$cmd" && git rebase--helper --add-exec-commands "$cmd"
todocount=$(git stripspace --strip-comments <"$todo" | wc -l)
todocount=${todocount##* }
if test -z "$rebase_root" && test ! -d "$rewritten"
then
require_clean_work_tree "rebase"
- exec git rebase--helper ${force_rebase:+--no-ff} --continue
+ exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+ --continue
fi
do_rest