From e1263b13e568d640e64c69f2c70cc7c232241a4f Mon Sep 17 00:00:00 2001 From: Rohit Ashiwal Date: Sun, 16 Jun 2019 13:50:37 +0530 Subject: [PATCH 1/8] sequencer: add advice for revert In the case of merge conflicts, while performing a revert, we are currently advised to use `git cherry-pick --` of which --continue is incompatible for continuing the revert. Introduce a separate advice message for `git revert`. Also change the signature of `create_seq_dir` to handle which advice to display selectively. Signed-off-by: Rohit Ashiwal --- sequencer.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/sequencer.c b/sequencer.c index f88a97fb10a322..d80e1c3fbbd0ef 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2650,15 +2650,37 @@ static int walk_revs_populate_todo(struct todo_list *todo_list, return 0; } -static int create_seq_dir(void) +static int create_seq_dir(struct repository *r) { - if (file_exists(git_path_seq_dir())) { - error(_("a cherry-pick or revert is already in progress")); - advise(_("try \"git cherry-pick (--continue | --quit | --abort)\"")); + enum replay_action action; + const char *in_progress_error = NULL; + const char *in_progress_advice = NULL; + + if (!sequencer_get_last_command(r, &action)) { + switch (action) { + case REPLAY_REVERT: + in_progress_error = _("revert is already in progress"); + in_progress_advice = + _("try \"git revert (--continue | --abort | --quit)\""); + break; + case REPLAY_PICK: + in_progress_error = _("cherry-pick is already in progress"); + in_progress_advice = + _("try \"git cherry-pick (--continue | --abort | --quit)\""); + break; + default: + BUG(_("unexpected action in create_seq_dir")); + } + } + if (in_progress_error) { + error("%s", in_progress_error); + advise("%s", in_progress_advice); return -1; - } else if (mkdir(git_path_seq_dir(), 0777) < 0) + } + if (mkdir(git_path_seq_dir(), 0777) < 0) return error_errno(_("could not create sequencer directory '%s'"), git_path_seq_dir()); + return 0; } @@ -4237,7 +4259,7 @@ int sequencer_pick_revisions(struct repository *r, */ if (walk_revs_populate_todo(&todo_list, opts) || - create_seq_dir() < 0) + create_seq_dir(r) < 0) return -1; if (get_oid("HEAD", &oid) && (opts->action == REPLAY_REVERT)) return error(_("can't revert as initial commit")); From bc63072cd3aa9731e4b38b9e8d4f1c850d374e51 Mon Sep 17 00:00:00 2001 From: Rohit Ashiwal Date: Sun, 16 Jun 2019 13:50:38 +0530 Subject: [PATCH 2/8] sequencer: rename reset_for_rollback to reset_merge We are on a path to teach cherry-pick/revert how to skip commits. To achieve this, we could really make use of existing functions. reset_for_rollback is one such function, but the name does not intuitively suggest to use it to reset a merge, which it was born to perform, see 539047c ("revert: introduce --abort to cancel a failed cherry-pick", 2011-11-23). Change the name to reset_merge to make it more intuitive. Signed-off-by: Rohit Ashiwal --- sequencer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sequencer.c b/sequencer.c index d80e1c3fbbd0ef..408643f88aee77 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2731,7 +2731,7 @@ static int rollback_is_safe(void) return oideq(&actual_head, &expected_head); } -static int reset_for_rollback(const struct object_id *oid) +static int reset_merge(const struct object_id *oid) { const char *argv[4]; /* reset --merge + NULL */ @@ -2753,7 +2753,7 @@ static int rollback_single_pick(struct repository *r) return error(_("cannot resolve HEAD")); if (is_null_oid(&head_oid)) return error(_("cannot abort from a branch yet to be born")); - return reset_for_rollback(&head_oid); + return reset_merge(&head_oid); } int sequencer_rollback(struct repository *r, struct replay_opts *opts) @@ -2796,7 +2796,7 @@ int sequencer_rollback(struct repository *r, struct replay_opts *opts) warning(_("You seem to have moved HEAD. " "Not rewinding, check your HEAD!")); } else - if (reset_for_rollback(&oid)) + if (reset_merge(&oid)) goto fail; strbuf_release(&buf); return sequencer_remove_state(opts); From e535304c7599301bf9cf80fbdcbefb9cb96d7ece Mon Sep 17 00:00:00 2001 From: Rohit Ashiwal Date: Sun, 16 Jun 2019 13:50:39 +0530 Subject: [PATCH 3/8] cherry-pick/revert: add --skip option git am or rebase have a --skip flag to skip the current commit if the user wishes to do so. During a cherry-pick or revert a user could likewise skip a commit, but needs to use 'git reset' (or in the case of conflicts 'git reset --merge'), followed by 'git (cherry-pick | revert) --continue' to skip the commit. This is more annoying and sometimes confusing on the users' part. Add a `--skip` option to make skipping commits easier for the user and to make the commands more consistent. In the next commit, we will change the advice messages and some tests hence finishing the process of teaching revert and cherry-pick "how to skip commits". Signed-off-by: Rohit Ashiwal --- Documentation/git-cherry-pick.txt | 4 +- Documentation/git-revert.txt | 4 +- Documentation/sequencer.txt | 4 ++ builtin/revert.c | 5 ++ sequencer.c | 94 +++++++++++++++++++++++++-- sequencer.h | 1 + t/t3510-cherry-pick-sequence.sh | 102 ++++++++++++++++++++++++++++++ 7 files changed, 202 insertions(+), 12 deletions(-) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 754b16ce0c9da6..83ce51aedfea54 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -10,9 +10,7 @@ SYNOPSIS [verse] 'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] [-S[]] ... -'git cherry-pick' --continue -'git cherry-pick' --quit -'git cherry-pick' --abort +'git cherry-pick' (--continue | --skip | --abort | --quit) DESCRIPTION ----------- diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index 0c82ca5bc0e5a3..665e065ee378f6 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -9,9 +9,7 @@ SYNOPSIS -------- [verse] 'git revert' [--[no-]edit] [-n] [-m parent-number] [-s] [-S[]] ... -'git revert' --continue -'git revert' --quit -'git revert' --abort +'git revert' (--continue | --skip | --abort | --quit) DESCRIPTION ----------- diff --git a/Documentation/sequencer.txt b/Documentation/sequencer.txt index 5a57c4a4077f0b..3bceb564741158 100644 --- a/Documentation/sequencer.txt +++ b/Documentation/sequencer.txt @@ -3,6 +3,10 @@ `.git/sequencer`. Can be used to continue after resolving conflicts in a failed cherry-pick or revert. +--skip:: + Skip the current commit and continue with the rest of the + sequence. + --quit:: Forget about the current operation in progress. Can be used to clear the sequencer state after a failed cherry-pick or diff --git a/builtin/revert.c b/builtin/revert.c index d4dcedbdc683f9..5dc5891ea2a262 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -102,6 +102,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'), OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'), OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'), + OPT_CMDMODE(0, "skip", &cmd, N_("skip current commit and continue"), 's'), OPT_CLEANUP(&cleanup_arg), OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")), OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")), @@ -151,6 +152,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) this_operation = "--quit"; else if (cmd == 'c') this_operation = "--continue"; + else if (cmd == 's') + this_operation = "--skip"; else { assert(cmd == 'a'); this_operation = "--abort"; @@ -210,6 +213,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) return sequencer_continue(the_repository, opts); if (cmd == 'a') return sequencer_rollback(the_repository, opts); + if (cmd == 's') + return sequencer_skip(the_repository, opts); return sequencer_pick_revisions(the_repository, opts); } diff --git a/sequencer.c b/sequencer.c index 408643f88aee77..95fa19a118cbbf 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2733,13 +2733,18 @@ static int rollback_is_safe(void) static int reset_merge(const struct object_id *oid) { - const char *argv[4]; /* reset --merge + NULL */ + int ret; + struct argv_array argv = ARGV_ARRAY_INIT; - argv[0] = "reset"; - argv[1] = "--merge"; - argv[2] = oid_to_hex(oid); - argv[3] = NULL; - return run_command_v_opt(argv, RUN_GIT_CMD); + argv_array_pushl(&argv, "reset", "--merge", NULL); + + if (!is_null_oid(oid)) + argv_array_push(&argv, oid_to_hex(oid)); + + ret = run_command_v_opt(argv.argv, RUN_GIT_CMD); + argv_array_clear(&argv); + + return ret; } static int rollback_single_pick(struct repository *r) @@ -2756,6 +2761,15 @@ static int rollback_single_pick(struct repository *r) return reset_merge(&head_oid); } +static int skip_single_pick(void) +{ + struct object_id head; + + if (read_ref_full("HEAD", 0, &head, NULL)) + return error(_("cannot resolve HEAD")); + return reset_merge(&head); +} + int sequencer_rollback(struct repository *r, struct replay_opts *opts) { FILE *f; @@ -2805,6 +2819,74 @@ int sequencer_rollback(struct repository *r, struct replay_opts *opts) return -1; } +int sequencer_skip(struct repository *r, struct replay_opts *opts) +{ + enum replay_action action = -1; + sequencer_get_last_command(r, &action); + + /* + * opts->action tells us which subcommand requested to skip + * the commit. + */ + switch (opts->action) { + case REPLAY_REVERT: + /* + * If .git/REVERT_HEAD exists then we are sure that we are in + * the middle of a revert and we allow to skip the commit. + */ + if (!file_exists(git_path_revert_head(r))) { + /* + * Check if the last instruction executed was related to + * revert. If so, we are sure that a revert is in progress. + * + * NB: single commit revert is also counted in this + * definition of "progress" (and was dealt with in the + * previous check). + */ + if (action == REPLAY_REVERT) { + /* + * Check if the user has moved the HEAD, i.e., + * already committed. In this case, we would like + * to advise instead of skipping. + */ + if (!rollback_is_safe()) + goto give_advice; + else + /* skip commit :) */ + break; + } + return error(_("no revert in progress")); + } + break; + case REPLAY_PICK: + if (!file_exists(git_path_cherry_pick_head(r))) { + if (action == REPLAY_PICK) { + if (!rollback_is_safe()) + goto give_advice; + else + break; + } + return error(_("no cherry-pick in progress")); + } + break; + default: + BUG("unexpected action in sequencer_skip"); + } + + if (skip_single_pick()) + return error(_("failed to skip the commit")); + if (!is_directory(git_path_seq_dir())) + return 0; + + return sequencer_continue(r, opts); + +give_advice: + advise(_("have you committed already?\n" + "try \"git %s --continue\""), + action == REPLAY_REVERT ? "revert" : "cherry-pick"); + return error(_("there is nothing to skip")); +} + static int save_todo(struct todo_list *todo_list, struct replay_opts *opts) { struct lock_file todo_lock = LOCK_INIT; diff --git a/sequencer.h b/sequencer.h index 0c494b83d43e2c..731b9853ebd265 100644 --- a/sequencer.h +++ b/sequencer.h @@ -129,6 +129,7 @@ int sequencer_pick_revisions(struct repository *repo, struct replay_opts *opts); int sequencer_continue(struct repository *repo, struct replay_opts *opts); int sequencer_rollback(struct repository *repo, struct replay_opts *opts); +int sequencer_skip(struct repository *repo, struct replay_opts *opts); int sequencer_remove_state(struct replay_opts *opts); #define TODO_LIST_KEEP_EMPTY (1U << 0) diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh index 941d5026da2adc..dc0ac8343c4b71 100755 --- a/t/t3510-cherry-pick-sequence.sh +++ b/t/t3510-cherry-pick-sequence.sh @@ -93,6 +93,108 @@ test_expect_success 'cherry-pick cleans up sequencer state upon success' ' test_path_is_missing .git/sequencer ' +test_expect_success 'cherry-pick --skip requires cherry-pick in progress' ' + pristine_detach initial && + test_must_fail git cherry-pick --skip +' + +test_expect_success 'revert --skip requires revert in progress' ' + pristine_detach initial && + test_must_fail git revert --skip +' + +test_expect_success 'cherry-pick --skip to skip commit' ' + pristine_detach initial && + test_must_fail git cherry-pick anotherpick && + test_must_fail git revert --skip && + git cherry-pick --skip && + test_cmp_rev initial HEAD && + test_path_is_missing .git/CHERRY_PICK_HEAD +' + +test_expect_success 'revert --skip to skip commit' ' + pristine_detach anotherpick && + test_must_fail git revert anotherpick~1 && + test_must_fail git cherry-pick --skip && + git revert --skip && + test_cmp_rev anotherpick HEAD +' + +test_expect_success 'skip "empty" commit' ' + pristine_detach picked && + test_commit dummy foo d && + test_must_fail git cherry-pick anotherpick && + git cherry-pick --skip && + test_cmp_rev dummy HEAD +' + +test_expect_success 'skip a commit and check if rest of sequence is correct' ' + pristine_detach initial && + echo e >expect && + cat >expect.log <<-EOF && + OBJID + :100644 100644 OBJID OBJID M foo + OBJID + :100644 100644 OBJID OBJID M foo + OBJID + :100644 100644 OBJID OBJID M unrelated + OBJID + :000000 100644 OBJID OBJID A foo + :000000 100644 OBJID OBJID A unrelated + EOF + test_must_fail git cherry-pick base..yetanotherpick && + test_must_fail git cherry-pick --skip && + echo d >foo && + git add foo && + git cherry-pick --continue && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$OID_REGEX/OBJID/g" + } >actual.log && + test_cmp expect foo && + test_cmp expect.log actual.log +' + +test_expect_success 'check advice when we move HEAD by committing' ' + pristine_detach initial && + cat >expect <<-EOF && + hint: have you committed already? + hint: try "git cherry-pick --continue" + error: there is nothing to skip + fatal: cherry-pick failed + EOF + test_must_fail git cherry-pick base..yetanotherpick && + echo c >foo && + git commit -a && + test_path_is_missing .git/CHERRY_PICK_HEAD && + test_must_fail git cherry-pick --skip 2>advice && + test_i18ncmp expect advice +' + +test_expect_success 'allow skipping commit but not abort for a new history' ' + pristine_detach initial && + cat >expect <<-EOF && + error: cannot abort from a branch yet to be born + fatal: cherry-pick failed + EOF + git checkout --orphan new_disconnected && + git reset --hard && + test_must_fail git cherry-pick anotherpick && + test_must_fail git cherry-pick --abort 2>advice && + git cherry-pick --skip && + test_i18ncmp expect advice +' + +test_expect_success 'allow skipping stopped cherry-pick because of untracked file modifications' ' + pristine_detach initial && + git rm --cached unrelated && + git commit -m "untrack unrelated" && + test_must_fail git cherry-pick initial base && + test_path_is_missing .git/CHERRY_PICK_HEAD && + git cherry-pick --skip +' + test_expect_success '--quit does not complain when no cherry-pick is in progress' ' pristine_detach initial && git cherry-pick --quit From 8c15c012963607ec21b01d64847cdf444ed23ae2 Mon Sep 17 00:00:00 2001 From: Rohit Ashiwal Date: Sun, 16 Jun 2019 13:50:40 +0530 Subject: [PATCH 4/8] cherry-pick/revert: advise using --skip The previous commit introduced a --skip flag for cherry-pick and revert. Update the advice messages, to tell users about this less cumbersome way of skipping commits. Also add tests to ensure everything is working fine. Signed-off-by: Rohit Ashiwal --- builtin/commit.c | 13 ++++++++----- sequencer.c | 11 ++++++++--- t/t3510-cherry-pick-sequence.sh | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/builtin/commit.c b/builtin/commit.c index 1c9e8e2228c7ce..1f47c51bdcabd4 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -60,15 +60,18 @@ N_("The previous cherry-pick is now empty, possibly due to conflict resolution.\ "\n"); static const char empty_cherry_pick_advice_single[] = -N_("Otherwise, please use 'git reset'\n"); +N_("Otherwise, please use 'git cherry-pick --skip'\n"); static const char empty_cherry_pick_advice_multi[] = -N_("If you wish to skip this commit, use:\n" +N_("and then use:\n" "\n" -" git reset\n" +" git cherry-pick --continue\n" "\n" -"Then \"git cherry-pick --continue\" will resume cherry-picking\n" -"the remaining commits.\n"); +"to resume cherry-picking the remaining commits.\n" +"If you wish to skip this commit, use:\n" +"\n" +" git cherry-pick --skip\n" +"\n"); static const char *color_status_slots[] = { [WT_STATUS_HEADER] = "header", diff --git a/sequencer.c b/sequencer.c index 95fa19a118cbbf..6e8afe8f223de1 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2655,18 +2655,20 @@ static int create_seq_dir(struct repository *r) enum replay_action action; const char *in_progress_error = NULL; const char *in_progress_advice = NULL; + unsigned int advise_skip = file_exists(git_path_revert_head(r)) || + file_exists(git_path_cherry_pick_head(r)); if (!sequencer_get_last_command(r, &action)) { switch (action) { case REPLAY_REVERT: in_progress_error = _("revert is already in progress"); in_progress_advice = - _("try \"git revert (--continue | --abort | --quit)\""); + _("try \"git revert (--continue | %s--abort | --quit)\""); break; case REPLAY_PICK: in_progress_error = _("cherry-pick is already in progress"); in_progress_advice = - _("try \"git cherry-pick (--continue | --abort | --quit)\""); + _("try \"git cherry-pick (--continue | %s--abort | --quit)\""); break; default: BUG(_("unexpected action in create_seq_dir")); @@ -2674,7 +2676,10 @@ static int create_seq_dir(struct repository *r) } if (in_progress_error) { error("%s", in_progress_error); - advise("%s", in_progress_advice); + if (advise_skip) + advise(in_progress_advice, "--skip | "); + else + advise(in_progress_advice, ""); return -1; } if (mkdir(git_path_seq_dir(), 0777) < 0) diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh index dc0ac8343c4b71..0e8adc95fcdadc 100755 --- a/t/t3510-cherry-pick-sequence.sh +++ b/t/t3510-cherry-pick-sequence.sh @@ -172,6 +172,26 @@ test_expect_success 'check advice when we move HEAD by committing' ' test_i18ncmp expect advice ' +test_expect_success 'selectively advise --skip while launching another sequence' ' + pristine_detach initial && + cat >expect <<-EOF && + error: cherry-pick is already in progress + hint: try "git cherry-pick (--continue | --skip | --abort | --quit)" + fatal: cherry-pick failed + EOF + test_must_fail git cherry-pick picked..yetanotherpick && + test_must_fail git cherry-pick picked..yetanotherpick 2>advice && + test_i18ncmp expect advice && + cat >expect <<-EOF && + error: cherry-pick is already in progress + hint: try "git cherry-pick (--continue | --abort | --quit)" + fatal: cherry-pick failed + EOF + git reset --merge && + test_must_fail git cherry-pick picked..yetanotherpick 2>advice && + test_i18ncmp expect advice +' + test_expect_success 'allow skipping commit but not abort for a new history' ' pristine_detach initial && cat >expect <<-EOF && From 9a2233751b38068aca976afe7391391ee85fbec4 Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Sun, 16 Jun 2019 14:14:19 +0100 Subject: [PATCH 5/8] show --continue/skip etc. consistently in synopsis The synopsis for am shows the command mode options as (--continue | --skip | --abort | --quit) They are on a single line and in parenthesis as they are not optional. Fix the merge and rebase docs to match this style. Signed-off-by: Phillip Wood --- This patch is based on top of nd/merge-quit. The docs for cherry-pick/revert are updated to this style by https://public-inbox.org/git/20190616082040.9440-1-rohit.ashiwal265@gmail.com/T/#u --- Documentation/git-merge.txt | 3 +-- Documentation/git-rebase.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index c01cfa659529b1..1a6548bee61f4e 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -13,8 +13,7 @@ SYNOPSIS [-s ] [-X ] [-S[]] [--[no-]allow-unrelated-histories] [--[no-]rerere-autoupdate] [-m ] [-F ] [...] -'git merge' --abort -'git merge' --continue +'git merge' (--continue | --skip | --abort | --quit) DESCRIPTION ----------- diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 5e4e9276479c94..057c21d8ee5de7 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -12,7 +12,7 @@ SYNOPSIS [ []] 'git rebase' [-i | --interactive] [] [--exec ] [--onto ] --root [] -'git rebase' --continue | --skip | --abort | --quit | --edit-todo | --show-current-patch +'git rebase' (--continue | --skip | --abort | --quit | --edit-todo | --show-current-patch) DESCRIPTION ----------- From e27cffb1c4e7d8f9bba27c11c0c575ffe27e5865 Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Sun, 16 Jun 2019 14:45:28 +0100 Subject: [PATCH 6/8] show --continue/skip etc. consistently in help Show a similar synopsis for --continue/--skip etc. in the help printed with -h as in the man pages. Signed-off-by: Phillip Wood --- builtin/am.c | 3 ++- builtin/merge.c | 3 +-- builtin/rebase.c | 3 ++- builtin/revert.c | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/builtin/am.c b/builtin/am.c index 912d9821b18acf..bafade68553a26 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -2164,7 +2164,8 @@ int cmd_am(int argc, const char **argv, const char *prefix) const char * const usage[] = { N_("git am [] [( | )...]"), - N_("git am [] (--continue | --skip | --abort)"), + N_("git am [] (--continue | --skip | --abort | --quit" + " | --show-current-patch)"), NULL }; diff --git a/builtin/merge.c b/builtin/merge.c index 5c83f89cc639c4..67a4974f4123e3 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -53,8 +53,7 @@ struct strategy { static const char * const builtin_merge_usage[] = { N_("git merge [] [...]"), - N_("git merge --abort"), - N_("git merge --continue"), + N_("git merge (--continue | --skip | --abort | --quit)"), NULL }; diff --git a/builtin/rebase.c b/builtin/rebase.c index db6ca9bd7d4c4e..9bff0f4c0ccbdc 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -33,7 +33,8 @@ static char const * const builtin_rebase_usage[] = { "[] []"), N_("git rebase [-i] [options] [--exec ] [--onto ] " "--root []"), - N_("git rebase --continue | --abort | --skip | --edit-todo"), + N_("git rebase (--continue | --skip | --abort | --quit | --edit-todo | " + "--show-current-patch)"), NULL }; diff --git a/builtin/revert.c b/builtin/revert.c index 5dc5891ea2a262..60f778c3f3a413 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -22,13 +22,13 @@ static const char * const revert_usage[] = { N_("git revert [] ..."), - N_("git revert "), + N_("git revert (--continue | --skip | --abort | --quit)"), NULL }; static const char * const cherry_pick_usage[] = { N_("git cherry-pick [] ..."), - N_("git cherry-pick "), + N_("git cherry-pick (--continue | --skip | --abort | --quit)"), NULL }; From 806f7ac17890c16b913164c6ea71ebbdb2849fed Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Sun, 16 Jun 2019 14:53:12 +0100 Subject: [PATCH 7/8] help: show command mode options at the top Show --continue/--skip etc. in a consistent order at the top of the help printed by -h. Signed-off-by: Phillip Wood --- builtin/am.c | 36 ++++++++++++++++++------------------ builtin/merge.c | 12 ++++++------ builtin/rebase.c | 28 ++++++++++++++-------------- builtin/revert.c | 4 ++-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/builtin/am.c b/builtin/am.c index bafade68553a26..74a88221123225 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -2170,6 +2170,24 @@ int cmd_am(int argc, const char **argv, const char *prefix) }; struct option options[] = { + OPT_CMDMODE(0, "continue", &resume, + N_("continue applying patches after resolving a conflict"), + RESUME_RESOLVED), + OPT_CMDMODE(0, "skip", &resume, + N_("skip the current patch"), + RESUME_SKIP), + OPT_CMDMODE(0, "abort", &resume, + N_("restore the original branch and abort the patching operation."), + RESUME_ABORT), + OPT_CMDMODE(0, "quit", &resume, + N_("abort the patching operation but keep HEAD where it is."), + RESUME_QUIT), + OPT_CMDMODE(0, "show-current-patch", &resume, + N_("show the patch being applied."), + RESUME_SHOW_PATCH), + OPT_CMDMODE('r', "resolved", &resume, + N_("synonym for --continue"), + RESUME_RESOLVED), OPT_BOOL('i', "interactive", &state.interactive, N_("run interactively")), OPT_HIDDEN_BOOL('b', "binary", &binary, @@ -2228,24 +2246,6 @@ int cmd_am(int argc, const char **argv, const char *prefix) PARSE_OPT_NOARG), OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL, N_("override error message when patch failure occurs")), - OPT_CMDMODE(0, "continue", &resume, - N_("continue applying patches after resolving a conflict"), - RESUME_RESOLVED), - OPT_CMDMODE('r', "resolved", &resume, - N_("synonyms for --continue"), - RESUME_RESOLVED), - OPT_CMDMODE(0, "skip", &resume, - N_("skip the current patch"), - RESUME_SKIP), - OPT_CMDMODE(0, "abort", &resume, - N_("restore the original branch and abort the patching operation."), - RESUME_ABORT), - OPT_CMDMODE(0, "quit", &resume, - N_("abort the patching operation but keep HEAD where it is."), - RESUME_QUIT), - OPT_CMDMODE(0, "show-current-patch", &resume, - N_("show the patch being applied."), - RESUME_SHOW_PATCH), OPT_BOOL(0, "committer-date-is-author-date", &state.committer_date_is_author_date, N_("lie about committer date")), diff --git a/builtin/merge.c b/builtin/merge.c index 67a4974f4123e3..7153c4bd0db1c2 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -239,6 +239,12 @@ static int option_parse_n(const struct option *opt, } static struct option builtin_merge_options[] = { + OPT_BOOL(0, "continue", &continue_current_merge, + N_("continue the current in-progress merge")), + OPT_BOOL(0, "abort", &abort_current_merge, + N_("abort the current in-progress merge")), + OPT_BOOL(0, "quit", &quit_current_merge, + N_("--abort but leave index and working tree alone")), { OPTION_CALLBACK, 'n', NULL, NULL, NULL, N_("do not show a diffstat at the end of the merge"), PARSE_OPT_NOARG, option_parse_n }, @@ -273,12 +279,6 @@ static struct option builtin_merge_options[] = { N_("read message from file"), PARSE_OPT_NONEG, NULL, 0, option_read_message }, OPT__VERBOSITY(&verbosity), - OPT_BOOL(0, "abort", &abort_current_merge, - N_("abort the current in-progress merge")), - OPT_BOOL(0, "quit", &quit_current_merge, - N_("--abort but leave index and working tree alone")), - OPT_BOOL(0, "continue", &continue_current_merge, - N_("continue the current in-progress merge")), OPT_BOOL(0, "allow-unrelated-histories", &allow_unrelated_histories, N_("allow merging unrelated histories")), OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1), diff --git a/builtin/rebase.c b/builtin/rebase.c index 9bff0f4c0ccbdc..def9a02ba92052 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -1386,6 +1386,20 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) struct object_id squash_onto; char *squash_onto_name = NULL; struct option builtin_rebase_options[] = { + OPT_CMDMODE(0, "continue", &action, N_("continue"), + ACTION_CONTINUE), + OPT_CMDMODE(0, "skip", &action, + N_("skip current patch and continue"), ACTION_SKIP), + OPT_CMDMODE(0, "abort", &action, + N_("abort and check out the original branch"), + ACTION_ABORT), + OPT_CMDMODE(0, "quit", &action, + N_("abort but keep HEAD where it is"), ACTION_QUIT), + OPT_CMDMODE(0, "edit-todo", &action, N_("edit the todo list " + "during an interactive rebase"), ACTION_EDIT_TODO), + OPT_CMDMODE(0, "show-current-patch", &action, + N_("show the patch file being applied or merged"), + ACTION_SHOW_CURRENT_PATCH), OPT_STRING(0, "onto", &options.onto_name, N_("revision"), N_("rebase onto given branch instead of upstream")), @@ -1420,20 +1434,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) OPT_BIT(0, "no-ff", &options.flags, N_("cherry-pick all commits, even if unchanged"), REBASE_FORCE), - OPT_CMDMODE(0, "continue", &action, N_("continue"), - ACTION_CONTINUE), - OPT_CMDMODE(0, "skip", &action, - N_("skip current patch and continue"), ACTION_SKIP), - OPT_CMDMODE(0, "abort", &action, - N_("abort and check out the original branch"), - ACTION_ABORT), - OPT_CMDMODE(0, "quit", &action, - N_("abort but keep HEAD where it is"), ACTION_QUIT), - OPT_CMDMODE(0, "edit-todo", &action, N_("edit the todo list " - "during an interactive rebase"), ACTION_EDIT_TODO), - OPT_CMDMODE(0, "show-current-patch", &action, - N_("show the patch file being applied or merged"), - ACTION_SHOW_CURRENT_PATCH), { OPTION_CALLBACK, 'm', "merge", &options, NULL, N_("use merging strategies to rebase"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, diff --git a/builtin/revert.c b/builtin/revert.c index 60f778c3f3a413..1cc512d9b54ac0 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -99,10 +99,10 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) const char *cleanup_arg = NULL; int cmd = 0; struct option base_options[] = { - OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'), OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'), - OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'), OPT_CMDMODE(0, "skip", &cmd, N_("skip current commit and continue"), 's'), + OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'), + OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'), OPT_CLEANUP(&cleanup_arg), OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")), OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")), From b6e4769a93ba1f45136c2bea23417eb3d9754142 Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Sun, 16 Jun 2019 16:21:43 +0100 Subject: [PATCH 8/8] docs: show --continue/--skip in consistent order Show --continue, --skip, --abort and --quit in that order in the docs. This commit reorders those commands but does not move them to the top like the last one. Signed-off-by: Phillip Wood --- Documentation/git-am.txt | 8 ++++---- Documentation/git-merge.txt | 10 +++++----- Documentation/git-rebase.txt | 22 +++++++++++----------- Documentation/sequencer.txt | 6 +++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index fc3b993c3338b5..a5dff10fa23cc9 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -142,10 +142,6 @@ default. You can use `--no-utf8` to override this. user to lie about the author date by using the same value as the committer date. ---skip:: - Skip the current patch. This is only meaningful when - restarting an aborted patch. - -S[]:: --gpg-sign[=]:: GPG-sign commits. The `keyid` argument is optional and @@ -162,6 +158,10 @@ default. You can use `--no-utf8` to override this. extracted from the e-mail message and the current index file, and continue. +--skip:: + Skip the current patch. This is only meaningful when + restarting an aborted patch. + --resolvemsg=:: When a patch failure occurs, will be printed to the screen before exiting. This overrides the diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 1a6548bee61f4e..740407855e0584 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -87,6 +87,11 @@ will be appended to the specified message. Allow the rerere mechanism to update the index with the result of auto-conflict resolution if possible. +--continue:: + After a 'git merge' stops due to conflicts you can conclude the + merge by running 'git merge --continue' (see "HOW TO RESOLVE + CONFLICTS" section below). + --abort:: Abort the current conflict resolution process, and try to reconstruct the pre-merge state. @@ -103,11 +108,6 @@ commit or stash your changes before running 'git merge'. Forget about the current merge in progress. Leave the index and the working tree as-is. ---continue:: - After a 'git merge' stops due to conflicts you can conclude the - merge by running 'git merge --continue' (see "HOW TO RESOLVE - CONFLICTS" section below). - ...:: Commits, usually other branch heads, to merge into our branch. Specifying more than one commit will create a merge with diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 057c21d8ee5de7..ededa36dc60ae2 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -228,6 +228,9 @@ leave out at most one of A and B, in which case it defaults to HEAD. --continue:: Restart the rebasing process after having resolved a merge conflict. +--skip:: + Restart the rebasing process by skipping the current patch. + --abort:: Abort the rebase operation and reset HEAD to the original branch. If was provided when the rebase operation was @@ -240,6 +243,14 @@ leave out at most one of A and B, in which case it defaults to HEAD. original branch. The index and working tree are also left unchanged as a result. +--edit-todo:: + Edit the todo list during an interactive rebase. + +--show-current-patch:: + Show the current patch in an interactive rebase or when rebase + is stopped because of conflicts. This is the equivalent of + `git show REBASE_HEAD`. + --keep-empty:: Keep the commits that do not change anything from its parents in the result. @@ -253,17 +264,6 @@ See also INCOMPATIBLE OPTIONS below. + See also INCOMPATIBLE OPTIONS below. ---skip:: - Restart the rebasing process by skipping the current patch. - ---edit-todo:: - Edit the todo list during an interactive rebase. - ---show-current-patch:: - Show the current patch in an interactive rebase or when rebase - is stopped because of conflicts. This is the equivalent of - `git show REBASE_HEAD`. - -m:: --merge:: Use merging strategies to rebase. When the recursive (default) merge diff --git a/Documentation/sequencer.txt b/Documentation/sequencer.txt index 3bceb564741158..4db07ea723a7ee 100644 --- a/Documentation/sequencer.txt +++ b/Documentation/sequencer.txt @@ -7,10 +7,10 @@ Skip the current commit and continue with the rest of the sequence. +--abort:: + Cancel the operation and return to the pre-sequence state. + --quit:: Forget about the current operation in progress. Can be used to clear the sequencer state after a failed cherry-pick or revert. - ---abort:: - Cancel the operation and return to the pre-sequence state.