Skip to content

Commit 7acaaac

Browse files
jrngitster
authored andcommitted
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 <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7f13334 commit 7acaaac

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

builtin/revert.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,12 @@ static int sequencer_continue(struct replay_opts *opts)
10721072
return pick_commits(todo_list, opts);
10731073
}
10741074

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+
10751081
static int pick_revisions(struct replay_opts *opts)
10761082
{
10771083
struct commit_list *todo_list = NULL;
@@ -1096,6 +1102,26 @@ static int pick_revisions(struct replay_opts *opts)
10961102
if (opts->subcommand == REPLAY_CONTINUE)
10971103
return sequencer_continue(opts);
10981104

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+
10991125
/*
11001126
* Start a new cherry-pick/ revert sequence; but
11011127
* first, make sure that an existing one isn't in

t/t3510-cherry-pick-sequence.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ test_expect_success 'cherry-pick persists data on failure' '
5050
test_path_is_file .git/sequencer/opts
5151
'
5252

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+
5365
test_expect_success 'cherry-pick persists opts correctly' '
5466
pristine_detach initial &&
5567
test_must_fail git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours base..anotherpick &&

0 commit comments

Comments
 (0)