revert(3p/git): Revert merge of git upstream at v2.26.2
This causes cgit to serve error pages, which is undesirable. This reverts commit5229c9b232, reversing changes made tof2b211131f.
This commit is contained in:
parent
6f8fbf4aa4
commit
93ba78d6f4
1006 changed files with 60537 additions and 148724 deletions
414
third_party/git/builtin/rebase.c
vendored
414
third_party/git/builtin/rebase.c
vendored
|
|
@ -29,8 +29,8 @@
|
|||
#include "rebase-interactive.h"
|
||||
|
||||
static char const * const builtin_rebase_usage[] = {
|
||||
N_("git rebase [-i] [options] [--exec <cmd>] "
|
||||
"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
|
||||
N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
|
||||
"[<upstream>] [<branch>]"),
|
||||
N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
|
||||
"--root [<branch>]"),
|
||||
N_("git rebase --continue | --abort | --skip | --edit-todo"),
|
||||
|
|
@ -44,22 +44,14 @@ static GIT_PATH_FUNC(merge_dir, "rebase-merge")
|
|||
|
||||
enum rebase_type {
|
||||
REBASE_UNSPECIFIED = -1,
|
||||
REBASE_APPLY,
|
||||
REBASE_AM,
|
||||
REBASE_MERGE,
|
||||
REBASE_INTERACTIVE,
|
||||
REBASE_PRESERVE_MERGES
|
||||
};
|
||||
|
||||
enum empty_type {
|
||||
EMPTY_UNSPECIFIED = -1,
|
||||
EMPTY_DROP,
|
||||
EMPTY_KEEP,
|
||||
EMPTY_ASK
|
||||
};
|
||||
|
||||
struct rebase_options {
|
||||
enum rebase_type type;
|
||||
enum empty_type empty;
|
||||
const char *default_backend;
|
||||
const char *state_dir;
|
||||
struct commit *upstream;
|
||||
const char *upstream_name;
|
||||
|
|
@ -70,7 +62,7 @@ struct rebase_options {
|
|||
const char *onto_name;
|
||||
const char *revisions;
|
||||
const char *switch_to;
|
||||
int root, root_with_onto;
|
||||
int root;
|
||||
struct object_id *squash_onto;
|
||||
struct commit *restrict_revision;
|
||||
int dont_finish_rebase;
|
||||
|
|
@ -85,6 +77,7 @@ struct rebase_options {
|
|||
const char *action;
|
||||
int signoff;
|
||||
int allow_rerere_autoupdate;
|
||||
int keep_empty;
|
||||
int autosquash;
|
||||
char *gpg_sign_opt;
|
||||
int autostash;
|
||||
|
|
@ -99,8 +92,6 @@ struct rebase_options {
|
|||
|
||||
#define REBASE_OPTIONS_INIT { \
|
||||
.type = REBASE_UNSPECIFIED, \
|
||||
.empty = EMPTY_UNSPECIFIED, \
|
||||
.default_backend = "merge", \
|
||||
.flags = REBASE_NO_QUIET, \
|
||||
.git_am_opts = ARGV_ARRAY_INIT, \
|
||||
.git_format_patch_opt = STRBUF_INIT \
|
||||
|
|
@ -119,9 +110,6 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
|
|||
replay.allow_rerere_auto = opts->allow_rerere_autoupdate;
|
||||
replay.allow_empty = 1;
|
||||
replay.allow_empty_message = opts->allow_empty_message;
|
||||
replay.drop_redundant_commits = (opts->empty == EMPTY_DROP);
|
||||
replay.keep_redundant_commits = (opts->empty == EMPTY_KEEP);
|
||||
replay.quiet = !(opts->flags & REBASE_NO_QUIET);
|
||||
replay.verbose = opts->flags & REBASE_VERBOSE;
|
||||
replay.reschedule_failed_exec = opts->reschedule_failed_exec;
|
||||
replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
|
||||
|
|
@ -129,11 +117,6 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
|
|||
if (opts->strategy_opts)
|
||||
parse_strategy_opts(&replay, opts->strategy_opts);
|
||||
|
||||
if (opts->squash_onto) {
|
||||
oidcpy(&replay.squash_onto, opts->squash_onto);
|
||||
replay.have_squash_onto = 1;
|
||||
}
|
||||
|
||||
return replay;
|
||||
}
|
||||
|
||||
|
|
@ -258,17 +241,21 @@ static int edit_todo_file(unsigned flags)
|
|||
}
|
||||
|
||||
static int get_revision_ranges(struct commit *upstream, struct commit *onto,
|
||||
struct object_id *orig_head, const char **head_hash,
|
||||
const char **head_hash,
|
||||
char **revisions, char **shortrevisions)
|
||||
{
|
||||
struct commit *base_rev = upstream ? upstream : onto;
|
||||
const char *shorthead;
|
||||
struct object_id orig_head;
|
||||
|
||||
*head_hash = find_unique_abbrev(orig_head, GIT_MAX_HEXSZ);
|
||||
if (get_oid("HEAD", &orig_head))
|
||||
return error(_("no HEAD?"));
|
||||
|
||||
*head_hash = find_unique_abbrev(&orig_head, GIT_MAX_HEXSZ);
|
||||
*revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
|
||||
*head_hash);
|
||||
|
||||
shorthead = find_unique_abbrev(orig_head, DEFAULT_ABBREV);
|
||||
shorthead = find_unique_abbrev(&orig_head, DEFAULT_ABBREV);
|
||||
|
||||
if (upstream) {
|
||||
const char *shortrev;
|
||||
|
|
@ -322,8 +309,12 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
|
|||
struct replay_opts replay = get_replay_opts(opts);
|
||||
struct string_list commands = STRING_LIST_INIT_DUP;
|
||||
|
||||
if (get_revision_ranges(opts->upstream, opts->onto, &opts->orig_head,
|
||||
&head_hash, &revisions, &shortrevisions))
|
||||
if (prepare_branch_to_be_rebased(the_repository, &replay,
|
||||
opts->switch_to))
|
||||
return -1;
|
||||
|
||||
if (get_revision_ranges(opts->upstream, opts->onto, &head_hash,
|
||||
&revisions, &shortrevisions))
|
||||
return -1;
|
||||
|
||||
if (init_basic_state(&replay,
|
||||
|
|
@ -341,8 +332,8 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
|
|||
|
||||
argv_array_pushl(&make_script_args, "", revisions, NULL);
|
||||
if (opts->restrict_revision)
|
||||
argv_array_pushf(&make_script_args, "^%s",
|
||||
oid_to_hex(&opts->restrict_revision->object.oid));
|
||||
argv_array_push(&make_script_args,
|
||||
oid_to_hex(&opts->restrict_revision->object.oid));
|
||||
|
||||
ret = sequencer_make_script(the_repository, &todo_list.buf,
|
||||
make_script_args.argc, make_script_args.argv,
|
||||
|
|
@ -371,7 +362,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int run_sequencer_rebase(struct rebase_options *opts,
|
||||
static int run_rebase_interactive(struct rebase_options *opts,
|
||||
enum action command)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
|
|
@ -379,10 +370,10 @@ static int run_sequencer_rebase(struct rebase_options *opts,
|
|||
|
||||
git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
|
||||
|
||||
flags |= opts->keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
|
||||
flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
|
||||
flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
|
||||
flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
|
||||
flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0;
|
||||
flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
|
||||
|
||||
switch (command) {
|
||||
|
|
@ -442,21 +433,6 @@ static int run_sequencer_rebase(struct rebase_options *opts,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int parse_opt_keep_empty(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct rebase_options *opts = opt->value;
|
||||
|
||||
BUG_ON_OPT_ARG(arg);
|
||||
|
||||
/*
|
||||
* If we ever want to remap --keep-empty to --empty=keep, insert:
|
||||
* opts->empty = unset ? EMPTY_UNSPECIFIED : EMPTY_KEEP;
|
||||
*/
|
||||
opts->type = REBASE_MERGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const builtin_rebase_interactive_usage[] = {
|
||||
N_("git rebase--interactive [<options>]"),
|
||||
NULL
|
||||
|
|
@ -470,13 +446,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
|
|||
struct option options[] = {
|
||||
OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"),
|
||||
REBASE_FORCE),
|
||||
{ OPTION_CALLBACK, 'k', "keep-empty", &options, NULL,
|
||||
N_("(DEPRECATED) keep empty commits"),
|
||||
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
|
||||
parse_opt_keep_empty },
|
||||
OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message,
|
||||
N_("allow commits with empty messages"),
|
||||
PARSE_OPT_HIDDEN),
|
||||
OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")),
|
||||
OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message,
|
||||
N_("allow commits with empty messages")),
|
||||
OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")),
|
||||
OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins,
|
||||
N_("keep original branch points of cousins")),
|
||||
|
|
@ -546,26 +518,28 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
|
|||
warning(_("--[no-]rebase-cousins has no effect without "
|
||||
"--rebase-merges"));
|
||||
|
||||
return !!run_sequencer_rebase(&opts, command);
|
||||
return !!run_rebase_interactive(&opts, command);
|
||||
}
|
||||
|
||||
static int is_merge(struct rebase_options *opts)
|
||||
static int is_interactive(struct rebase_options *opts)
|
||||
{
|
||||
return opts->type == REBASE_MERGE ||
|
||||
return opts->type == REBASE_INTERACTIVE ||
|
||||
opts->type == REBASE_PRESERVE_MERGES;
|
||||
}
|
||||
|
||||
static void imply_merge(struct rebase_options *opts, const char *option)
|
||||
static void imply_interactive(struct rebase_options *opts, const char *option)
|
||||
{
|
||||
switch (opts->type) {
|
||||
case REBASE_APPLY:
|
||||
case REBASE_AM:
|
||||
die(_("%s requires an interactive rebase"), option);
|
||||
break;
|
||||
case REBASE_MERGE:
|
||||
case REBASE_INTERACTIVE:
|
||||
case REBASE_PRESERVE_MERGES:
|
||||
break;
|
||||
case REBASE_MERGE:
|
||||
/* we now implement --merge via --interactive */
|
||||
default:
|
||||
opts->type = REBASE_MERGE; /* implied */
|
||||
opts->type = REBASE_INTERACTIVE; /* implied */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -691,8 +665,8 @@ static int rebase_write_basic_state(struct rebase_options *opts)
|
|||
opts->onto ? oid_to_hex(&opts->onto->object.oid) : "");
|
||||
write_file(state_dir_path("orig-head", opts), "%s",
|
||||
oid_to_hex(&opts->orig_head));
|
||||
if (!(opts->flags & REBASE_NO_QUIET))
|
||||
write_file(state_dir_path("quiet", opts), "%s", "");
|
||||
write_file(state_dir_path("quiet", opts), "%s",
|
||||
opts->flags & REBASE_NO_QUIET ? "" : "t");
|
||||
if (opts->flags & REBASE_VERBOSE)
|
||||
write_file(state_dir_path("verbose", opts), "%s", "");
|
||||
if (opts->strategy)
|
||||
|
|
@ -710,7 +684,7 @@ static int rebase_write_basic_state(struct rebase_options *opts)
|
|||
write_file(state_dir_path("gpg_sign_opt", opts), "%s",
|
||||
opts->gpg_sign_opt);
|
||||
if (opts->signoff)
|
||||
write_file(state_dir_path("signoff", opts), "--signoff");
|
||||
write_file(state_dir_path("strategy", opts), "--signoff");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -774,7 +748,7 @@ static int finish_rebase(struct rebase_options *opts)
|
|||
* user should see them.
|
||||
*/
|
||||
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
|
||||
if (opts->type == REBASE_MERGE) {
|
||||
if (opts->type == REBASE_INTERACTIVE) {
|
||||
struct replay_opts replay = REPLAY_OPTS_INIT;
|
||||
|
||||
replay.action = REPLAY_INTERACTIVE_REBASE;
|
||||
|
|
@ -1037,8 +1011,7 @@ static int run_am(struct rebase_options *opts)
|
|||
argv_array_pushl(&format_patch.args, "format-patch", "-k", "--stdout",
|
||||
"--full-index", "--cherry-pick", "--right-only",
|
||||
"--src-prefix=a/", "--dst-prefix=b/", "--no-renames",
|
||||
"--no-cover-letter", "--pretty=mboxrd", "--topo-order",
|
||||
"--no-base", NULL);
|
||||
"--no-cover-letter", "--pretty=mboxrd", "--topo-order", NULL);
|
||||
if (opts->git_format_patch_opt.len)
|
||||
argv_array_split(&format_patch.args,
|
||||
opts->git_format_patch_opt.buf);
|
||||
|
|
@ -1107,8 +1080,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
|
|||
int status;
|
||||
const char *backend, *backend_func;
|
||||
|
||||
if (opts->type == REBASE_MERGE) {
|
||||
/* Run sequencer-based rebase */
|
||||
if (opts->type == REBASE_INTERACTIVE) {
|
||||
/* Run builtin interactive rebase */
|
||||
setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1);
|
||||
if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
|
||||
setenv("GIT_SEQUENCE_EDITOR", ":", 1);
|
||||
|
|
@ -1121,11 +1094,11 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
|
|||
opts->gpg_sign_opt = tmp;
|
||||
}
|
||||
|
||||
status = run_sequencer_rebase(opts, action);
|
||||
status = run_rebase_interactive(opts, action);
|
||||
goto finished_rebase;
|
||||
}
|
||||
|
||||
if (opts->type == REBASE_APPLY) {
|
||||
if (opts->type == REBASE_AM) {
|
||||
status = run_am(opts);
|
||||
goto finished_rebase;
|
||||
}
|
||||
|
|
@ -1145,6 +1118,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
|
|||
add_var(&script_snippet, "revisions", opts->revisions);
|
||||
add_var(&script_snippet, "restrict_revision", opts->restrict_revision ?
|
||||
oid_to_hex(&opts->restrict_revision->object.oid) : NULL);
|
||||
add_var(&script_snippet, "GIT_QUIET",
|
||||
opts->flags & REBASE_NO_QUIET ? "" : "t");
|
||||
sq_quote_argv_pretty(&buf, opts->git_am_opts.argv);
|
||||
add_var(&script_snippet, "git_am_opt", buf.buf);
|
||||
strbuf_release(&buf);
|
||||
|
|
@ -1162,6 +1137,7 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
|
|||
opts->allow_rerere_autoupdate ?
|
||||
opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ?
|
||||
"--rerere-autoupdate" : "--no-rerere-autoupdate" : "");
|
||||
add_var(&script_snippet, "keep_empty", opts->keep_empty ? "yes" : "");
|
||||
add_var(&script_snippet, "autosquash", opts->autosquash ? "t" : "");
|
||||
add_var(&script_snippet, "gpg_sign_opt", opts->gpg_sign_opt);
|
||||
add_var(&script_snippet, "cmd", opts->cmd);
|
||||
|
|
@ -1179,7 +1155,7 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
|
|||
add_var(&script_snippet, "git_format_patch_opt",
|
||||
opts->git_format_patch_opt.buf);
|
||||
|
||||
if (is_merge(opts) &&
|
||||
if (is_interactive(opts) &&
|
||||
!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
|
||||
strbuf_addstr(&script_snippet,
|
||||
"GIT_SEQUENCE_EDITOR=:; export GIT_SEQUENCE_EDITOR; ");
|
||||
|
|
@ -1204,8 +1180,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
|
|||
finished_rebase:
|
||||
if (opts->dont_finish_rebase)
|
||||
; /* do nothing */
|
||||
else if (opts->type == REBASE_MERGE)
|
||||
; /* merge backend cleans up after itself */
|
||||
else if (opts->type == REBASE_INTERACTIVE)
|
||||
; /* interactive rebase cleans up after itself */
|
||||
else if (status == 0) {
|
||||
if (!file_exists(state_dir_path("stopped-sha", opts)))
|
||||
finish_rebase(opts);
|
||||
|
|
@ -1263,10 +1239,6 @@ static int rebase_config(const char *var, const char *value, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(var, "rebase.backend")) {
|
||||
return git_config_string(&opts->default_backend, var, value);
|
||||
}
|
||||
|
||||
return git_default_config(var, value, data);
|
||||
}
|
||||
|
||||
|
|
@ -1288,60 +1260,28 @@ static int is_linear_history(struct commit *from, struct commit *to)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int can_fast_forward(struct commit *onto, struct commit *upstream,
|
||||
struct commit *restrict_revision,
|
||||
struct object_id *head_oid, struct object_id *merge_base)
|
||||
static int can_fast_forward(struct commit *onto, struct object_id *head_oid,
|
||||
struct object_id *merge_base)
|
||||
{
|
||||
struct commit *head = lookup_commit(the_repository, head_oid);
|
||||
struct commit_list *merge_bases = NULL;
|
||||
int res = 0;
|
||||
struct commit_list *merge_bases;
|
||||
int res;
|
||||
|
||||
if (!head)
|
||||
goto done;
|
||||
return 0;
|
||||
|
||||
merge_bases = get_merge_bases(onto, head);
|
||||
if (!merge_bases || merge_bases->next) {
|
||||
if (merge_bases && !merge_bases->next) {
|
||||
oidcpy(merge_base, &merge_bases->item->object.oid);
|
||||
res = oideq(merge_base, &onto->object.oid);
|
||||
} else {
|
||||
oidcpy(merge_base, &null_oid);
|
||||
goto done;
|
||||
res = 0;
|
||||
}
|
||||
|
||||
oidcpy(merge_base, &merge_bases->item->object.oid);
|
||||
if (!oideq(merge_base, &onto->object.oid))
|
||||
goto done;
|
||||
|
||||
if (restrict_revision && !oideq(&restrict_revision->object.oid, merge_base))
|
||||
goto done;
|
||||
|
||||
if (!upstream)
|
||||
goto done;
|
||||
|
||||
free_commit_list(merge_bases);
|
||||
merge_bases = get_merge_bases(upstream, head);
|
||||
if (!merge_bases || merge_bases->next)
|
||||
goto done;
|
||||
|
||||
if (!oideq(&onto->object.oid, &merge_bases->item->object.oid))
|
||||
goto done;
|
||||
|
||||
res = 1;
|
||||
|
||||
done:
|
||||
free_commit_list(merge_bases);
|
||||
return res && is_linear_history(onto, head);
|
||||
}
|
||||
|
||||
static int parse_opt_am(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct rebase_options *opts = opt->value;
|
||||
|
||||
BUG_ON_OPT_NEG(unset);
|
||||
BUG_ON_OPT_ARG(arg);
|
||||
|
||||
opts->type = REBASE_APPLY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -i followed by -m is still -i */
|
||||
static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
|
|
@ -1350,7 +1290,7 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
|
|||
BUG_ON_OPT_NEG(unset);
|
||||
BUG_ON_OPT_ARG(arg);
|
||||
|
||||
if (!is_merge(opts))
|
||||
if (!is_interactive(opts))
|
||||
opts->type = REBASE_MERGE;
|
||||
|
||||
return 0;
|
||||
|
|
@ -1365,35 +1305,12 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
|
|||
BUG_ON_OPT_NEG(unset);
|
||||
BUG_ON_OPT_ARG(arg);
|
||||
|
||||
opts->type = REBASE_MERGE;
|
||||
opts->type = REBASE_INTERACTIVE;
|
||||
opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum empty_type parse_empty_value(const char *value)
|
||||
{
|
||||
if (!strcasecmp(value, "drop"))
|
||||
return EMPTY_DROP;
|
||||
else if (!strcasecmp(value, "keep"))
|
||||
return EMPTY_KEEP;
|
||||
else if (!strcasecmp(value, "ask"))
|
||||
return EMPTY_ASK;
|
||||
|
||||
die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value);
|
||||
}
|
||||
|
||||
static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct rebase_options *options = opt->value;
|
||||
enum empty_type value = parse_empty_value(arg);
|
||||
|
||||
BUG_ON_OPT_NEG(unset);
|
||||
|
||||
options->empty = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NORETURN error_on_missing_default_upstream(void)
|
||||
{
|
||||
struct branch *current_branch = branch_get(NULL);
|
||||
|
|
@ -1429,14 +1346,14 @@ static void set_reflog_action(struct rebase_options *options)
|
|||
const char *env;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (!is_merge(options))
|
||||
if (!is_interactive(options))
|
||||
return;
|
||||
|
||||
env = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
|
||||
if (env && strcmp("rebase", env))
|
||||
return; /* only override it if it is "rebase" */
|
||||
|
||||
strbuf_addf(&buf, "rebase (%s)", options->action);
|
||||
strbuf_addf(&buf, "rebase -i (%s)", options->action);
|
||||
setenv(GIT_REFLOG_ACTION_ENVIRONMENT, buf.buf, 1);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
|
@ -1459,7 +1376,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
struct rebase_options options = REBASE_OPTIONS_INIT;
|
||||
const char *branch_name;
|
||||
int ret, flags, total_argc, in_progress = 0;
|
||||
int keep_base = 0;
|
||||
int ok_to_skip_pre_rebase = 0;
|
||||
struct strbuf msg = STRBUF_INIT;
|
||||
struct strbuf revisions = STRBUF_INIT;
|
||||
|
|
@ -1474,18 +1390,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
struct object_id squash_onto;
|
||||
char *squash_onto_name = NULL;
|
||||
int reschedule_failed_exec = -1;
|
||||
int allow_preemptive_ff = 1;
|
||||
struct option builtin_rebase_options[] = {
|
||||
OPT_STRING(0, "onto", &options.onto_name,
|
||||
N_("revision"),
|
||||
N_("rebase onto given branch instead of upstream")),
|
||||
OPT_BOOL(0, "keep-base", &keep_base,
|
||||
N_("use the merge-base of upstream and branch as the current base")),
|
||||
OPT_BOOL(0, "no-verify", &ok_to_skip_pre_rebase,
|
||||
N_("allow pre-rebase hook to run")),
|
||||
OPT_NEGBIT('q', "quiet", &options.flags,
|
||||
N_("be quiet. implies --no-stat"),
|
||||
REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
|
||||
REBASE_NO_QUIET| REBASE_VERBOSE | REBASE_DIFFSTAT),
|
||||
OPT_BIT('v', "verbose", &options.flags,
|
||||
N_("display a diffstat of what changed upstream"),
|
||||
REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
|
||||
|
|
@ -1526,10 +1439,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
OPT_CMDMODE(0, "show-current-patch", &action,
|
||||
N_("show the patch file being applied or merged"),
|
||||
ACTION_SHOW_CURRENT_PATCH),
|
||||
{ OPTION_CALLBACK, 0, "apply", &options, NULL,
|
||||
N_("use apply strategies to rebase"),
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
|
||||
parse_opt_am },
|
||||
{ OPTION_CALLBACK, 'm', "merge", &options, NULL,
|
||||
N_("use merging strategies to rebase"),
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
|
||||
|
|
@ -1538,18 +1447,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
N_("let the user edit the list of commits to rebase"),
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
|
||||
parse_opt_interactive },
|
||||
OPT_SET_INT_F('p', "preserve-merges", &options.type,
|
||||
N_("(DEPRECATED) try to recreate merges instead of "
|
||||
"ignoring them"),
|
||||
REBASE_PRESERVE_MERGES, PARSE_OPT_HIDDEN),
|
||||
OPT_SET_INT('p', "preserve-merges", &options.type,
|
||||
N_("(DEPRECATED) try to recreate merges instead of "
|
||||
"ignoring them"), REBASE_PRESERVE_MERGES),
|
||||
OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
|
||||
OPT_CALLBACK_F(0, "empty", &options, "{drop,keep,ask}",
|
||||
N_("how to handle commits that become empty"),
|
||||
PARSE_OPT_NONEG, parse_opt_empty),
|
||||
{ OPTION_CALLBACK, 'k', "keep-empty", &options, NULL,
|
||||
N_("(DEPRECATED) keep empty commits"),
|
||||
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
|
||||
parse_opt_keep_empty },
|
||||
OPT_BOOL('k', "keep-empty", &options.keep_empty,
|
||||
N_("preserve empty commits during rebase")),
|
||||
OPT_BOOL(0, "autosquash", &options.autosquash,
|
||||
N_("move commits that begin with "
|
||||
"squash!/fixup! under -i")),
|
||||
|
|
@ -1561,10 +1464,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
OPT_STRING_LIST('x', "exec", &exec, N_("exec"),
|
||||
N_("add exec lines after each commit of the "
|
||||
"editable list")),
|
||||
OPT_BOOL_F(0, "allow-empty-message",
|
||||
&options.allow_empty_message,
|
||||
N_("allow rebasing commits with empty messages"),
|
||||
PARSE_OPT_HIDDEN),
|
||||
OPT_BOOL(0, "allow-empty-message",
|
||||
&options.allow_empty_message,
|
||||
N_("allow rebasing commits with empty messages")),
|
||||
{OPTION_STRING, 'r', "rebase-merges", &rebase_merges,
|
||||
N_("mode"),
|
||||
N_("try to rebase merges instead of skipping them"),
|
||||
|
|
@ -1604,7 +1506,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
die(_("It looks like 'git am' is in progress. Cannot rebase."));
|
||||
|
||||
if (is_directory(apply_dir())) {
|
||||
options.type = REBASE_APPLY;
|
||||
options.type = REBASE_AM;
|
||||
options.state_dir = apply_dir();
|
||||
} else if (is_directory(merge_dir())) {
|
||||
strbuf_reset(&buf);
|
||||
|
|
@ -1616,7 +1518,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "%s/interactive", merge_dir());
|
||||
if(file_exists(buf.buf)) {
|
||||
options.type = REBASE_MERGE;
|
||||
options.type = REBASE_INTERACTIVE;
|
||||
options.flags |= REBASE_INTERACTIVE_EXPLICIT;
|
||||
} else
|
||||
options.type = REBASE_MERGE;
|
||||
|
|
@ -1645,23 +1547,16 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
warning(_("git rebase --preserve-merges is deprecated. "
|
||||
"Use --rebase-merges instead."));
|
||||
|
||||
if (keep_base) {
|
||||
if (options.onto_name)
|
||||
die(_("cannot combine '--keep-base' with '--onto'"));
|
||||
if (options.root)
|
||||
die(_("cannot combine '--keep-base' with '--root'"));
|
||||
}
|
||||
|
||||
if (action != ACTION_NONE && !in_progress)
|
||||
die(_("No rebase in progress?"));
|
||||
setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
|
||||
|
||||
if (action == ACTION_EDIT_TODO && !is_merge(&options))
|
||||
if (action == ACTION_EDIT_TODO && !is_interactive(&options))
|
||||
die(_("The --edit-todo action can only be used during "
|
||||
"interactive rebase."));
|
||||
|
||||
if (trace2_is_enabled()) {
|
||||
if (is_merge(&options))
|
||||
if (is_interactive(&options))
|
||||
trace2_cmd_mode("interactive");
|
||||
else if (exec.nr)
|
||||
trace2_cmd_mode("interactive-exec");
|
||||
|
|
@ -1737,7 +1632,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
goto cleanup;
|
||||
}
|
||||
case ACTION_QUIT: {
|
||||
if (options.type == REBASE_MERGE) {
|
||||
if (options.type == REBASE_INTERACTIVE) {
|
||||
struct replay_opts replay = REPLAY_OPTS_INIT;
|
||||
|
||||
replay.action = REPLAY_INTERACTIVE_REBASE;
|
||||
|
|
@ -1786,20 +1681,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
state_dir_base, cmd_live_rebase, buf.buf);
|
||||
}
|
||||
|
||||
if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
|
||||
(action != ACTION_NONE) ||
|
||||
(exec.nr > 0) ||
|
||||
options.autosquash) {
|
||||
allow_preemptive_ff = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < options.git_am_opts.argc; i++) {
|
||||
const char *option = options.git_am_opts.argv[i], *p;
|
||||
if (!strcmp(option, "--committer-date-is-author-date") ||
|
||||
!strcmp(option, "--ignore-date") ||
|
||||
!strcmp(option, "--whitespace=fix") ||
|
||||
!strcmp(option, "--whitespace=strip"))
|
||||
allow_preemptive_ff = 0;
|
||||
options.flags |= REBASE_FORCE;
|
||||
else if (skip_prefix(option, "-C", &p)) {
|
||||
while (*p)
|
||||
if (!isdigit(*(p++)))
|
||||
|
|
@ -1819,8 +1707,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
if (!(options.flags & REBASE_NO_QUIET))
|
||||
argv_array_push(&options.git_am_opts, "-q");
|
||||
|
||||
if (options.empty != EMPTY_UNSPECIFIED)
|
||||
imply_merge(&options, "--empty");
|
||||
if (options.keep_empty)
|
||||
imply_interactive(&options, "--keep-empty");
|
||||
|
||||
if (gpg_sign) {
|
||||
free(options.gpg_sign_opt);
|
||||
|
|
@ -1830,7 +1718,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
if (exec.nr) {
|
||||
int i;
|
||||
|
||||
imply_merge(&options, "--exec");
|
||||
imply_interactive(&options, "--exec");
|
||||
|
||||
strbuf_reset(&buf);
|
||||
for (i = 0; i < exec.nr; i++)
|
||||
|
|
@ -1846,7 +1734,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
else if (strcmp("no-rebase-cousins", rebase_merges))
|
||||
die(_("Unknown mode: %s"), rebase_merges);
|
||||
options.rebase_merges = 1;
|
||||
imply_merge(&options, "--rebase-merges");
|
||||
imply_interactive(&options, "--rebase-merges");
|
||||
}
|
||||
|
||||
if (strategy_options.nr) {
|
||||
|
|
@ -1865,9 +1753,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
if (options.strategy) {
|
||||
options.strategy = xstrdup(options.strategy);
|
||||
switch (options.type) {
|
||||
case REBASE_APPLY:
|
||||
case REBASE_AM:
|
||||
die(_("--strategy requires --merge or --interactive"));
|
||||
case REBASE_MERGE:
|
||||
case REBASE_INTERACTIVE:
|
||||
case REBASE_PRESERVE_MERGES:
|
||||
/* compatible */
|
||||
break;
|
||||
|
|
@ -1880,65 +1769,47 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
|
||||
if (options.type == REBASE_MERGE)
|
||||
imply_merge(&options, "--merge");
|
||||
imply_interactive(&options, "--merge");
|
||||
|
||||
if (options.root && !options.onto_name)
|
||||
imply_merge(&options, "--root without --onto");
|
||||
imply_interactive(&options, "--root without --onto");
|
||||
|
||||
if (isatty(2) && options.flags & REBASE_NO_QUIET)
|
||||
strbuf_addstr(&options.git_format_patch_opt, " --progress");
|
||||
|
||||
if (options.git_am_opts.argc || options.type == REBASE_APPLY) {
|
||||
/* all am options except -q are compatible only with --apply */
|
||||
for (i = options.git_am_opts.argc - 1; i >= 0; i--)
|
||||
if (strcmp(options.git_am_opts.argv[i], "-q"))
|
||||
break;
|
||||
|
||||
if (i >= 0) {
|
||||
if (is_merge(&options))
|
||||
die(_("cannot combine apply options with "
|
||||
"merge options"));
|
||||
else
|
||||
options.type = REBASE_APPLY;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.type == REBASE_UNSPECIFIED) {
|
||||
if (!strcmp(options.default_backend, "merge"))
|
||||
imply_merge(&options, "--merge");
|
||||
else if (!strcmp(options.default_backend, "apply"))
|
||||
options.type = REBASE_APPLY;
|
||||
else
|
||||
die(_("Unknown rebase backend: %s"),
|
||||
options.default_backend);
|
||||
}
|
||||
|
||||
switch (options.type) {
|
||||
case REBASE_MERGE:
|
||||
case REBASE_INTERACTIVE:
|
||||
case REBASE_PRESERVE_MERGES:
|
||||
options.state_dir = merge_dir();
|
||||
break;
|
||||
case REBASE_APPLY:
|
||||
case REBASE_AM:
|
||||
options.state_dir = apply_dir();
|
||||
break;
|
||||
default:
|
||||
BUG("options.type was just set above; should be unreachable.");
|
||||
/* the default rebase backend is `--am` */
|
||||
options.type = REBASE_AM;
|
||||
options.state_dir = apply_dir();
|
||||
break;
|
||||
}
|
||||
|
||||
if (options.empty == EMPTY_UNSPECIFIED) {
|
||||
if (options.flags & REBASE_INTERACTIVE_EXPLICIT)
|
||||
options.empty = EMPTY_ASK;
|
||||
else if (exec.nr > 0)
|
||||
options.empty = EMPTY_KEEP;
|
||||
else
|
||||
options.empty = EMPTY_DROP;
|
||||
}
|
||||
if (reschedule_failed_exec > 0 && !is_merge(&options))
|
||||
if (reschedule_failed_exec > 0 && !is_interactive(&options))
|
||||
die(_("--reschedule-failed-exec requires "
|
||||
"--exec or --interactive"));
|
||||
if (reschedule_failed_exec >= 0)
|
||||
options.reschedule_failed_exec = reschedule_failed_exec;
|
||||
|
||||
if (options.git_am_opts.argc) {
|
||||
/* all am options except -q are compatible only with --am */
|
||||
for (i = options.git_am_opts.argc - 1; i >= 0; i--)
|
||||
if (strcmp(options.git_am_opts.argv[i], "-q"))
|
||||
break;
|
||||
|
||||
if (is_interactive(&options) && i >= 0)
|
||||
die(_("cannot combine am options with either "
|
||||
"interactive or merge options"));
|
||||
}
|
||||
|
||||
if (options.signoff) {
|
||||
if (options.type == REBASE_PRESERVE_MERGES)
|
||||
die("cannot combine '--signoff' with "
|
||||
|
|
@ -1962,6 +1833,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
"'--reschedule-failed-exec'"));
|
||||
}
|
||||
|
||||
if (options.rebase_merges) {
|
||||
if (strategy_options.nr)
|
||||
die(_("cannot combine '--rebase-merges' with "
|
||||
"'--strategy-option'"));
|
||||
if (options.strategy)
|
||||
die(_("cannot combine '--rebase-merges' with "
|
||||
"'--strategy'"));
|
||||
}
|
||||
|
||||
if (!options.root) {
|
||||
if (argc < 1) {
|
||||
struct branch *branch;
|
||||
|
|
@ -1992,9 +1872,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
options.squash_onto = &squash_onto;
|
||||
options.onto_name = squash_onto_name =
|
||||
xstrdup(oid_to_hex(&squash_onto));
|
||||
} else
|
||||
options.root_with_onto = 1;
|
||||
|
||||
}
|
||||
options.upstream_name = NULL;
|
||||
options.upstream = NULL;
|
||||
if (argc > 1)
|
||||
|
|
@ -2004,22 +1882,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
|
||||
/* Make sure the branch to rebase onto is valid. */
|
||||
if (keep_base) {
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addstr(&buf, options.upstream_name);
|
||||
strbuf_addstr(&buf, "...");
|
||||
options.onto_name = xstrdup(buf.buf);
|
||||
} else if (!options.onto_name)
|
||||
if (!options.onto_name)
|
||||
options.onto_name = options.upstream_name;
|
||||
if (strstr(options.onto_name, "...")) {
|
||||
if (get_oid_mb(options.onto_name, &merge_base) < 0) {
|
||||
if (keep_base)
|
||||
die(_("'%s': need exactly one merge base with branch"),
|
||||
options.upstream_name);
|
||||
else
|
||||
die(_("'%s': need exactly one merge base"),
|
||||
options.onto_name);
|
||||
}
|
||||
if (get_oid_mb(options.onto_name, &merge_base) < 0)
|
||||
die(_("'%s': need exactly one merge base"),
|
||||
options.onto_name);
|
||||
options.onto = lookup_commit_or_die(&merge_base,
|
||||
options.onto_name);
|
||||
} else {
|
||||
|
|
@ -2044,11 +1912,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
/* Is it a local branch? */
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "refs/heads/%s", branch_name);
|
||||
if (!read_ref(buf.buf, &options.orig_head)) {
|
||||
die_if_checked_out(buf.buf, 1);
|
||||
if (!read_ref(buf.buf, &options.orig_head))
|
||||
options.head_name = xstrdup(buf.buf);
|
||||
/* If not is it a valid ref (branch or commit)? */
|
||||
} else if (!get_oid(branch_name, &options.orig_head))
|
||||
else if (!get_oid(branch_name, &options.orig_head))
|
||||
options.head_name = NULL;
|
||||
else
|
||||
die(_("fatal: no such branch/commit '%s'"),
|
||||
|
|
@ -2101,6 +1968,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
state_dir_path("autostash", &options);
|
||||
struct child_process stash = CHILD_PROCESS_INIT;
|
||||
struct object_id oid;
|
||||
struct commit *head =
|
||||
lookup_commit_reference(the_repository,
|
||||
&options.orig_head);
|
||||
|
||||
argv_array_pushl(&stash.args,
|
||||
"stash", "create", "autostash", NULL);
|
||||
|
|
@ -2121,9 +1991,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
options.state_dir);
|
||||
write_file(autostash, "%s", oid_to_hex(&oid));
|
||||
printf(_("Created autostash: %s\n"), buf.buf);
|
||||
if (reset_head(NULL, "reset --hard",
|
||||
if (reset_head(&head->object.oid, "reset --hard",
|
||||
NULL, RESET_HEAD_HARD, NULL, NULL) < 0)
|
||||
die(_("could not reset --hard"));
|
||||
printf(_("HEAD is now at %s"),
|
||||
find_unique_abbrev(&head->object.oid,
|
||||
DEFAULT_ABBREV));
|
||||
strbuf_reset(&buf);
|
||||
pp_commit_easy(CMIT_FMT_ONELINE, head, &buf);
|
||||
if (buf.len > 0)
|
||||
printf(" %s", buf.buf);
|
||||
putchar('\n');
|
||||
|
||||
if (discard_index(the_repository->index) < 0 ||
|
||||
repo_read_index(the_repository) < 0)
|
||||
|
|
@ -2144,25 +2022,31 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
|
||||
/*
|
||||
* Check if we are already based on onto with linear history,
|
||||
* in which case we could fast-forward without replacing the commits
|
||||
* with new commits recreated by replaying their changes.
|
||||
*
|
||||
* Note that can_fast_forward() initializes merge_base, so we have to
|
||||
* call it before checking allow_preemptive_ff.
|
||||
* but this should be done only when upstream and onto are the same
|
||||
* and if this is not an interactive rebase.
|
||||
*/
|
||||
if (can_fast_forward(options.onto, options.upstream, options.restrict_revision,
|
||||
&options.orig_head, &merge_base) &&
|
||||
allow_preemptive_ff) {
|
||||
if (can_fast_forward(options.onto, &options.orig_head, &merge_base) &&
|
||||
!is_interactive(&options) && !options.restrict_revision &&
|
||||
options.upstream &&
|
||||
!oidcmp(&options.upstream->object.oid, &options.onto->object.oid)) {
|
||||
int flag;
|
||||
|
||||
if (!(options.flags & REBASE_FORCE)) {
|
||||
/* Lazily switch to the target branch if needed... */
|
||||
if (options.switch_to) {
|
||||
struct object_id oid;
|
||||
|
||||
if (get_oid(options.switch_to, &oid) < 0) {
|
||||
ret = !!error(_("could not parse '%s'"),
|
||||
options.switch_to);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "%s: checkout %s",
|
||||
getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
|
||||
options.switch_to);
|
||||
if (reset_head(&options.orig_head, "checkout",
|
||||
if (reset_head(&oid, "checkout",
|
||||
options.head_name,
|
||||
RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
|
||||
NULL, buf.buf) < 0) {
|
||||
|
|
@ -2227,7 +2111,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
diff_flush(&opts);
|
||||
}
|
||||
|
||||
if (is_merge(&options))
|
||||
if (is_interactive(&options))
|
||||
goto run_rebase;
|
||||
|
||||
/* Detach HEAD and reset the tree */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue