You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
7.2 KiB
283 lines
7.2 KiB
# This shell script fragment is sourced by git-rebase to implement |
|
# its interactive mode. "git rebase --interactive" makes it easy |
|
# to fix up commits in the middle of a series and rearrange commits. |
|
# |
|
# Copyright (c) 2006 Johannes E. Schindelin |
|
# |
|
# The original idea comes from Eric W. Biederman, in |
|
# https://public-inbox.org/git/m1odwkyuf5.fsf_-_@ebiederm.dsl.xmission.com/ |
|
# |
|
# The file containing rebase commands, comments, and empty lines. |
|
# This file is created by "git rebase -i" then edited by the user. As |
|
# the lines are processed, they are removed from the front of this |
|
# file and written to the tail of $done. |
|
todo="$state_dir"/git-rebase-todo |
|
|
|
GIT_CHERRY_PICK_HELP="$resolvemsg" |
|
export GIT_CHERRY_PICK_HELP |
|
|
|
comment_char=$(git config --get core.commentchar 2>/dev/null) |
|
case "$comment_char" in |
|
'' | auto) |
|
comment_char="#" |
|
;; |
|
?) |
|
;; |
|
*) |
|
comment_char=$(echo "$comment_char" | cut -c1) |
|
;; |
|
esac |
|
|
|
orig_reflog_action="$GIT_REFLOG_ACTION" |
|
|
|
comment_for_reflog () { |
|
case "$orig_reflog_action" in |
|
''|rebase*) |
|
GIT_REFLOG_ACTION="rebase -i ($1)" |
|
export GIT_REFLOG_ACTION |
|
;; |
|
esac |
|
} |
|
|
|
append_todo_help () { |
|
gettext " |
|
Commands: |
|
p, pick <commit> = use commit |
|
r, reword <commit> = use commit, but edit the commit message |
|
e, edit <commit> = use commit, but stop for amending |
|
s, squash <commit> = use commit, but meld into previous commit |
|
f, fixup <commit> = like \"squash\", but discard this commit's log message |
|
x, exec <command> = run command (the rest of the line) using shell |
|
d, drop <commit> = remove commit |
|
l, label <label> = label current HEAD with a name |
|
t, reset <label> = reset HEAD to a label |
|
m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] |
|
. create a merge commit using the original merge commit's |
|
. message (or the oneline, if no original merge commit was |
|
. specified). Use -c <commit> to reword the commit message. |
|
|
|
These lines can be re-ordered; they are executed from top to bottom. |
|
" | git stripspace --comment-lines >>"$todo" |
|
|
|
if test $(get_missing_commit_check_level) = error |
|
then |
|
gettext " |
|
Do not remove any line. Use 'drop' explicitly to remove a commit. |
|
" | git stripspace --comment-lines >>"$todo" |
|
else |
|
gettext " |
|
If you remove a line here THAT COMMIT WILL BE LOST. |
|
" | git stripspace --comment-lines >>"$todo" |
|
fi |
|
} |
|
|
|
die_abort () { |
|
apply_autostash |
|
rm -rf "$state_dir" |
|
die "$1" |
|
} |
|
|
|
has_action () { |
|
test -n "$(git stripspace --strip-comments <"$1")" |
|
} |
|
|
|
git_sequence_editor () { |
|
if test -z "$GIT_SEQUENCE_EDITOR" |
|
then |
|
GIT_SEQUENCE_EDITOR="$(git config sequence.editor)" |
|
if [ -z "$GIT_SEQUENCE_EDITOR" ] |
|
then |
|
GIT_SEQUENCE_EDITOR="$(git var GIT_EDITOR)" || return $? |
|
fi |
|
fi |
|
|
|
eval "$GIT_SEQUENCE_EDITOR" '"$@"' |
|
} |
|
|
|
expand_todo_ids() { |
|
git rebase--helper --expand-ids |
|
} |
|
|
|
collapse_todo_ids() { |
|
git rebase--helper --shorten-ids |
|
} |
|
|
|
# Switch to the branch in $into and notify it in the reflog |
|
checkout_onto () { |
|
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" |
|
output git checkout $onto || die_abort "$(gettext "could not detach HEAD")" |
|
git update-ref ORIG_HEAD $orig_head |
|
} |
|
|
|
get_missing_commit_check_level () { |
|
check_level=$(git config --get rebase.missingCommitsCheck) |
|
check_level=${check_level:-ignore} |
|
# Don't be case sensitive |
|
printf '%s' "$check_level" | tr 'A-Z' 'a-z' |
|
} |
|
|
|
# Initiate an action. If the cannot be any |
|
# further action it may exec a command |
|
# or exit and not return. |
|
# |
|
# TODO: Consider a cleaner return model so it |
|
# never exits and always return 0 if process |
|
# is complete. |
|
# |
|
# Parameter 1 is the action to initiate. |
|
# |
|
# Returns 0 if the action was able to complete |
|
# and if 1 if further processing is required. |
|
initiate_action () { |
|
case "$1" in |
|
continue) |
|
exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \ |
|
--continue |
|
;; |
|
skip) |
|
git rerere clear |
|
exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \ |
|
--continue |
|
;; |
|
edit-todo) |
|
git stripspace --strip-comments <"$todo" >"$todo".new |
|
mv -f "$todo".new "$todo" |
|
collapse_todo_ids |
|
append_todo_help |
|
gettext " |
|
You are editing the todo file of an ongoing interactive rebase. |
|
To continue rebase after editing, run: |
|
git rebase --continue |
|
|
|
" | 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 |
|
test -z "$squash_onto" || |
|
echo "$squash_onto" >"$state_dir"/squash-onto |
|
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" || |
|
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 -n "$force_rebase" || |
|
onto="$(git rebase--helper --skip-unnecessary-picks)" || |
|
die "Could not skip unnecessary pick commands" |
|
|
|
checkout_onto |
|
require_clean_work_tree "rebase" |
|
exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \ |
|
--continue |
|
} |
|
|
|
git_rebase__interactive () { |
|
initiate_action "$action" |
|
ret=$? |
|
if test $ret = 0; then |
|
return 0 |
|
fi |
|
|
|
setup_reflog_action |
|
init_basic_state |
|
|
|
init_revisions_and_shortrevisions |
|
|
|
git rebase--helper --make-script ${keep_empty:+--keep-empty} \ |
|
${rebase_merges:+--rebase-merges} \ |
|
${rebase_cousins:+--rebase-cousins} \ |
|
$revisions ${restrict_revision+^$restrict_revision} >"$todo" || |
|
die "$(gettext "Could not generate todo list")" |
|
|
|
complete_action |
|
}
|
|
|