summaryrefslogtreecommitdiff
path: root/t/t3404-rebase-interactive.sh
diff options
context:
space:
mode:
authorAlban Gruin <alban.gruin@gmail.com>2020-01-28 21:12:46 (GMT)
committerJunio C Hamano <gitster@pobox.com>2020-01-28 22:14:57 (GMT)
commit5a5445d8788058c6d038f5f4072316db0d250eeb (patch)
treee07383c42f839af13a3631ecac3bf416b1395587 /t/t3404-rebase-interactive.sh
parent1da5874c1b283862f8252a2f5f2f8d4afe86346a (diff)
downloadgit-5a5445d8788058c6d038f5f4072316db0d250eeb.zip
git-5a5445d8788058c6d038f5f4072316db0d250eeb.tar.gz
git-5a5445d8788058c6d038f5f4072316db0d250eeb.tar.bz2
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 't/t3404-rebase-interactive.sh')
-rwxr-xr-xt/t3404-rebase-interactive.sh121
1 files changed, 121 insertions, 0 deletions
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index b90ea0f..d79a3ef 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1463,6 +1463,127 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
test B = $(git cat-file commit HEAD^ | sed -ne \$p)
'
+test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ignore' '
+ test_config rebase.missingCommitsCheck ignore &&
+ rebase_setup_and_clean missing-commit &&
+ (
+ set_fake_editor &&
+ FAKE_LINES="break 1 2 3 4 5" git rebase -i --root &&
+ FAKE_LINES="1 2 3 4" git rebase --edit-todo &&
+ git rebase --continue 2>actual
+ ) &&
+ test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+ test_i18ngrep \
+ "Successfully rebased and updated refs/heads/missing-commit" \
+ actual
+'
+
+test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' '
+ cat >expect <<-EOF &&
+ error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+ Warning: some commits may have been dropped accidentally.
+ Dropped commits (newer to older):
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+ To avoid this message, use "drop" to explicitly remove a commit.
+ EOF
+ head -n4 expect >expect.2 &&
+ tail -n1 expect >>expect.2 &&
+ tail -n4 expect.2 >expect.3 &&
+ test_config rebase.missingCommitsCheck warn &&
+ rebase_setup_and_clean missing-commit &&
+ (
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \
+ git rebase -i --root &&
+ cp .git/rebase-merge/git-rebase-todo.backup orig &&
+ FAKE_LINES="2 3 4" git rebase --edit-todo 2>actual.2 &&
+ head -n6 actual.2 >actual &&
+ test_i18ncmp expect actual &&
+ cp orig .git/rebase-merge/git-rebase-todo &&
+ FAKE_LINES="1 2 3 4" git rebase --edit-todo 2>actual.2 &&
+ head -n4 actual.2 >actual &&
+ test_i18ncmp expect.3 actual &&
+ git rebase --continue 2>actual
+ ) &&
+ test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+ test_i18ngrep \
+ "Successfully rebased and updated refs/heads/missing-commit" \
+ actual
+'
+
+test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' '
+ cat >expect <<-EOF &&
+ error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+ Warning: some commits may have been dropped accidentally.
+ Dropped commits (newer to older):
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+ To avoid this message, use "drop" to explicitly remove a commit.
+
+ Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings.
+ The possible behaviours are: ignore, warn, error.
+
+ You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''.
+ Or you can abort the rebase with '\''git rebase --abort'\''.
+ EOF
+ tail -n11 expect >expect.2 &&
+ head -n3 expect.2 >expect.3 &&
+ tail -n7 expect.2 >>expect.3 &&
+ test_config rebase.missingCommitsCheck error &&
+ rebase_setup_and_clean missing-commit &&
+ (
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \
+ git rebase -i --root &&
+ cp .git/rebase-merge/git-rebase-todo.backup orig &&
+ test_must_fail env FAKE_LINES="2 3 4" \
+ git rebase --edit-todo 2>actual &&
+ test_i18ncmp expect actual &&
+ test_must_fail git rebase --continue 2>actual &&
+ test_i18ncmp expect.2 actual &&
+ test_must_fail git rebase --edit-todo &&
+ cp orig .git/rebase-merge/git-rebase-todo &&
+ test_must_fail env FAKE_LINES="1 2 3 4" \
+ git rebase --edit-todo 2>actual &&
+ test_i18ncmp expect.3 actual &&
+ test_must_fail git rebase --continue 2>actual &&
+ test_i18ncmp expect.3 actual &&
+ cp orig .git/rebase-merge/git-rebase-todo &&
+ FAKE_LINES="1 2 3 4 drop 5" git rebase --edit-todo &&
+ git rebase --continue 2>actual
+ ) &&
+ test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+ test_i18ngrep \
+ "Successfully rebased and updated refs/heads/missing-commit" \
+ actual
+'
+
+test_expect_success 'rebase.missingCommitsCheck = error after resolving conflicts' '
+ test_config rebase.missingCommitsCheck error &&
+ (
+ set_fake_editor &&
+ FAKE_LINES="drop 1 break 2 3 4" git rebase -i A E
+ ) &&
+ git rebase --edit-todo &&
+ test_must_fail git rebase --continue &&
+ echo x >file1 &&
+ git add file1 &&
+ git rebase --continue
+'
+
+test_expect_success 'rebase.missingCommitsCheck = error when editing for a second time' '
+ test_config rebase.missingCommitsCheck error &&
+ (
+ set_fake_editor &&
+ FAKE_LINES="1 break 2 3" git rebase -i A D &&
+ cp .git/rebase-merge/git-rebase-todo todo &&
+ test_must_fail env FAKE_LINES=2 git rebase --edit-todo &&
+ GIT_SEQUENCE_EDITOR="cp todo" git rebase --edit-todo &&
+ git rebase --continue
+ )
+'
+
test_expect_success 'respects rebase.abbreviateCommands with fixup, squash and exec' '
rebase_setup_and_clean abbrevcmd &&
test_commit "first" file1.txt "first line" first &&