зеркало из https://github.com/microsoft/git.git
Merge branch 'pw/rebase-i-orig-head'
"git rebase -i" did not store ORIG_HEAD correctly. * pw/rebase-i-orig-head: rebase -i: simplify get_revision_ranges() rebase -i: use struct object_id when writing state rebase -i: use struct object_id rather than looking up commit rebase -i: stop overwriting ORIG_HEAD buffer
This commit is contained in:
Коммит
c042c455d4
|
@ -270,15 +270,14 @@ 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,
|
||||
char **revisions, char **shortrevisions)
|
||||
struct object_id *orig_head, char **revisions,
|
||||
char **shortrevisions)
|
||||
{
|
||||
struct commit *base_rev = upstream ? upstream : onto;
|
||||
const char *shorthead;
|
||||
|
||||
*head_hash = find_unique_abbrev(orig_head, GIT_MAX_HEXSZ);
|
||||
*revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
|
||||
*head_hash);
|
||||
oid_to_hex(orig_head));
|
||||
|
||||
shorthead = find_unique_abbrev(orig_head, DEFAULT_ABBREV);
|
||||
|
||||
|
@ -296,7 +295,8 @@ static int get_revision_ranges(struct commit *upstream, struct commit *onto,
|
|||
}
|
||||
|
||||
static int init_basic_state(struct replay_opts *opts, const char *head_name,
|
||||
struct commit *onto, const char *orig_head)
|
||||
struct commit *onto,
|
||||
const struct object_id *orig_head)
|
||||
{
|
||||
FILE *interactive;
|
||||
|
||||
|
@ -327,7 +327,6 @@ static void split_exec_commands(const char *cmd, struct string_list *commands)
|
|||
static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
|
||||
{
|
||||
int ret;
|
||||
const char *head_hash = NULL;
|
||||
char *revisions = NULL, *shortrevisions = NULL;
|
||||
struct strvec make_script_args = STRVEC_INIT;
|
||||
struct todo_list todo_list = TODO_LIST_INIT;
|
||||
|
@ -335,12 +334,12 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
|
|||
struct string_list commands = STRING_LIST_INIT_DUP;
|
||||
|
||||
if (get_revision_ranges(opts->upstream, opts->onto, &opts->orig_head,
|
||||
&head_hash, &revisions, &shortrevisions))
|
||||
&revisions, &shortrevisions))
|
||||
return -1;
|
||||
|
||||
if (init_basic_state(&replay,
|
||||
opts->head_name ? opts->head_name : "detached HEAD",
|
||||
opts->onto, head_hash)) {
|
||||
opts->onto, &opts->orig_head)) {
|
||||
free(revisions);
|
||||
free(shortrevisions);
|
||||
|
||||
|
@ -370,8 +369,9 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
|
|||
|
||||
split_exec_commands(opts->cmd, &commands);
|
||||
ret = complete_action(the_repository, &replay, flags,
|
||||
shortrevisions, opts->onto_name, opts->onto, head_hash,
|
||||
&commands, opts->autosquash, &todo_list);
|
||||
shortrevisions, opts->onto_name, opts->onto,
|
||||
&opts->orig_head, &commands, opts->autosquash,
|
||||
&todo_list);
|
||||
}
|
||||
|
||||
string_list_clear(&commands, 0);
|
||||
|
|
15
sequencer.c
15
sequencer.c
|
@ -2690,7 +2690,7 @@ static void write_strategy_opts(struct replay_opts *opts)
|
|||
}
|
||||
|
||||
int write_basic_state(struct replay_opts *opts, const char *head_name,
|
||||
struct commit *onto, const char *orig_head)
|
||||
struct commit *onto, const struct object_id *orig_head)
|
||||
{
|
||||
if (head_name)
|
||||
write_file(rebase_path_head_name(), "%s\n", head_name);
|
||||
|
@ -2698,7 +2698,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
|
|||
write_file(rebase_path_onto(), "%s\n",
|
||||
oid_to_hex(&onto->object.oid));
|
||||
if (orig_head)
|
||||
write_file(rebase_path_orig_head(), "%s\n", orig_head);
|
||||
write_file(rebase_path_orig_head(), "%s\n",
|
||||
oid_to_hex(orig_head));
|
||||
|
||||
if (opts->quiet)
|
||||
write_file(rebase_path_quiet(), "%s", "");
|
||||
|
@ -3964,21 +3965,17 @@ static int run_git_checkout(struct repository *r, struct replay_opts *opts,
|
|||
|
||||
static int checkout_onto(struct repository *r, struct replay_opts *opts,
|
||||
const char *onto_name, const struct object_id *onto,
|
||||
const char *orig_head)
|
||||
const struct object_id *orig_head)
|
||||
{
|
||||
struct object_id oid;
|
||||
const char *action = reflog_message(opts, "start", "checkout %s", onto_name);
|
||||
|
||||
if (get_oid(orig_head, &oid))
|
||||
return error(_("%s: not a valid OID"), orig_head);
|
||||
|
||||
if (run_git_checkout(r, opts, oid_to_hex(onto), action)) {
|
||||
apply_autostash(rebase_path_autostash());
|
||||
sequencer_remove_state(opts);
|
||||
return error(_("could not detach HEAD"));
|
||||
}
|
||||
|
||||
return update_ref(NULL, "ORIG_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
|
||||
return update_ref(NULL, "ORIG_HEAD", orig_head, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
|
||||
}
|
||||
|
||||
static int stopped_at_head(struct repository *r)
|
||||
|
@ -5294,7 +5291,7 @@ static int skip_unnecessary_picks(struct repository *r,
|
|||
|
||||
int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
|
||||
const char *shortrevisions, const char *onto_name,
|
||||
struct commit *onto, const char *orig_head,
|
||||
struct commit *onto, const struct object_id *orig_head,
|
||||
struct string_list *commands, unsigned autosquash,
|
||||
struct todo_list *todo_list)
|
||||
{
|
||||
|
|
|
@ -161,8 +161,9 @@ void todo_list_add_exec_commands(struct todo_list *todo_list,
|
|||
struct string_list *commands);
|
||||
int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
|
||||
const char *shortrevisions, const char *onto_name,
|
||||
struct commit *onto, const char *orig_head, struct string_list *commands,
|
||||
unsigned autosquash, struct todo_list *todo_list);
|
||||
struct commit *onto, const struct object_id *orig_head,
|
||||
struct string_list *commands, unsigned autosquash,
|
||||
struct todo_list *todo_list);
|
||||
int todo_list_rearrange_squash(struct todo_list *todo_list);
|
||||
|
||||
/*
|
||||
|
@ -224,7 +225,7 @@ int read_author_script(const char *path, char **name, char **email, char **date,
|
|||
int allow_missing);
|
||||
void parse_strategy_opts(struct replay_opts *opts, char *raw_opts);
|
||||
int write_basic_state(struct replay_opts *opts, const char *head_name,
|
||||
struct commit *onto, const char *orig_head);
|
||||
struct commit *onto, const struct object_id *orig_head);
|
||||
void sequencer_post_commit_cleanup(struct repository *r, int verbose);
|
||||
int sequencer_get_last_command(struct repository* r,
|
||||
enum replay_action *action);
|
||||
|
|
|
@ -1797,6 +1797,17 @@ test_expect_success 'todo has correct onto hash' '
|
|||
test_i18ngrep "^# Rebase ..* onto $onto" actual
|
||||
'
|
||||
|
||||
test_expect_success 'ORIG_HEAD is updated correctly' '
|
||||
test_when_finished "git checkout master && git branch -D test-orig-head" &&
|
||||
git checkout -b test-orig-head A &&
|
||||
git commit --allow-empty -m A1 &&
|
||||
git commit --allow-empty -m A2 &&
|
||||
git commit --allow-empty -m A3 &&
|
||||
git commit --allow-empty -m A4 &&
|
||||
git rebase master &&
|
||||
test_cmp_rev ORIG_HEAD test-orig-head@{1}
|
||||
'
|
||||
|
||||
# This must be the last test in this file
|
||||
test_expect_success '$EDITOR and friends are unchanged' '
|
||||
test_editor_unchanged
|
||||
|
|
Загрузка…
Ссылка в новой задаче