mirror of
https://github.com/git-for-windows/git.git
synced 2026-03-17 22:19:19 -05:00
Merge branch 'make-builtin-stash-and-rebase-opt-ins'
This branch adds back the scripted versions, then adds the option to use the builtin versions of `stash` and `rebase` by setting `stash.useBuiltin=true` and `rebase.useBuiltin=true`, respectively, (the latter already worked for the top-level `git rebase` command and the `--am` backend, and now it also works for the interactive backend). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -83,6 +83,7 @@
|
||||
/git-interpret-trailers
|
||||
/git-instaweb
|
||||
/git-legacy-rebase
|
||||
/git-legacy-rebase--interactive
|
||||
/git-legacy-stash
|
||||
/git-log
|
||||
/git-ls-files
|
||||
|
||||
1
Makefile
1
Makefile
@@ -639,6 +639,7 @@ SCRIPT_SH += git-request-pull.sh
|
||||
SCRIPT_SH += git-submodule.sh
|
||||
SCRIPT_SH += git-web--browse.sh
|
||||
|
||||
SCRIPT_LIB += git-legacy-rebase--interactive
|
||||
SCRIPT_LIB += git-mergetool--lib
|
||||
SCRIPT_LIB += git-parse-remote
|
||||
SCRIPT_LIB += git-rebase--am
|
||||
|
||||
@@ -143,7 +143,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
|
||||
char *raw_strategies = NULL;
|
||||
enum {
|
||||
NONE = 0, CONTINUE, SKIP, EDIT_TODO, SHOW_CURRENT_PATCH,
|
||||
SHORTEN_OIDS, EXPAND_OIDS, CHECK_TODO_LIST, REARRANGE_SQUASH, ADD_EXEC
|
||||
SHORTEN_OIDS, EXPAND_OIDS, CHECK_TODO_LIST, REARRANGE_SQUASH, ADD_EXEC,
|
||||
MAKE_SCRIPT, SKIP_UNNECESSARY_PICKS,
|
||||
} command = 0;
|
||||
struct option options[] = {
|
||||
OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
|
||||
@@ -196,6 +197,10 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
|
||||
OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_auto),
|
||||
OPT_BOOL(0, "reschedule-failed-exec", &opts.reschedule_failed_exec,
|
||||
N_("automatically re-schedule any `exec` that fails")),
|
||||
OPT_CMDMODE(0, "make-script", &command,
|
||||
N_("make rebase script"), MAKE_SCRIPT),
|
||||
OPT_CMDMODE(0, "skip-unnecessary-picks", &command,
|
||||
N_("skip unnecessary picks"), SKIP_UNNECESSARY_PICKS),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
@@ -267,6 +272,18 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
|
||||
case ADD_EXEC:
|
||||
ret = sequencer_add_exec_commands(the_repository, cmd);
|
||||
break;
|
||||
case MAKE_SCRIPT:
|
||||
ret = sequencer_make_script(the_repository,
|
||||
stdout, argc, argv, flags);
|
||||
break;
|
||||
case SKIP_UNNECESSARY_PICKS: {
|
||||
struct object_id oid;
|
||||
|
||||
ret = skip_unnecessary_picks(the_repository, &oid);
|
||||
if (!ret)
|
||||
printf("%s\n", oid_to_hex(&oid));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BUG("invalid command '%d'", command);
|
||||
}
|
||||
|
||||
283
git-legacy-rebase--interactive.sh
Normal file
283
git-legacy-rebase--interactive.sh
Normal file
@@ -0,0 +1,283 @@
|
||||
# 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--interactive --expand-ids
|
||||
}
|
||||
|
||||
collapse_todo_ids() {
|
||||
git rebase--interactive --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--interactive ${force_rebase:+--no-ff} $allow_empty_message \
|
||||
--continue
|
||||
;;
|
||||
skip)
|
||||
git rerere clear
|
||||
exec git rebase--interactive ${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--interactive --rearrange-squash || exit
|
||||
test -n "$cmd" && git rebase--interactive --add-exec-commands --cmd "$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--interactive --check-todo-list || {
|
||||
ret=$?
|
||||
checkout_onto
|
||||
exit $ret
|
||||
}
|
||||
|
||||
expand_todo_ids
|
||||
|
||||
test -n "$force_rebase" ||
|
||||
onto="$(git rebase--interactive --skip-unnecessary-picks)" ||
|
||||
die "Could not skip unnecessary pick commands"
|
||||
|
||||
checkout_onto
|
||||
require_clean_work_tree "rebase"
|
||||
exec git rebase--interactive ${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--interactive --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
|
||||
}
|
||||
@@ -141,38 +141,6 @@ 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_SEQUENCE_EDITOR=:
|
||||
@@ -182,7 +150,9 @@ run_specific_rebase () {
|
||||
|
||||
if test -n "$interactive_rebase" -a -z "$preserve_merges"
|
||||
then
|
||||
run_interactive
|
||||
. git-legacy-rebase--$type
|
||||
|
||||
git_rebase__$type
|
||||
else
|
||||
. git-rebase--$type
|
||||
|
||||
@@ -202,7 +172,12 @@ run_specific_rebase () {
|
||||
then
|
||||
apply_autostash &&
|
||||
rm -rf "$state_dir" &&
|
||||
die "Nothing to do"
|
||||
if test -n "$interactive_rebase" -a -z "$preserve_merges"
|
||||
then
|
||||
die "error: nothing to do"
|
||||
else
|
||||
die "Nothing to do"
|
||||
fi
|
||||
fi
|
||||
exit $ret
|
||||
}
|
||||
|
||||
@@ -4793,7 +4793,7 @@ static int rewrite_file(const char *path, const char *buf, size_t len)
|
||||
}
|
||||
|
||||
/* skip picking commits whose parents are unchanged */
|
||||
static int skip_unnecessary_picks(struct repository *r, struct object_id *output_oid)
|
||||
int skip_unnecessary_picks(struct repository *r, struct object_id *output_oid)
|
||||
{
|
||||
const char *todo_file = rebase_path_todo();
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
@@ -144,3 +144,5 @@ int read_author_script(const char *path, char **name, char **email, char **date,
|
||||
void parse_strategy_opts(struct replay_opts *opts, char *raw_opts);
|
||||
int write_basic_state(struct replay_opts *opts, const char *head_name,
|
||||
const char *onto, const char *orig_head);
|
||||
|
||||
int skip_unnecessary_picks(struct repository *r, struct object_id *output_oid);
|
||||
|
||||
Reference in New Issue
Block a user