edit-todo! edit the todo list during an interactive rebase
quit! abort but keep HEAD where it is
show-current-patch! show the patch file being applied or merged
+reschedule-failed-exec automatically reschedule failed exec commands
"
. git-sh-setup
set_reflog_action rebase
LF='
'
ok_to_skip_pre_rebase=
-resolvemsg="
-$(gettext 'Resolve all conflicts manually, mark them as resolved with
-"git add/rm <conflicted_files>", then run "git rebase --continue".
-You can instead skip this commit: run "git rebase --skip".
-To abort and get back to the state before "git rebase", run "git rebase --abort".')
-"
+
squash_onto=
unset onto
unset restrict_revision
keep_empty=
allow_empty_message=--allow-empty-message
signoff=
+reschedule_failed_exec=
test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
case "$(git config --bool commit.gpgsign)" in
true) gpg_sign_opt=-S ;;
*) gpg_sign_opt= ;;
esac
+test "$(git config --bool rebase.reschedulefailedexec)" = "true" &&
+reschedule_failed_exec=--reschedule-failed-exec
+. git-rebase--common
read_basic_state () {
test -f "$state_dir/head-name" &&
else
orig_head=$(cat "$state_dir"/head)
fi &&
- GIT_QUIET=$(cat "$state_dir"/quiet) &&
+ test -f "$state_dir"/quiet && GIT_QUIET=t
test -f "$state_dir"/verbose && verbose=t
test -f "$state_dir"/strategy && strategy="$(cat "$state_dir"/strategy)"
test -f "$state_dir"/strategy_opts &&
signoff="$(cat "$state_dir"/signoff)"
force_rebase=t
}
-}
-
-write_basic_state () {
- echo "$head_name" > "$state_dir"/head-name &&
- echo "$onto" > "$state_dir"/onto &&
- echo "$orig_head" > "$state_dir"/orig-head &&
- echo "$GIT_QUIET" > "$state_dir"/quiet &&
- test t = "$verbose" && : > "$state_dir"/verbose
- test -n "$strategy" && echo "$strategy" > "$state_dir"/strategy
- test -n "$strategy_opts" && echo "$strategy_opts" > \
- "$state_dir"/strategy_opts
- test -n "$allow_rerere_autoupdate" && echo "$allow_rerere_autoupdate" > \
- "$state_dir"/allow_rerere_autoupdate
- test -n "$gpg_sign_opt" && echo "$gpg_sign_opt" > "$state_dir"/gpg_sign_opt
- test -n "$signoff" && echo "$signoff" >"$state_dir"/signoff
-}
-
-output () {
- case "$verbose" in
- '')
- output=$("$@" 2>&1 )
- status=$?
- test $status != 0 && printf "%s\n" "$output"
- return $status
- ;;
- *)
- "$@"
- ;;
- esac
-}
-
-move_to_original_branch () {
- case "$head_name" in
- refs/*)
- message="rebase finished: $head_name onto $onto"
- git update-ref -m "$message" \
- $head_name $(git rev-parse HEAD) $orig_head &&
- git symbolic-ref \
- -m "rebase finished: returning to $head_name" \
- HEAD $head_name ||
- die "$(eval_gettext "Could not move back to \$head_name")"
- ;;
- esac
-}
-
-apply_autostash () {
- if test -f "$state_dir/autostash"
- then
- stash_sha1=$(cat "$state_dir/autostash")
- if git stash apply $stash_sha1 >/dev/null 2>&1
- then
- echo "$(gettext 'Applied autostash.')" >&2
- else
- git stash store -m "autostash" -q $stash_sha1 ||
- die "$(eval_gettext "Cannot store \$stash_sha1")"
- gettext 'Applying autostash resulted in conflicts.
-Your changes are safe in the stash.
-You can run "git stash pop" or "git stash drop" at any time.
-' >&2
- fi
- fi
+ test -f "$state_dir"/reschedule-failed-exec &&
+ reschedule_failed_exec=t
}
finish_rebase () {
rm -rf "$state_dir"
}
+run_interactive () {
+ GIT_CHERRY_PICK_HELP="$resolvemsg"
+ export GIT_CHERRY_PICK_HELP
+
+ test -n "$keep_empty" && keep_empty="--keep-empty"
+ test -n "$rebase_merges" && rebase_merges="--rebase-merges"
+ test -n "$rebase_cousins" && rebase_cousins="--rebase-cousins"
+ test -n "$autosquash" && autosquash="--autosquash"
+ test -n "$verbose" && verbose="--verbose"
+ test -n "$force_rebase" && force_rebase="--no-ff"
+ test -n "$restrict_revision" && \
+ restrict_revision="--restrict-revision=^$restrict_revision"
+ test -n "$upstream" && upstream="--upstream=$upstream"
+ test -n "$onto" && onto="--onto=$onto"
+ test -n "$squash_onto" && squash_onto="--squash-onto=$squash_onto"
+ test -n "$onto_name" && onto_name="--onto-name=$onto_name"
+ test -n "$head_name" && head_name="--head-name=$head_name"
+ test -n "$strategy" && strategy="--strategy=$strategy"
+ test -n "$strategy_opts" && strategy_opts="--strategy-opts=$strategy_opts"
+ test -n "$switch_to" && switch_to="--switch-to=$switch_to"
+ test -n "$cmd" && cmd="--cmd=$cmd"
+ test -n "$action" && action="--$action"
+
+ exec git rebase--interactive "$action" "$keep_empty" "$rebase_merges" "$rebase_cousins" \
+ "$upstream" "$onto" "$squash_onto" "$restrict_revision" \
+ "$allow_empty_message" "$autosquash" "$verbose" \
+ "$force_rebase" "$onto_name" "$head_name" "$strategy" \
+ "$strategy_opts" "$cmd" "$switch_to" \
+ "$allow_rerere_autoupdate" "$gpg_sign_opt" "$signoff" \
+ "$reschedule_failed_exec"
+}
+
run_specific_rebase () {
if [ "$interactive_rebase" = implied ]; then
- GIT_EDITOR=:
- export GIT_EDITOR
+ GIT_SEQUENCE_EDITOR=:
+ export GIT_SEQUENCE_EDITOR
autosquash=
fi
- . git-rebase--$type
- if test -z "$preserve_merges"
+ if test -n "$interactive_rebase" -a -z "$preserve_merges"
then
- git_rebase__$type
+ run_interactive
else
- git_rebase__preserve_merges
+ . git-rebase--$type
+
+ if test -z "$preserve_merges"
+ then
+ git_rebase__$type
+ else
+ git_rebase__preserve_merges
+ fi
fi
ret=$?
if test $ret -eq 0
then
finish_rebase
- elif test $ret -eq 2 # special exit status for rebase -i
+ elif test $ret -eq 2 # special exit status for rebase -p
then
apply_autostash &&
rm -rf "$state_dir" &&
state_dir="$apply_dir"
elif test -d "$merge_dir"
then
+ type=interactive
if test -d "$merge_dir"/rewritten
then
type=preserve-merges
preserve_merges=t
elif test -f "$merge_dir"/interactive
then
- type=interactive
interactive_rebase=explicit
- else
- type=merge
fi
state_dir="$merge_dir"
fi
fix|strip)
force_rebase=t
;;
+ warn|nowarn|error|error-all)
+ ;; # okay, known whitespace option
+ *)
+ die "fatal: Invalid whitespace option: '${1#*=}'"
+ ;;
esac
;;
--ignore-whitespace)
git_am_opt="$git_am_opt $1"
force_rebase=t
;;
+ -C*[!0-9]*)
+ die "fatal: switch \`C' expects a numerical value"
+ ;;
-C*)
git_am_opt="$git_am_opt $1"
;;
--gpg-sign=*)
gpg_sign_opt="-S${1#--gpg-sign=}"
;;
+ --reschedule-failed-exec)
+ reschedule_failed_exec=--reschedule-failed-exec
+ ;;
+ --no-reschedule-failed-exec)
+ reschedule_failed_exec=
+ ;;
--)
shift
break
test -z "$interactive_rebase" && interactive_rebase=implied
fi
+actually_interactive=
if test -n "$interactive_rebase"
then
if test -z "$preserve_merges"
else
type=preserve-merges
fi
-
+ actually_interactive=t
state_dir="$merge_dir"
elif test -n "$do_merge"
then
- type=merge
+ interactive_rebase=implied
+ type=interactive
state_dir="$merge_dir"
else
type=am
git_format_patch_opt="$git_format_patch_opt --progress"
fi
-if test -n "$git_am_opt"; then
- incompatible_opts=$(echo " $git_am_opt " | \
- sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
- if test -n "$interactive_rebase"
+incompatible_opts=$(echo " $git_am_opt " | \
+ sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
+if test -n "$incompatible_opts"
+then
+ if test -n "$actually_interactive" || test "$do_merge"
then
- if test -n "$incompatible_opts"
- then
- die "$(gettext "error: cannot combine interactive options (--interactive, --exec, --rebase-merges, --preserve-merges, --keep-empty, --root + --onto) with am options ($incompatible_opts)")"
- fi
- fi
- if test -n "$do_merge"; then
- if test -n "$incompatible_opts"
- then
- die "$(gettext "error: cannot combine merge options (--merge, --strategy, --strategy-option) with am options ($incompatible_opts)")"
- fi
+ die "$(gettext "fatal: cannot combine am options with either interactive or merge options")"
fi
fi
if test -n "$signoff"
then
test -n "$preserve_merges" &&
- die "$(gettext "error: cannot combine '--signoff' with '--preserve-merges'")"
+ die "$(gettext "fatal: cannot combine '--signoff' with '--preserve-merges'")"
git_am_opt="$git_am_opt $signoff"
force_rebase=t
fi
# Note: incompatibility with --interactive is just a strong warning;
# git-rebase.txt caveats with "unless you know what you are doing"
test -n "$rebase_merges" &&
- die "$(gettext "error: cannot combine '--preserve_merges' with '--rebase-merges'")"
+ die "$(gettext "fatal: cannot combine '--preserve-merges' with '--rebase-merges'")"
+
+ test -n "$reschedule_failed_exec" &&
+ die "$(gettext "error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'")"
fi
if test -n "$rebase_merges"
then
test -n "$strategy_opts" &&
- die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy-option'")"
+ die "$(gettext "fatal: cannot combine '--rebase-merges' with '--strategy-option'")"
test -n "$strategy" &&
- die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy'")"
+ die "$(gettext "fatal: cannot combine '--rebase-merges' with '--strategy'")"
fi
if test -z "$rebase_root"
# but this should be done only when upstream and onto are the same
# and if this is not an interactive rebase.
mb=$(git merge-base "$onto" "$orig_head")
-if test -z "$interactive_rebase" && test "$upstream" = "$onto" &&
+if test -z "$actually_interactive" && test "$upstream" = "$onto" &&
test "$mb" = "$onto" && test -z "$restrict_revision" &&
# linear history?
! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
then
if test -n "$verbose"
then
- echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+ if test -z "$mb"
+ then
+ echo "$(eval_gettext "Changes to \$onto:")"
+ else
+ echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+ fi
fi
+ mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
# We want color (if set), but no pager
- GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
+ GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
+fi
+
+if test -z "$actually_interactive" && test "$mb" = "$orig_head"
+then
+ say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
+ GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
+ git checkout -q "$onto^0" || die "could not detach HEAD"
+ # If the $onto is a proper descendant of the tip of the branch, then
+ # we just fast-forwarded.
+ git update-ref ORIG_HEAD $orig_head
+ move_to_original_branch
+ finish_rebase
+ exit 0
fi
test -n "$interactive_rebase" && run_specific_rebase
git checkout -q "$onto^0" || die "could not detach HEAD"
git update-ref ORIG_HEAD $orig_head
-# If the $onto is a proper descendant of the tip of the branch, then
-# we just fast-forwarded.
-if test "$mb" = "$orig_head"
-then
- say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
- move_to_original_branch
- finish_rebase
- exit 0
-fi
-
if test -n "$rebase_root"
then
revisions="$onto..$orig_head"