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 &&