Merge branch 'ws/rebase-p'

Code clean-up.

* ws/rebase-p:
  rebase: remove merges_option and a blank line
  rebase: remove unused code paths from git_rebase__interactive__preserve_merges
  rebase: remove unused code paths from git_rebase__interactive
  rebase: add and use git_rebase__interactive__preserve_merges
  rebase: extract functions out of git_rebase__interactive
  rebase: reindent function git_rebase__interactive
  rebase: update invocation of rebase dot-sourced scripts
  rebase-interactive: simplify pick_on_preserving_merges
This commit is contained in:
Junio C Hamano 2018-04-10 16:28:21 +09:00
commit 57e4b1c67a
4 changed files with 217 additions and 215 deletions

View File

@ -4,15 +4,6 @@
# Copyright (c) 2010 Junio C Hamano. # Copyright (c) 2010 Junio C Hamano.
# #
# The whole contents of this file is run by dot-sourcing it from
# inside a shell function. It used to be that "return"s we see
# below were not inside any function, and expected to return
# to the function that dot-sourced us.
#
# However, older (9.x) versions of FreeBSD /bin/sh misbehave on such a
# construct and continue to run the statements that follow such a "return".
# As a work-around, we introduce an extra layer of a function
# here, and immediately call it after defining it.
git_rebase__am () { git_rebase__am () {
case "$action" in case "$action" in
@ -105,5 +96,3 @@ fi
move_to_original_branch move_to_original_branch
} }
# ... and then we call the whole thing.
git_rebase__am

View File

@ -307,17 +307,14 @@ pick_one_preserving_merges () {
esac esac
sha1=$(git rev-parse $sha1) sha1=$(git rev-parse $sha1)
if test -f "$state_dir"/current-commit if test -f "$state_dir"/current-commit && test "$fast_forward" = t
then then
if test "$fast_forward" = t while read current_commit
then do
while read current_commit git rev-parse HEAD > "$rewritten"/$current_commit
do done <"$state_dir"/current-commit
git rev-parse HEAD > "$rewritten"/$current_commit rm "$state_dir"/current-commit ||
done <"$state_dir"/current-commit die "$(gettext "Cannot write current commit's replacement sha1")"
rm "$state_dir"/current-commit ||
die "$(gettext "Cannot write current commit's replacement sha1")"
fi
fi fi
echo $sha1 >> "$state_dir"/current-commit echo $sha1 >> "$state_dir"/current-commit
@ -743,37 +740,39 @@ get_missing_commit_check_level () {
printf '%s' "$check_level" | tr 'A-Z' 'a-z' printf '%s' "$check_level" | tr 'A-Z' 'a-z'
} }
# The whole contents of this file is run by dot-sourcing it from # Initiate an action. If the cannot be any
# inside a shell function. It used to be that "return"s we see # further action it may exec a command
# below were not inside any function, and expected to return # or exit and not return.
# to the function that dot-sourced us.
# #
# However, older (9.x) versions of FreeBSD /bin/sh misbehave on such a # TODO: Consider a cleaner return model so it
# construct and continue to run the statements that follow such a "return". # never exits and always return 0 if process
# As a work-around, we introduce an extra layer of a function # is complete.
# here, and immediately call it after defining it. #
git_rebase__interactive () { # Parameter 1 is the action to initiate.
#
case "$action" in # Returns 0 if the action was able to complete
continue) # and if 1 if further processing is required.
if test ! -d "$rewritten" initiate_action () {
then case "$1" in
exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \ continue)
--continue if test ! -d "$rewritten"
fi
# do we have anything to commit?
if git diff-index --cached --quiet HEAD --
then
# Nothing to commit -- skip this commit
test ! -f "$GIT_DIR"/CHERRY_PICK_HEAD ||
rm "$GIT_DIR"/CHERRY_PICK_HEAD ||
die "$(gettext "Could not remove CHERRY_PICK_HEAD")"
else
if ! test -f "$author_script"
then then
gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
die "$(eval_gettext "\ --continue
fi
# do we have anything to commit?
if git diff-index --cached --quiet HEAD --
then
# Nothing to commit -- skip this commit
test ! -f "$GIT_DIR"/CHERRY_PICK_HEAD ||
rm "$GIT_DIR"/CHERRY_PICK_HEAD ||
die "$(gettext "Could not remove CHERRY_PICK_HEAD")"
else
if ! test -f "$author_script"
then
gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")}
die "$(eval_gettext "\
You have staged changes in your working tree. You have staged changes in your working tree.
If these changes are meant to be If these changes are meant to be
squashed into the previous commit, run: squashed into the previous commit, run:
@ -788,88 +787,199 @@ In both cases, once you're done, continue with:
git rebase --continue git rebase --continue
")" ")"
fi fi
. "$author_script" || . "$author_script" ||
die "$(gettext "Error trying to find the author identity to amend commit")" die "$(gettext "Error trying to find the author identity to amend commit")"
if test -f "$amend" if test -f "$amend"
then then
current_head=$(git rev-parse --verify HEAD) current_head=$(git rev-parse --verify HEAD)
test "$current_head" = $(cat "$amend") || test "$current_head" = $(cat "$amend") ||
die "$(gettext "\ die "$(gettext "\
You have uncommitted changes in your working tree. Please commit them You have uncommitted changes in your working tree. Please commit them
first and then run 'git rebase --continue' again.")" first and then run 'git rebase --continue' again.")"
do_with_author git commit --amend --no-verify -F "$msg" -e \ do_with_author git commit --amend --no-verify -F "$msg" -e \
${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message || ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
die "$(gettext "Could not commit staged changes.")" die "$(gettext "Could not commit staged changes.")"
else else
do_with_author git commit --no-verify -F "$msg" -e \ do_with_author git commit --no-verify -F "$msg" -e \
${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message || ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
die "$(gettext "Could not commit staged changes.")" die "$(gettext "Could not commit staged changes.")"
fi
fi fi
fi
if test -r "$state_dir"/stopped-sha if test -r "$state_dir"/stopped-sha
then then
record_in_rewritten "$(cat "$state_dir"/stopped-sha)" record_in_rewritten "$(cat "$state_dir"/stopped-sha)"
fi fi
require_clean_work_tree "rebase" require_clean_work_tree "rebase"
do_rest do_rest
return 0 return 0
;; ;;
skip) skip)
git rerere clear git rerere clear
if test ! -d "$rewritten" if test ! -d "$rewritten"
then then
exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \ exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
--continue --continue
fi fi
do_rest do_rest
return 0 return 0
;; ;;
edit-todo) edit-todo)
git stripspace --strip-comments <"$todo" >"$todo".new git stripspace --strip-comments <"$todo" >"$todo".new
mv -f "$todo".new "$todo" mv -f "$todo".new "$todo"
collapse_todo_ids collapse_todo_ids
append_todo_help append_todo_help
gettext " gettext "
You are editing the todo file of an ongoing interactive rebase. You are editing the todo file of an ongoing interactive rebase.
To continue rebase after editing, run: To continue rebase after editing, run:
git rebase --continue git rebase --continue
" | git stripspace --comment-lines >>"$todo" " | git stripspace --comment-lines >>"$todo"
git_sequence_editor "$todo" ||
die "$(gettext "Could not execute editor")"
expand_todo_ids
exit
;;
show-current-patch)
exec git show REBASE_HEAD --
;;
*)
return 1 # continue
;;
esac
}
setup_reflog_action () {
comment_for_reflog start
if test ! -z "$switch_to"
then
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to"
output git checkout "$switch_to" -- ||
die "$(eval_gettext "Could not checkout \$switch_to")"
comment_for_reflog start
fi
}
init_basic_state () {
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
}
init_revisions_and_shortrevisions () {
shorthead=$(git rev-parse --short $orig_head)
shortonto=$(git rev-parse --short $onto)
if test -z "$rebase_root"
# this is now equivalent to ! -z "$upstream"
then
shortupstream=$(git rev-parse --short $upstream)
revisions=$upstream...$orig_head
shortrevisions=$shortupstream..$shorthead
else
revisions=$onto...$orig_head
shortrevisions=$shorthead
fi
}
complete_action() {
test -s "$todo" || echo noop >> "$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##* }
cat >>"$todo" <<EOF
$comment_char $(eval_ngettext \
"Rebase \$shortrevisions onto \$shortonto (\$todocount command)" \
"Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \
"$todocount")
EOF
append_todo_help
gettext "
However, if you remove everything, the rebase will be aborted.
" | git stripspace --comment-lines >>"$todo"
if test -z "$keep_empty"
then
printf '%s\n' "$comment_char $(gettext "Note that empty commits are commented out")" >>"$todo"
fi
has_action "$todo" ||
return 2
cp "$todo" "$todo".backup
collapse_todo_ids
git_sequence_editor "$todo" || git_sequence_editor "$todo" ||
die "$(gettext "Could not execute editor")" die_abort "$(gettext "Could not execute editor")"
has_action "$todo" ||
return 2
git rebase--helper --check-todo-list || {
ret=$?
checkout_onto
exit $ret
}
expand_todo_ids expand_todo_ids
exit test -d "$rewritten" || test -n "$force_rebase" ||
;; onto="$(git rebase--helper --skip-unnecessary-picks)" ||
show-current-patch) die "Could not skip unnecessary pick commands"
exec git show REBASE_HEAD --
;;
esac
comment_for_reflog start checkout_onto
if test -z "$rebase_root" && test ! -d "$rewritten"
then
require_clean_work_tree "rebase"
exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
--continue
fi
do_rest
}
if test ! -z "$switch_to" git_rebase__interactive () {
then initiate_action "$action"
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" ret=$?
output git checkout "$switch_to" -- || if test $ret = 0; then
die "$(eval_gettext "Could not checkout \$switch_to")" return 0
fi
comment_for_reflog start setup_reflog_action
fi init_basic_state
orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")" init_revisions_and_shortrevisions
mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")"
rm -f "$(git rev-parse --git-path REBASE_HEAD)" git rebase--helper --make-script ${keep_empty:+--keep-empty} \
$revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
die "$(gettext "Could not generate todo list")"
complete_action
}
git_rebase__interactive__preserve_merges () {
initiate_action "$action"
ret=$?
if test $ret = 0; then
return 0
fi
setup_reflog_action
init_basic_state
: > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")"
write_basic_state
if test t = "$preserve_merges"
then
if test -z "$rebase_root" if test -z "$rebase_root"
then then
mkdir "$rewritten" && mkdir "$rewritten" &&
@ -883,41 +993,17 @@ then
echo $onto > "$rewritten"/root || echo $onto > "$rewritten"/root ||
die "$(gettext "Could not init rewritten commits")" die "$(gettext "Could not init rewritten commits")"
fi fi
# No cherry-pick because our first pass is to determine
# parents to rewrite and skipping dropped commits would
# prematurely end our probe
merges_option=
else
merges_option="--no-merges --cherry-pick"
fi
shorthead=$(git rev-parse --short $orig_head) init_revisions_and_shortrevisions
shortonto=$(git rev-parse --short $onto)
if test -z "$rebase_root"
# this is now equivalent to ! -z "$upstream"
then
shortupstream=$(git rev-parse --short $upstream)
revisions=$upstream...$orig_head
shortrevisions=$shortupstream..$shorthead
else
revisions=$onto...$orig_head
shortrevisions=$shorthead
fi
if test t != "$preserve_merges"
then
git rebase--helper --make-script ${keep_empty:+--keep-empty} \
$revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
die "$(gettext "Could not generate todo list")"
else
format=$(git config --get rebase.instructionFormat) format=$(git config --get rebase.instructionFormat)
# the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to parse # the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to parse
git rev-list $merges_option --format="%m%H ${format:-%s}" \ git rev-list --format="%m%H ${format:-%s}" \
--reverse --left-right --topo-order \ --reverse --left-right --topo-order \
$revisions ${restrict_revision+^$restrict_revision} | \ $revisions ${restrict_revision+^$restrict_revision} | \
sed -n "s/^>//p" | sed -n "s/^>//p" |
while read -r sha1 rest while read -r sha1 rest
do do
if test -z "$keep_empty" && is_empty_commit $sha1 && ! is_merge_commit $sha1 if test -z "$keep_empty" && is_empty_commit $sha1 && ! is_merge_commit $sha1
then then
comment_out="$comment_char " comment_out="$comment_char "
@ -944,11 +1030,8 @@ else
printf '%s\n' "${comment_out}pick $sha1 $rest" >>"$todo" printf '%s\n' "${comment_out}pick $sha1 $rest" >>"$todo"
fi fi
done done
fi
# Watch for commits that been dropped by --cherry-pick # Watch for commits that been dropped by --cherry-pick
if test t = "$preserve_merges"
then
mkdir "$dropped" mkdir "$dropped"
# Save all non-cherry-picked changes # Save all non-cherry-picked changes
git rev-list $revisions --left-right --cherry-pick | \ git rev-list $revisions --left-right --cherry-pick | \
@ -971,66 +1054,6 @@ then
rm "$rewritten"/$rev rm "$rewritten"/$rev
fi fi
done done
fi
test -s "$todo" || echo noop >> "$todo" complete_action
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##* }
cat >>"$todo" <<EOF
$comment_char $(eval_ngettext \
"Rebase \$shortrevisions onto \$shortonto (\$todocount command)" \
"Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \
"$todocount")
EOF
append_todo_help
gettext "
However, if you remove everything, the rebase will be aborted.
" | git stripspace --comment-lines >>"$todo"
if test -z "$keep_empty"
then
printf '%s\n' "$comment_char $(gettext "Note that empty commits are commented out")" >>"$todo"
fi
has_action "$todo" ||
return 2
cp "$todo" "$todo".backup
collapse_todo_ids
git_sequence_editor "$todo" ||
die_abort "$(gettext "Could not execute editor")"
has_action "$todo" ||
return 2
git rebase--helper --check-todo-list || {
ret=$?
checkout_onto
exit $ret
} }
expand_todo_ids
test -d "$rewritten" || test -n "$force_rebase" ||
onto="$(git rebase--helper --skip-unnecessary-picks)" ||
die "Could not skip unnecessary pick commands"
checkout_onto
if test -z "$rebase_root" && test ! -d "$rewritten"
then
require_clean_work_tree "rebase"
exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
--continue
fi
do_rest
}
# ... and then we call the whole thing.
git_rebase__interactive

View File

@ -104,15 +104,6 @@ finish_rb_merge () {
say All done. say All done.
} }
# The whole contents of this file is run by dot-sourcing it from
# inside a shell function. It used to be that "return"s we see
# below were not inside any function, and expected to return
# to the function that dot-sourced us.
#
# However, older (9.x) versions of FreeBSD /bin/sh misbehave on such a
# construct and continue to run the statements that follow such a "return".
# As a work-around, we introduce an extra layer of a function
# here, and immediately call it after defining it.
git_rebase__merge () { git_rebase__merge () {
case "$action" in case "$action" in
@ -171,5 +162,3 @@ done
finish_rb_merge finish_rb_merge
} }
# ... and then we call the whole thing.
git_rebase__merge

View File

@ -197,6 +197,7 @@ run_specific_rebase () {
autosquash= autosquash=
fi fi
. git-rebase--$type . git-rebase--$type
git_rebase__$type${preserve_merges:+__preserve_merges}
ret=$? ret=$?
if test $ret -eq 0 if test $ret -eq 0
then then