@@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git cherry-pick' [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]
[-S[<keyid>]] <commit>...
-'git cherry-pick' (--continue | --skip | --abort | --quit)
+'git cherry-pick' (--continue | --skip | --abort | --quit | --show-current-patch)
DESCRIPTION
-----------
@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git revert' [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] <commit>...
-'git revert' (--continue | --skip | --abort | --quit)
+'git revert' (--continue | --skip | --abort | --quit | --show-current-patch)
DESCRIPTION
-----------
@@ -12,5 +12,10 @@
to clear the sequencer state after a failed cherry-pick or
revert.
+--show-current-patch::
+ Show the current patch when a revert or cherry-pick is
+ stopped because of conflicts. This is the equivalent of
+ `git show REVERT_HEAD` or `git show CHERRY_PICK_HEAD`.
+
--abort::
Cancel the operation and return to the pre-sequence state.
@@ -360,12 +360,9 @@ static int run_sequencer_rebase(struct rebase_options *opts)
ret = edit_todo_file(flags);
break;
case ACTION_SHOW_CURRENT_PATCH: {
- struct child_process cmd = CHILD_PROCESS_INIT;
-
- cmd.git_cmd = 1;
- strvec_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
- ret = run_command(&cmd);
+ struct replay_opts replay_opts = get_replay_opts(opts);
+ ret = sequencer_show_current_patch(the_repository, &replay_opts);
break;
}
default:
@@ -24,14 +24,14 @@
static const char * const revert_usage[] = {
N_("git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] <commit>..."),
- N_("git revert (--continue | --skip | --abort | --quit)"),
+ N_("git revert (--continue | --skip | --abort | --quit | --show-current-patch)"),
NULL
};
static const char * const cherry_pick_usage[] = {
N_("git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n"
" [-S[<keyid>]] <commit>..."),
- N_("git cherry-pick (--continue | --skip | --abort | --quit)"),
+ N_("git cherry-pick (--continue | --skip | --abort | --quit | --show-current-patch)"),
NULL
};
@@ -93,6 +93,7 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
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, "show-current-patch", &cmd, N_("show the patch file being reverted or cherry-picked"), 'p'),
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")),
@@ -154,6 +155,8 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
this_operation = "--continue";
else if (cmd == 's')
this_operation = "--skip";
+ else if (cmd == 'p')
+ this_operation = "--show-current-patch";
else {
assert(cmd == 'a');
this_operation = "--abort";
@@ -224,6 +227,8 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
return sequencer_rollback(the_repository, opts);
if (cmd == 's')
return sequencer_skip(the_repository, opts);
+ if (cmd == 'p')
+ return sequencer_show_current_patch(the_repository, opts);
return sequencer_pick_revisions(the_repository, opts);
}
@@ -1618,7 +1618,7 @@ _git_checkout ()
esac
}
-__git_sequencer_inprogress_options="--continue --quit --abort --skip"
+__git_sequencer_inprogress_options="--continue --quit --abort --skip --show-current-patch"
__git_cherry_pick_inprogress_options=$__git_sequencer_inprogress_options
@@ -3417,6 +3417,30 @@ int sequencer_skip(struct repository *r, struct replay_opts *opts)
return -1;
}
+int sequencer_show_current_patch(struct repository *r, struct replay_opts *opts)
+{
+ struct child_process cmd = CHILD_PROCESS_INIT;
+ cmd.git_cmd = 1;
+ switch (opts->action) {
+ case REPLAY_REVERT:
+ if (!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
+ die(_("No revert in progress?"));
+ strvec_pushl(&cmd.args, "show", "REVERT_HEAD", "--", NULL);
+ break;
+ case REPLAY_PICK:
+ if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD"))
+ die(_("No cherry-pick in progress?"));
+ strvec_pushl(&cmd.args, "show", "CHERRY_PICK_HEAD", "--", NULL);
+ break;
+ case REPLAY_INTERACTIVE_REBASE:
+ if (!refs_ref_exists(get_main_ref_store(r), "REBASE_HEAD"))
+ die(_("No rebase in progress?"));
+ strvec_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
+ break;
+ }
+ return run_command(&cmd);
+}
+
static int save_todo(struct todo_list *todo_list, struct replay_opts *opts,
int reschedule)
{
@@ -162,6 +162,8 @@ 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_show_current_patch(struct repository *repo,
+ struct replay_opts *opts);
int sequencer_skip(struct repository *repo, struct replay_opts *opts);
void replay_opts_release(struct replay_opts *opts);
int sequencer_remove_state(struct replay_opts *opts);
@@ -566,6 +566,36 @@ test_expect_success 'cherry-pick preserves sparse-checkout' '
test_grep ! "Changes not staged for commit:" actual
'
+test_expect_success 'cherry-pick --show-current-patch fails if no cherry-pick in progress' '
+ pristine_detach initial &&
+ test_must_fail git cherry-pick --show-current-patch
+'
+
+test_expect_success 'cherry-pick --show-current-patch describes patch that failed to apply' '
+ test_when_finished "git cherry-pick --abort || :" &&
+ pristine_detach initial &&
+ git show picked >expected &&
+
+ test_must_fail git cherry-pick picked &&
+
+ git cherry-pick --show-current-patch >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'revert --show-current-patch fails if no revert in progress' '
+ pristine_detach initial &&
+ test_must_fail git revert --show-current-patch
+'
+
+test_expect_success 'revert --show-current-patch describes patch that failed to apply' '
+ test_when_finished "git revert --abort || :" &&
+ pristine_detach initial &&
+ git show picked >expected &&
+ test_must_fail git revert picked &&
+ git revert --show-current-patch >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'cherry-pick --continue remembers --keep-redundant-commits' '
test_when_finished "git cherry-pick --abort || :" &&
pristine_detach initial &&
This aligns the interface to the rebase one and allows for an easier way of figuring out how to resolve conflicts if commits fail to apply (especially when reverting/cherry-picking multiple commits at the same time) Signed-off-by: Michael Lohmann <mi.al.lohmann@gmail.com> --- Documentation/git-cherry-pick.txt | 2 +- Documentation/git-revert.txt | 2 +- Documentation/sequencer.txt | 5 +++++ builtin/rebase.c | 7 ++---- builtin/revert.c | 9 ++++++-- contrib/completion/git-completion.bash | 2 +- sequencer.c | 24 +++++++++++++++++++++ sequencer.h | 2 ++ t/t3507-cherry-pick-conflict.sh | 30 ++++++++++++++++++++++++++ 9 files changed, 73 insertions(+), 10 deletions(-)