revert: allow single-pick in the middle of cherry-pick sequence

After messing up a difficult conflict resolution in the middle of a cherry-pick sequence, it can be useful to be able to git checkout HEAD . && git cherry-pick that-one-commit to restart the conflict resolution. The current code however errors out saying that another cherry-pick is already in progress. Suggested-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Nieder committed Dec 10, 2011 at 06:59 UTC 7acaaac275a1d338f7b2540779b7ea60f3f0667c
2 files changed +38
builtin/revert.c
+26
@@ -1072,6 +1072,12 @@ static int sequencer_continue(struct replay_opts *opts)
1072 return pick_commits(todo_list, opts);
1073 }
1074
1075 +static int single_pick(struct commit *cmit, struct replay_opts *opts)
1076 +{
1077 + setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
1078 + return do_pick_commit(cmit, opts);
1079 +}
1080 +
1081 static int pick_revisions(struct replay_opts *opts)
1082 {
1083 struct commit_list *todo_list = NULL;
@@ -1096,6 +1102,26 @@ static int pick_revisions(struct replay_opts *opts)
1102 if (opts->subcommand == REPLAY_CONTINUE)
1103 return sequencer_continue(opts);
1104
1105 + /*
1106 + * If we were called as "git cherry-pick <commit>", just
1107 + * cherry-pick/revert it, set CHERRY_PICK_HEAD /
1108 + * REVERT_HEAD, and don't touch the sequencer state.
1109 + * This means it is possible to cherry-pick in the middle
1110 + * of a cherry-pick sequence.
1111 + */
1112 + if (opts->revs->cmdline.nr == 1 &&
1113 + opts->revs->cmdline.rev->whence == REV_CMD_REV &&
1114 + opts->revs->no_walk &&
1115 + !opts->revs->cmdline.rev->flags) {
1116 + struct commit *cmit;
1117 + if (prepare_revision_walk(opts->revs))
1118 + die(_("revision walk setup failed"));
1119 + cmit = get_revision(opts->revs);
1120 + if (!cmit || get_revision(opts->revs))
1121 + die("BUG: expected exactly one commit from walk");
1122 + return single_pick(cmit, opts);
1123 + }
1124 +
1125 /*
1126 * Start a new cherry-pick/ revert sequence; but
1127 * first, make sure that an existing one isn't in
t/t3510-cherry-pick-sequence.sh
+12
@@ -50,6 +50,18 @@ test_expect_success 'cherry-pick persists data on failure' '
50 test_path_is_file .git/sequencer/opts
51 '
52
53 +test_expect_success 'cherry-pick mid-cherry-pick-sequence' '
54 + pristine_detach initial &&
55 + test_must_fail git cherry-pick base..anotherpick &&
56 + test_cmp_rev picked CHERRY_PICK_HEAD &&
57 + # "oops, I forgot that these patches rely on the change from base"
58 + git checkout HEAD foo &&
59 + git cherry-pick base &&
60 + git cherry-pick picked &&
61 + git cherry-pick --continue &&
62 + git diff --exit-code anotherpick
63 +'
64 +
65 test_expect_success 'cherry-pick persists opts correctly' '
66 pristine_detach initial &&
67 test_must_fail git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours base..anotherpick &&