Merge branch 'jn/revert-quit'
* jn/revert-quit: revert: remove --reset compatibility option revert: introduce --abort to cancel a failed cherry-pick revert: write REVERT_HEAD pseudoref during conflicted revert revert: improve error message for cherry-pick during cherry-pick revert: rearrange pick_revisions() for clarity revert: rename --reset option to --quit
This commit is contained in:
commit
9fd389b650
@ -9,8 +9,9 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>...
|
||||
'git cherry-pick' --reset
|
||||
'git cherry-pick' --continue
|
||||
'git cherry-pick' --quit
|
||||
'git cherry-pick' --abort
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
@ -9,8 +9,9 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>...
|
||||
'git revert' --reset
|
||||
'git revert' --continue
|
||||
'git revert' --quit
|
||||
'git revert' --abort
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
@ -1,9 +1,12 @@
|
||||
--reset::
|
||||
Forget about the current operation in progress. Can be used
|
||||
to clear the sequencer state after a failed cherry-pick or
|
||||
revert.
|
||||
|
||||
--continue::
|
||||
Continue the operation in progress using the information in
|
||||
'.git/sequencer'. Can be used to continue after resolving
|
||||
conflicts in a failed cherry-pick or revert.
|
||||
|
||||
--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.
|
||||
|
1
branch.c
1
branch.c
@ -241,6 +241,7 @@ void create_branch(const char *head,
|
||||
void remove_branch_state(void)
|
||||
{
|
||||
unlink(git_path("CHERRY_PICK_HEAD"));
|
||||
unlink(git_path("REVERT_HEAD"));
|
||||
unlink(git_path("MERGE_HEAD"));
|
||||
unlink(git_path("MERGE_RR"));
|
||||
unlink(git_path("MERGE_MSG"));
|
||||
|
@ -1514,6 +1514,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
|
||||
unlink(git_path("CHERRY_PICK_HEAD"));
|
||||
unlink(git_path("REVERT_HEAD"));
|
||||
unlink(git_path("MERGE_HEAD"));
|
||||
unlink(git_path("MERGE_MSG"));
|
||||
unlink(git_path("MERGE_MODE"));
|
||||
|
136
builtin/revert.c
136
builtin/revert.c
@ -40,7 +40,12 @@ static const char * const cherry_pick_usage[] = {
|
||||
};
|
||||
|
||||
enum replay_action { REVERT, CHERRY_PICK };
|
||||
enum replay_subcommand { REPLAY_NONE, REPLAY_RESET, REPLAY_CONTINUE };
|
||||
enum replay_subcommand {
|
||||
REPLAY_NONE,
|
||||
REPLAY_REMOVE_STATE,
|
||||
REPLAY_CONTINUE,
|
||||
REPLAY_ROLLBACK
|
||||
};
|
||||
|
||||
struct replay_opts {
|
||||
enum replay_action action;
|
||||
@ -133,11 +138,13 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
|
||||
{
|
||||
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
|
||||
const char *me = action_name(opts);
|
||||
int reset = 0;
|
||||
int remove_state = 0;
|
||||
int contin = 0;
|
||||
int rollback = 0;
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN(0, "reset", &reset, "forget the current operation"),
|
||||
OPT_BOOLEAN(0, "continue", &contin, "continue the current operation"),
|
||||
OPT_BOOLEAN(0, "quit", &remove_state, "end revert or cherry-pick sequence"),
|
||||
OPT_BOOLEAN(0, "continue", &contin, "resume revert or cherry-pick sequence"),
|
||||
OPT_BOOLEAN(0, "abort", &rollback, "cancel revert or cherry-pick sequence"),
|
||||
OPT_BOOLEAN('n', "no-commit", &opts->no_commit, "don't automatically commit"),
|
||||
OPT_BOOLEAN('e', "edit", &opts->edit, "edit the commit message"),
|
||||
OPT_NOOP_NOARG('r', NULL),
|
||||
@ -168,25 +175,32 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
|
||||
|
||||
/* Check for incompatible subcommands */
|
||||
verify_opt_mutually_compatible(me,
|
||||
"--reset", reset,
|
||||
"--quit", remove_state,
|
||||
"--continue", contin,
|
||||
"--abort", rollback,
|
||||
NULL);
|
||||
|
||||
/* Set the subcommand */
|
||||
if (reset)
|
||||
opts->subcommand = REPLAY_RESET;
|
||||
if (remove_state)
|
||||
opts->subcommand = REPLAY_REMOVE_STATE;
|
||||
else if (contin)
|
||||
opts->subcommand = REPLAY_CONTINUE;
|
||||
else if (rollback)
|
||||
opts->subcommand = REPLAY_ROLLBACK;
|
||||
else
|
||||
opts->subcommand = REPLAY_NONE;
|
||||
|
||||
/* Check for incompatible command line arguments */
|
||||
if (opts->subcommand != REPLAY_NONE) {
|
||||
char *this_operation;
|
||||
if (opts->subcommand == REPLAY_RESET)
|
||||
this_operation = "--reset";
|
||||
else
|
||||
if (opts->subcommand == REPLAY_REMOVE_STATE)
|
||||
this_operation = "--quit";
|
||||
else if (opts->subcommand == REPLAY_CONTINUE)
|
||||
this_operation = "--continue";
|
||||
else {
|
||||
assert(opts->subcommand == REPLAY_ROLLBACK);
|
||||
this_operation = "--abort";
|
||||
}
|
||||
|
||||
verify_opt_compatible(me, this_operation,
|
||||
"--no-commit", opts->no_commit,
|
||||
@ -286,7 +300,7 @@ static char *get_encoding(const char *message)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void write_cherry_pick_head(struct commit *commit)
|
||||
static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
|
||||
{
|
||||
const char *filename;
|
||||
int fd;
|
||||
@ -294,7 +308,7 @@ static void write_cherry_pick_head(struct commit *commit)
|
||||
|
||||
strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
|
||||
|
||||
filename = git_path("CHERRY_PICK_HEAD");
|
||||
filename = git_path(pseudoref);
|
||||
fd = open(filename, O_WRONLY | O_CREAT, 0666);
|
||||
if (fd < 0)
|
||||
die_errno(_("Could not open '%s' for writing"), filename);
|
||||
@ -594,7 +608,9 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||
* write it at all.
|
||||
*/
|
||||
if (opts->action == CHERRY_PICK && !opts->no_commit && (res == 0 || res == 1))
|
||||
write_cherry_pick_head(commit);
|
||||
write_cherry_pick_head(commit, "CHERRY_PICK_HEAD");
|
||||
if (opts->action == REVERT && ((opts->no_commit && res == 0) || res == 1))
|
||||
write_cherry_pick_head(commit, "REVERT_HEAD");
|
||||
|
||||
if (res) {
|
||||
error(opts->action == REVERT
|
||||
@ -843,8 +859,11 @@ static int create_seq_dir(void)
|
||||
{
|
||||
const char *seq_dir = git_path(SEQ_DIR);
|
||||
|
||||
if (file_exists(seq_dir))
|
||||
return error(_("%s already exists."), seq_dir);
|
||||
if (file_exists(seq_dir)) {
|
||||
error(_("a cherry-pick or revert is already in progress"));
|
||||
advise(_("try \"git cherry-pick (--continue | --quit | --abort)\""));
|
||||
return -1;
|
||||
}
|
||||
else if (mkdir(seq_dir, 0777) < 0)
|
||||
die_errno(_("Could not create sequencer directory %s"), seq_dir);
|
||||
return 0;
|
||||
@ -865,6 +884,71 @@ static void save_head(const char *head)
|
||||
die(_("Error wrapping up %s."), head_file);
|
||||
}
|
||||
|
||||
static int reset_for_rollback(const unsigned char *sha1)
|
||||
{
|
||||
const char *argv[4]; /* reset --merge <arg> + NULL */
|
||||
argv[0] = "reset";
|
||||
argv[1] = "--merge";
|
||||
argv[2] = sha1_to_hex(sha1);
|
||||
argv[3] = NULL;
|
||||
return run_command_v_opt(argv, RUN_GIT_CMD);
|
||||
}
|
||||
|
||||
static int rollback_single_pick(void)
|
||||
{
|
||||
unsigned char head_sha1[20];
|
||||
|
||||
if (!file_exists(git_path("CHERRY_PICK_HEAD")) &&
|
||||
!file_exists(git_path("REVERT_HEAD")))
|
||||
return error(_("no cherry-pick or revert in progress"));
|
||||
if (!resolve_ref("HEAD", head_sha1, 0, NULL))
|
||||
return error(_("cannot resolve HEAD"));
|
||||
if (is_null_sha1(head_sha1))
|
||||
return error(_("cannot abort from a branch yet to be born"));
|
||||
return reset_for_rollback(head_sha1);
|
||||
}
|
||||
|
||||
static int sequencer_rollback(struct replay_opts *opts)
|
||||
{
|
||||
const char *filename;
|
||||
FILE *f;
|
||||
unsigned char sha1[20];
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
filename = git_path(SEQ_HEAD_FILE);
|
||||
f = fopen(filename, "r");
|
||||
if (!f && errno == ENOENT) {
|
||||
/*
|
||||
* There is no multiple-cherry-pick in progress.
|
||||
* If CHERRY_PICK_HEAD or REVERT_HEAD indicates
|
||||
* a single-cherry-pick in progress, abort that.
|
||||
*/
|
||||
return rollback_single_pick();
|
||||
}
|
||||
if (!f)
|
||||
return error(_("cannot open %s: %s"), filename,
|
||||
strerror(errno));
|
||||
if (strbuf_getline(&buf, f, '\n')) {
|
||||
error(_("cannot read %s: %s"), filename, ferror(f) ?
|
||||
strerror(errno) : _("unexpected end of file"));
|
||||
goto fail;
|
||||
}
|
||||
if (get_sha1_hex(buf.buf, sha1) || buf.buf[40] != '\0') {
|
||||
error(_("stored pre-cherry-pick HEAD file '%s' is corrupt"),
|
||||
filename);
|
||||
goto fail;
|
||||
}
|
||||
if (reset_for_rollback(sha1))
|
||||
goto fail;
|
||||
strbuf_release(&buf);
|
||||
fclose(f);
|
||||
return 0;
|
||||
fail:
|
||||
strbuf_release(&buf);
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void save_todo(struct commit_list *todo_list, struct replay_opts *opts)
|
||||
{
|
||||
const char *todo_file = git_path(SEQ_TODO_FILE);
|
||||
@ -965,19 +1049,24 @@ static int pick_revisions(struct replay_opts *opts)
|
||||
* cherry-pick should be handled differently from an existing
|
||||
* one that is being continued
|
||||
*/
|
||||
if (opts->subcommand == REPLAY_RESET) {
|
||||
if (opts->subcommand == REPLAY_REMOVE_STATE) {
|
||||
remove_sequencer_state(1);
|
||||
return 0;
|
||||
} else if (opts->subcommand == REPLAY_CONTINUE) {
|
||||
}
|
||||
if (opts->subcommand == REPLAY_ROLLBACK)
|
||||
return sequencer_rollback(opts);
|
||||
if (opts->subcommand == REPLAY_CONTINUE) {
|
||||
if (!file_exists(git_path(SEQ_TODO_FILE)))
|
||||
goto error;
|
||||
return error(_("No %s in progress"), action_name(opts));
|
||||
read_populate_opts(&opts);
|
||||
read_populate_todo(&todo_list, opts);
|
||||
|
||||
/* Verify that the conflict has been resolved */
|
||||
if (!index_differs_from("HEAD", 0))
|
||||
todo_list = todo_list->next;
|
||||
} else {
|
||||
return pick_commits(todo_list, opts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a new cherry-pick/ revert sequence; but
|
||||
* first, make sure that an existing one isn't in
|
||||
@ -985,12 +1074,8 @@ static int pick_revisions(struct replay_opts *opts)
|
||||
*/
|
||||
|
||||
walk_revs_populate_todo(&todo_list, opts);
|
||||
if (create_seq_dir() < 0) {
|
||||
error(_("A cherry-pick or revert is in progress."));
|
||||
advise(_("Use --continue to continue the operation"));
|
||||
advise(_("or --reset to forget about it"));
|
||||
if (create_seq_dir() < 0)
|
||||
return -1;
|
||||
}
|
||||
if (get_sha1("HEAD", sha1)) {
|
||||
if (opts->action == REVERT)
|
||||
return error(_("Can't revert as initial commit"));
|
||||
@ -998,10 +1083,7 @@ static int pick_revisions(struct replay_opts *opts)
|
||||
}
|
||||
save_head(sha1_to_hex(sha1));
|
||||
save_opts(opts);
|
||||
}
|
||||
return pick_commits(todo_list, opts);
|
||||
error:
|
||||
return error(_("No %s in progress"), action_name(opts));
|
||||
}
|
||||
|
||||
int cmd_revert(int argc, const char **argv, const char *prefix)
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
* With the aggressive flag, it additionally removes SEQ_OLD_DIR,
|
||||
* ignoring any errors. Inteded to be used by the sequencer's
|
||||
* '--reset' subcommand.
|
||||
* '--quit' subcommand.
|
||||
*/
|
||||
void remove_sequencer_state(int aggressive);
|
||||
|
||||
|
@ -253,6 +253,60 @@ test_expect_success 'revert also handles conflicts sanely' '
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'failed revert sets REVERT_HEAD' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git revert picked &&
|
||||
test_cmp_rev picked REVERT_HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'successful revert does not set REVERT_HEAD' '
|
||||
pristine_detach base &&
|
||||
git revert base &&
|
||||
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
|
||||
test_must_fail git rev-parse --verify REVERT_HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'revert --no-commit sets REVERT_HEAD' '
|
||||
pristine_detach base &&
|
||||
git revert --no-commit base &&
|
||||
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
|
||||
test_cmp_rev base REVERT_HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
|
||||
pristine_detach base &&
|
||||
echo foo > foo &&
|
||||
test_must_fail git revert base &&
|
||||
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
|
||||
test_must_fail git rev-parse --verify REVERT_HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
|
||||
pristine_detach initial &&
|
||||
(
|
||||
GIT_CHERRY_PICK_HELP="and then do something else" &&
|
||||
GIT_REVERT_HELP="and then do something else, again" &&
|
||||
export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
|
||||
test_must_fail git revert picked
|
||||
) &&
|
||||
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
|
||||
test_cmp_rev picked REVERT_HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'git reset clears REVERT_HEAD' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git revert picked &&
|
||||
git reset &&
|
||||
test_must_fail git rev-parse --verify REVERT_HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'failed commit does not clear REVERT_HEAD' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git revert picked &&
|
||||
test_must_fail git commit &&
|
||||
test_cmp_rev picked REVERT_HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'revert conflict, diff3 -m style' '
|
||||
pristine_detach initial &&
|
||||
git config merge.conflictstyle diff3 &&
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
test_description='Test cherry-pick continuation features
|
||||
|
||||
+ yetanotherpick: rewrites foo to e
|
||||
+ anotherpick: rewrites foo to d
|
||||
+ picked: rewrites foo to c
|
||||
+ unrelatedpick: rewrites unrelated to reallyunrelated
|
||||
@ -13,12 +14,18 @@ test_description='Test cherry-pick continuation features
|
||||
. ./test-lib.sh
|
||||
|
||||
pristine_detach () {
|
||||
git cherry-pick --reset &&
|
||||
git cherry-pick --quit &&
|
||||
git checkout -f "$1^0" &&
|
||||
git read-tree -u --reset HEAD &&
|
||||
git clean -d -f -f -q -x
|
||||
}
|
||||
|
||||
test_cmp_rev () {
|
||||
git rev-parse --verify "$1" >expect.rev &&
|
||||
git rev-parse --verify "$2" >actual.rev &&
|
||||
test_cmp expect.rev actual.rev
|
||||
}
|
||||
|
||||
test_expect_success setup '
|
||||
echo unrelated >unrelated &&
|
||||
git add unrelated &&
|
||||
@ -27,6 +34,7 @@ test_expect_success setup '
|
||||
test_commit unrelatedpick unrelated reallyunrelated &&
|
||||
test_commit picked foo c &&
|
||||
test_commit anotherpick foo d &&
|
||||
test_commit yetanotherpick foo e &&
|
||||
git config advice.detachedhead false
|
||||
|
||||
'
|
||||
@ -70,18 +78,117 @@ test_expect_success 'cherry-pick cleans up sequencer state upon success' '
|
||||
test_path_is_missing .git/sequencer
|
||||
'
|
||||
|
||||
test_expect_success '--reset does not complain when no cherry-pick is in progress' '
|
||||
test_expect_success '--quit does not complain when no cherry-pick is in progress' '
|
||||
pristine_detach initial &&
|
||||
git cherry-pick --reset
|
||||
git cherry-pick --quit
|
||||
'
|
||||
|
||||
test_expect_success '--reset cleans up sequencer state' '
|
||||
test_expect_success '--abort requires cherry-pick in progress' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick --abort
|
||||
'
|
||||
|
||||
test_expect_success '--quit cleans up sequencer state' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick base..picked &&
|
||||
git cherry-pick --reset &&
|
||||
git cherry-pick --quit &&
|
||||
test_path_is_missing .git/sequencer
|
||||
'
|
||||
|
||||
test_expect_success '--quit keeps HEAD and conflicted index intact' '
|
||||
pristine_detach initial &&
|
||||
cat >expect <<-\EOF &&
|
||||
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..picked &&
|
||||
git cherry-pick --quit &&
|
||||
test_path_is_missing .git/sequencer &&
|
||||
test_must_fail git update-index --refresh &&
|
||||
{
|
||||
git rev-list HEAD |
|
||||
git diff-tree --root --stdin |
|
||||
sed "s/$_x40/OBJID/g"
|
||||
} >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success '--abort to cancel multiple cherry-pick' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick base..anotherpick &&
|
||||
git cherry-pick --abort &&
|
||||
test_path_is_missing .git/sequencer &&
|
||||
test_cmp_rev initial HEAD &&
|
||||
git update-index --refresh &&
|
||||
git diff-index --exit-code HEAD
|
||||
'
|
||||
|
||||
test_expect_success '--abort to cancel single cherry-pick' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick picked &&
|
||||
git cherry-pick --abort &&
|
||||
test_path_is_missing .git/sequencer &&
|
||||
test_cmp_rev initial HEAD &&
|
||||
git update-index --refresh &&
|
||||
git diff-index --exit-code HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'cherry-pick --abort to cancel multiple revert' '
|
||||
pristine_detach anotherpick &&
|
||||
test_must_fail git revert base..picked &&
|
||||
git cherry-pick --abort &&
|
||||
test_path_is_missing .git/sequencer &&
|
||||
test_cmp_rev anotherpick HEAD &&
|
||||
git update-index --refresh &&
|
||||
git diff-index --exit-code HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'revert --abort works, too' '
|
||||
pristine_detach anotherpick &&
|
||||
test_must_fail git revert base..picked &&
|
||||
git revert --abort &&
|
||||
test_path_is_missing .git/sequencer &&
|
||||
test_cmp_rev anotherpick HEAD
|
||||
'
|
||||
|
||||
test_expect_success '--abort to cancel single revert' '
|
||||
pristine_detach anotherpick &&
|
||||
test_must_fail git revert picked &&
|
||||
git revert --abort &&
|
||||
test_path_is_missing .git/sequencer &&
|
||||
test_cmp_rev anotherpick HEAD &&
|
||||
git update-index --refresh &&
|
||||
git diff-index --exit-code HEAD
|
||||
'
|
||||
|
||||
test_expect_success '--abort keeps unrelated change, easy case' '
|
||||
pristine_detach unrelatedpick &&
|
||||
echo changed >expect &&
|
||||
test_must_fail git cherry-pick picked..yetanotherpick &&
|
||||
echo changed >unrelated &&
|
||||
git cherry-pick --abort &&
|
||||
test_cmp expect unrelated
|
||||
'
|
||||
|
||||
test_expect_success '--abort refuses to clobber unrelated change, harder case' '
|
||||
pristine_detach initial &&
|
||||
echo changed >expect &&
|
||||
test_must_fail git cherry-pick base..anotherpick &&
|
||||
echo changed >unrelated &&
|
||||
test_must_fail git cherry-pick --abort &&
|
||||
test_cmp expect unrelated &&
|
||||
git rev-list HEAD >log &&
|
||||
test_line_count = 2 log &&
|
||||
test_must_fail git update-index --refresh &&
|
||||
|
||||
git checkout unrelated &&
|
||||
git cherry-pick --abort &&
|
||||
test_cmp_rev initial HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'cherry-pick cleans up sequencer state when one commit is left' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick base..picked &&
|
||||
@ -106,6 +213,16 @@ test_expect_success 'cherry-pick cleans up sequencer state when one commit is le
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_failure '--abort after last commit in sequence' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick base..picked &&
|
||||
git cherry-pick --abort &&
|
||||
test_path_is_missing .git/sequencer &&
|
||||
test_cmp_rev initial HEAD &&
|
||||
git update-index --refresh &&
|
||||
git diff-index --exit-code HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick base..anotherpick &&
|
||||
|
@ -12,7 +12,7 @@ test_description='Test interaction of reset --hard with sequencer
|
||||
. ./test-lib.sh
|
||||
|
||||
pristine_detach () {
|
||||
git cherry-pick --reset &&
|
||||
git cherry-pick --quit &&
|
||||
git checkout -f "$1^0" &&
|
||||
git read-tree -u --reset HEAD &&
|
||||
git clean -d -f -f -q -x
|
||||
|
Loading…
Reference in New Issue
Block a user