diff options
author | Alban Gruin <alban.gruin@gmail.com> | 2020-01-29 00:12:46 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2020-01-29 01:14:57 +0300 |
commit | 5a5445d8788058c6d038f5f4072316db0d250eeb (patch) | |
tree | e07383c42f839af13a3631ecac3bf416b1395587 /sequencer.c | |
parent | 1da5874c1b283862f8252a2f5f2f8d4afe86346a (diff) |
rebase-interactive: warn if commit is dropped with `rebase --edit-todo'
When set to "warn" or "error", `rebase.missingCommitsCheck' would make
`rebase -i' warn if the user removed commits from the todo list to
prevent mistakes. Unfortunately, `rebase --edit-todo' and `rebase
--continue' don't take it into account.
This adds the ability for `rebase --edit-todo' and `rebase --continue'
to check if commits were dropped by the user. As both edit_todo_list()
and complete_action() parse the todo list and check for dropped commits,
the code doing so in the latter is removed to reduce duplication.
`edit_todo_list_advice' is removed from sequencer.c as it is no longer
used there.
This changes when a backup of the todo list is made. Until now, it was
saved only once, before the initial edit. Now, it is also made if the
original todo list has no errors or no dropped commits. Thus, the
backup should be error-free. Without this, sequencer_continue()
(`rebase --continue') could only compare the current todo list against
the original, unedited list. Before this change, this file was only
used by edit_todo_list() and `rebase -p' to create the backup before
the initial edit, and check_todo_list_from_file(), only used by
`rebase -p' to check for dropped commits after its own initial edit.
If the edited list has an error, a file, `dropped', is created to
report the issue. Otherwise, it is deleted. Usually, the edited list
is compared against the list before editing, but if this file exists,
it will be compared to the backup. Also, if the file exists,
sequencer_continue() checks the list for dropped commits. If the
check was performed every time, it would fail when resuming a rebase
after resolving a conflict, as the backup will contain commits that
were picked, but they will not be in the new list. It's safe to
ignore this check if `dropped' does not exist, because that means that
no errors were found at the last edition, so any missing commits here
have already been picked.
Five tests are added to t3404. The tests for
`rebase.missingCommitsCheck = warn' and `rebase.missingCommitsCheck =
error' have a similar structure. First, we start a rebase with an
incorrect command on the first line. Then, we edit the todo list,
removing the first and the last lines. This demonstrates that
`--edit-todo' notices dropped commits, but not when the command is
incorrect. Then, we restore the original todo list, and edit it to
remove the last line. This demonstrates that if we add a commit after
the initial edit, then remove it, `--edit-todo' will notice that it
has been dropped. Then, the actual rebase takes place. In the third
test, it is also checked that `--continue' will refuse to resume the
rebase if commits were dropped. The fourth test checks that no errors
are raised when resuming a rebase after resolving a conflict, the fifth
checks that no errors are raised when editing the todo list after
pausing the rebase.
Signed-off-by: Alban Gruin <alban.gruin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sequencer.c')
-rw-r--r-- | sequencer.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/sequencer.c b/sequencer.c index 9365fc3e5a..638098b936 100644 --- a/sequencer.c +++ b/sequencer.c @@ -57,6 +57,8 @@ static GIT_PATH_FUNC(rebase_path, "rebase-merge") GIT_PATH_FUNC(rebase_path_todo, "rebase-merge/git-rebase-todo") GIT_PATH_FUNC(rebase_path_todo_backup, "rebase-merge/git-rebase-todo.backup") +GIT_PATH_FUNC(rebase_path_dropped, "rebase-merge/dropped") + /* * The rebase command lines that have already been processed. A line * is moved here when it is first handled, before any associated user @@ -4239,6 +4241,14 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts) if (is_rebase_i(opts)) { if ((res = read_populate_todo(r, &todo_list, opts))) goto release_todo_list; + + if (file_exists(rebase_path_dropped())) { + if ((res = todo_list_check_against_backup(r, &todo_list))) + goto release_todo_list; + + unlink(rebase_path_dropped()); + } + if (commit_staged_changes(r, opts, &todo_list)) { res = -1; goto release_todo_list; @@ -4985,12 +4995,6 @@ int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list, return res; } -static const char edit_todo_list_advice[] = -N_("You can fix this with 'git rebase --edit-todo' " -"and then run 'git rebase --continue'.\n" -"Or you can abort the rebase with 'git rebase" -" --abort'.\n"); - /* skip picking commits whose parents are unchanged */ static int skip_unnecessary_picks(struct repository *r, struct todo_list *todo_list, @@ -5088,11 +5092,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla todo_list_release(&new_todo); return error(_("nothing to do")); - } - - if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) || - todo_list_check(todo_list, &new_todo)) { - fprintf(stderr, _(edit_todo_list_advice)); + } else if (res == -4) { checkout_onto(r, opts, onto_name, &onto->object.oid, orig_head); todo_list_release(&new_todo); |