When using rebase, option --exec can be used, for example, to run tests after every commit created by rebase. When using interactive rebase, I don't always know, if I would want to run something against each commit before I start rebasing. Sometimes, I realize this only after doing some editing in the middle of the rebase. To do that, I have to manually edit the todo file. Additing exec command by hand or semi-automatically is cumbersome and error prone. Especially if the file is big or complex, e.g. when option --rebase-merges is used. Allow using the --edit-todo action of git rebase with option --exec. New test is based on test 'rebase --edit-todo can be used to modify todo'. Contents of todo file are checked using set_cat_todo_editor similarly to what test 'respects rebase.abbreviateCommands with fixup, squash and exec' does. Remove unnecessary braces around call to usage_with_options, while we're here. TODO: Still need better validation of options. With current implementation, the following is not rejected: git rebase --edit-todo -x 'git show HEAD' --autostash Signed-off-by: Andrei Rybak <rybak.a.v@xxxxxxxxx> --- Documentation/git-rebase.txt | 3 ++- builtin/rebase.c | 16 +++++++++++++--- t/t3404-rebase-interactive.sh | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 639a4179d1..b5db5e80d4 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -12,7 +12,8 @@ SYNOPSIS [--onto <newbase> | --keep-base] [<upstream> [<branch>]] 'git rebase' [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>] --root [<branch>] -'git rebase' (--continue | --skip | --abort | --quit | --edit-todo | --show-current-patch) +'git rebase' (--continue | --skip | --abort | --quit | + --edit-todo [--exec<cmd>] | --show-current-patch) DESCRIPTION ----------- diff --git a/builtin/rebase.c b/builtin/rebase.c index 27507d3cf6..1ee55b48e7 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -33,7 +33,8 @@ static char const * const builtin_rebase_usage[] = { "[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"), N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] " "--root [<branch>]"), - N_("git rebase --continue | --abort | --skip | --edit-todo"), + N_("git rebase --continue | --abort | --skip | " + "--edit-todo [--exec <cmd>]"), NULL }; @@ -409,6 +410,11 @@ static int run_rebase_interactive(struct rebase_options *opts, break; } case ACTION_EDIT_TODO: + if (opts->cmd) { + ret = add_exec(opts->cmd); + if (ret) + break; + } ret = edit_todo_file(flags); break; case ACTION_SHOW_CURRENT_PATCH: { @@ -1565,15 +1571,19 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) builtin_rebase_options, builtin_rebase_usage, 0); - if (action != ACTION_NONE && total_argc != 2) { + if (action != ACTION_NONE && action != ACTION_EDIT_TODO && + total_argc != 2) usage_with_options(builtin_rebase_usage, builtin_rebase_options); - } if (argc > 2) usage_with_options(builtin_rebase_usage, builtin_rebase_options); + if (action == ACTION_EDIT_TODO && argc > 0) + usage_with_options(builtin_rebase_usage, + builtin_rebase_options); + if (options.type == REBASE_PRESERVE_MERGES) warning(_("git rebase --preserve-merges is deprecated. " "Use --rebase-merges instead.")); diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index d2dfbe46b9..5decb8570e 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1082,6 +1082,38 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' ' test L = $(git cat-file commit HEAD | sed -ne \$p) ' +test_expect_success 'rebase --edit-todo can be used with -x' ' + test_when_finished "reset_rebase" && + git reset --hard && + git checkout no-conflict-branch^0 && + cat >expected <<-EOF && + pick $(git rev-list --abbrev-commit -1 HEAD^) L + exec git show HEAD + pick $(git rev-list --abbrev-commit -1 HEAD) M + exec git show HEAD + EOF + set_fake_editor && + FAKE_LINES="1 edit 2 3 4" git rebase -i HEAD~4 && + set_cat_todo_editor && + test_must_fail git rebase --edit-todo -x "git show HEAD" >actual && + test_cmp expected actual +' + +test_expect_failure 'rebase --edit-todo -x does not allow other arguments' ' + test_when_finished "reset_rebase" && + git reset --hard && + git checkout no-conflict-branch^0 && + cat >expected <<-EOF && + pick $(git rev-list --abbrev-commit -1 HEAD^) L + exec git show HEAD + pick $(git rev-list --abbrev-commit -1 HEAD) M + exec git show HEAD + EOF + set_fake_editor && + FAKE_LINES="1 edit 2 3 4" git rebase -i HEAD~4 && + test_must_fail git rebase --edit-todo -x "git show HEAD" --autostash +' + test_expect_success 'rebase -i produces readable reflog' ' git reset --hard && git branch -f branch-reflog-test H && -- 2.24.0.windows.2