Merge branch 'cc/cherry-pick-series'
* cc/cherry-pick-series: Documentation/revert: describe passing more than one commit Documentation/cherry-pick: describe passing more than one commit revert: add tests to check cherry-picking many commits revert: allow cherry-picking more than one commit revert: change help_msg() to take no argument revert: refactor code into a do_pick_commit() function revert: use run_command_v_opt() instead of execv_git_cmd() revert: cleanup code for -x optionmaint
commit
8c7da8690d
|
@ -3,24 +3,28 @@ git-cherry-pick(1)
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
----
|
----
|
||||||
git-cherry-pick - Apply the change introduced by an existing commit
|
git-cherry-pick - Apply the changes introduced by some existing commits
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>
|
'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Given one existing commit, apply the change the patch introduces, and record a
|
|
||||||
new commit that records it. This requires your working tree to be clean (no
|
Given one or more existing commits, apply the change each one
|
||||||
modifications from the HEAD commit).
|
introduces, recording a new commit for each. This requires your
|
||||||
|
working tree to be clean (no modifications from the HEAD commit).
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
<commit>::
|
<commit>...::
|
||||||
Commit to cherry-pick.
|
Commits to cherry-pick.
|
||||||
For a more complete list of ways to spell commits, see the
|
For a more complete list of ways to spell commits, see the
|
||||||
"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
||||||
|
Sets of commits can be passed but no traversal is done by
|
||||||
|
default, as if the '--no-walk' option was specified, see
|
||||||
|
linkgit:git-rev-list[1].
|
||||||
|
|
||||||
-e::
|
-e::
|
||||||
--edit::
|
--edit::
|
||||||
|
@ -55,10 +59,10 @@ OPTIONS
|
||||||
|
|
||||||
-n::
|
-n::
|
||||||
--no-commit::
|
--no-commit::
|
||||||
Usually the command automatically creates a commit.
|
Usually the command automatically creates a sequence of commits.
|
||||||
This flag applies the change necessary to cherry-pick
|
This flag applies the changes necessary to cherry-pick
|
||||||
the named commit to your working tree and the index,
|
each named commit to your working tree and the index,
|
||||||
but does not make the commit. In addition, when this
|
without making any commit. In addition, when this
|
||||||
option is used, your index does not have to match the
|
option is used, your index does not have to match the
|
||||||
HEAD commit. The cherry-pick is done against the
|
HEAD commit. The cherry-pick is done against the
|
||||||
beginning state of your index.
|
beginning state of your index.
|
||||||
|
@ -75,6 +79,40 @@ effect to your index in a row.
|
||||||
cherry-pick'ed commit, then a fast forward to this commit will
|
cherry-pick'ed commit, then a fast forward to this commit will
|
||||||
be performed.
|
be performed.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
git cherry-pick master::
|
||||||
|
|
||||||
|
Apply the change introduced by the commit at the tip of the
|
||||||
|
master branch and create a new commit with this change.
|
||||||
|
|
||||||
|
git cherry-pick ..master::
|
||||||
|
git cherry-pick ^HEAD master::
|
||||||
|
|
||||||
|
Apply the changes introduced by all commits that are ancestors
|
||||||
|
of master but not of HEAD to produce new commits.
|
||||||
|
|
||||||
|
git cherry-pick master\~4 master~2::
|
||||||
|
|
||||||
|
Apply the changes introduced by the fifth and third last
|
||||||
|
commits pointed to by master and create 2 new commits with
|
||||||
|
these changes.
|
||||||
|
|
||||||
|
git cherry-pick -n master~1 next::
|
||||||
|
|
||||||
|
Apply to the working tree and the index the changes introduced
|
||||||
|
by the second last commit pointed to by master and by the last
|
||||||
|
commit pointed to by next, but do not create any commit with
|
||||||
|
these changes.
|
||||||
|
|
||||||
|
git cherry-pick --ff ..next::
|
||||||
|
|
||||||
|
If history is linear and HEAD is an ancestor of next, update
|
||||||
|
the working tree and advance the HEAD pointer to match next.
|
||||||
|
Otherwise, apply the changes introduced by those commits that
|
||||||
|
are in next but not HEAD to the current branch, creating a new
|
||||||
|
commit for each new change.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Junio C Hamano <gitster@pobox.com>
|
Written by Junio C Hamano <gitster@pobox.com>
|
||||||
|
@ -83,6 +121,10 @@ Documentation
|
||||||
--------------
|
--------------
|
||||||
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
--------
|
||||||
|
linkgit:git-revert[1]
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
Part of the linkgit:git[1] suite
|
Part of the linkgit:git[1] suite
|
||||||
|
|
|
@ -3,20 +3,22 @@ git-revert(1)
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
----
|
----
|
||||||
git-revert - Revert an existing commit
|
git-revert - Revert some existing commits
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>
|
'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Given one existing commit, revert the change the patch introduces, and record a
|
|
||||||
new commit that records it. This requires your working tree to be clean (no
|
|
||||||
modifications from the HEAD commit).
|
|
||||||
|
|
||||||
Note: 'git revert' is used to record a new commit to reverse the
|
Given one or more existing commits, revert the changes that the
|
||||||
effect of an earlier commit (often a faulty one). If you want to
|
related patches introduce, and record some new commits that record
|
||||||
|
them. This requires your working tree to be clean (no modifications
|
||||||
|
from the HEAD commit).
|
||||||
|
|
||||||
|
Note: 'git revert' is used to record some new commits to reverse the
|
||||||
|
effect of some earlier commits (often only a faulty one). If you want to
|
||||||
throw away all uncommitted changes in your working directory, you
|
throw away all uncommitted changes in your working directory, you
|
||||||
should see linkgit:git-reset[1], particularly the '--hard' option. If
|
should see linkgit:git-reset[1], particularly the '--hard' option. If
|
||||||
you want to extract specific files as they were in another commit, you
|
you want to extract specific files as they were in another commit, you
|
||||||
|
@ -26,10 +28,13 @@ both will discard uncommitted changes in your working directory.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
<commit>::
|
<commit>...::
|
||||||
Commit to revert.
|
Commits to revert.
|
||||||
For a more complete list of ways to spell commit names, see
|
For a more complete list of ways to spell commit names, see
|
||||||
"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
||||||
|
Sets of commits can also be given but no traversal is done by
|
||||||
|
default, see linkgit:git-rev-list[1] and its '--no-walk'
|
||||||
|
option.
|
||||||
|
|
||||||
-e::
|
-e::
|
||||||
--edit::
|
--edit::
|
||||||
|
@ -59,11 +64,11 @@ more details.
|
||||||
|
|
||||||
-n::
|
-n::
|
||||||
--no-commit::
|
--no-commit::
|
||||||
Usually the command automatically creates a commit with
|
Usually the command automatically creates some commits with
|
||||||
a commit log message stating which commit was
|
commit log messages stating which commits were
|
||||||
reverted. This flag applies the change necessary
|
reverted. This flag applies the changes necessary
|
||||||
to revert the named commit to your working tree
|
to revert the named commits to your working tree
|
||||||
and the index, but does not make the commit. In addition,
|
and the index, but does not make the commits. In addition,
|
||||||
when this option is used, your index does not have to match
|
when this option is used, your index does not have to match
|
||||||
the HEAD commit. The revert is done against the
|
the HEAD commit. The revert is done against the
|
||||||
beginning state of your index.
|
beginning state of your index.
|
||||||
|
@ -75,6 +80,20 @@ effect to your index in a row.
|
||||||
--signoff::
|
--signoff::
|
||||||
Add Signed-off-by line at the end of the commit message.
|
Add Signed-off-by line at the end of the commit message.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
git revert HEAD~3::
|
||||||
|
|
||||||
|
Revert the changes specified by the fourth last commit in HEAD
|
||||||
|
and create a new commit with the reverted changes.
|
||||||
|
|
||||||
|
git revert -n master\~5..master~2::
|
||||||
|
|
||||||
|
Revert the changes done by commits from the fifth last commit
|
||||||
|
in master (included) to the third last commit in master
|
||||||
|
(included), but do not create any commit with the reverted
|
||||||
|
changes. The revert only modifies the working tree and the
|
||||||
|
index.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -84,6 +103,10 @@ Documentation
|
||||||
--------------
|
--------------
|
||||||
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
--------
|
||||||
|
linkgit:git-cherry-pick[1]
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
Part of the linkgit:git[1] suite
|
Part of the linkgit:git[1] suite
|
||||||
|
|
120
builtin/revert.c
120
builtin/revert.c
|
@ -39,7 +39,8 @@ static const char * const cherry_pick_usage[] = {
|
||||||
static int edit, no_replay, no_commit, mainline, signoff, allow_ff;
|
static int edit, no_replay, no_commit, mainline, signoff, allow_ff;
|
||||||
static enum { REVERT, CHERRY_PICK } action;
|
static enum { REVERT, CHERRY_PICK } action;
|
||||||
static struct commit *commit;
|
static struct commit *commit;
|
||||||
static const char *commit_name;
|
static int commit_argc;
|
||||||
|
static const char **commit_argv;
|
||||||
static int allow_rerere_auto;
|
static int allow_rerere_auto;
|
||||||
|
|
||||||
static const char *me;
|
static const char *me;
|
||||||
|
@ -53,12 +54,10 @@ static void parse_args(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
const char * const * usage_str =
|
const char * const * usage_str =
|
||||||
action == REVERT ? revert_usage : cherry_pick_usage;
|
action == REVERT ? revert_usage : cherry_pick_usage;
|
||||||
unsigned char sha1[20];
|
|
||||||
int noop;
|
int noop;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
|
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
|
||||||
OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
|
OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
|
||||||
OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"),
|
|
||||||
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
|
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
|
||||||
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
|
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
|
||||||
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
|
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
|
||||||
|
@ -71,6 +70,7 @@ static void parse_args(int argc, const char **argv)
|
||||||
|
|
||||||
if (action == CHERRY_PICK) {
|
if (action == CHERRY_PICK) {
|
||||||
struct option cp_extra[] = {
|
struct option cp_extra[] = {
|
||||||
|
OPT_BOOLEAN('x', NULL, &no_replay, "append commit name"),
|
||||||
OPT_BOOLEAN(0, "ff", &allow_ff, "allow fast-forward"),
|
OPT_BOOLEAN(0, "ff", &allow_ff, "allow fast-forward"),
|
||||||
OPT_END(),
|
OPT_END(),
|
||||||
};
|
};
|
||||||
|
@ -78,15 +78,11 @@ static void parse_args(int argc, const char **argv)
|
||||||
die("program error");
|
die("program error");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)
|
commit_argc = parse_options(argc, argv, NULL, options, usage_str, 0);
|
||||||
|
if (commit_argc < 1)
|
||||||
usage_with_options(usage_str, options);
|
usage_with_options(usage_str, options);
|
||||||
|
|
||||||
commit_name = argv[0];
|
commit_argv = argv;
|
||||||
if (get_sha1(commit_name, sha1))
|
|
||||||
die ("Cannot find '%s'", commit_name);
|
|
||||||
commit = lookup_commit_reference(sha1);
|
|
||||||
if (!commit)
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct commit_message {
|
struct commit_message {
|
||||||
|
@ -239,7 +235,7 @@ static void set_author_ident_env(const char *message)
|
||||||
sha1_to_hex(commit->object.sha1));
|
sha1_to_hex(commit->object.sha1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *help_msg(const char *name)
|
static char *help_msg(void)
|
||||||
{
|
{
|
||||||
struct strbuf helpbuf = STRBUF_INIT;
|
struct strbuf helpbuf = STRBUF_INIT;
|
||||||
char *msg = getenv("GIT_CHERRY_PICK_HELP");
|
char *msg = getenv("GIT_CHERRY_PICK_HELP");
|
||||||
|
@ -255,7 +251,7 @@ static char *help_msg(const char *name)
|
||||||
strbuf_addf(&helpbuf, " with: \n"
|
strbuf_addf(&helpbuf, " with: \n"
|
||||||
"\n"
|
"\n"
|
||||||
" git commit -c %s\n",
|
" git commit -c %s\n",
|
||||||
name);
|
sha1_to_hex(commit->object.sha1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
strbuf_addch(&helpbuf, '.');
|
strbuf_addch(&helpbuf, '.');
|
||||||
|
@ -357,7 +353,7 @@ static void do_recursive_merge(struct commit *base, struct commit *next,
|
||||||
}
|
}
|
||||||
write_message(msgbuf, defmsg);
|
write_message(msgbuf, defmsg);
|
||||||
fprintf(stderr, "Automatic %s failed.%s\n",
|
fprintf(stderr, "Automatic %s failed.%s\n",
|
||||||
me, help_msg(commit_name));
|
me, help_msg());
|
||||||
rerere(allow_rerere_auto);
|
rerere(allow_rerere_auto);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -365,7 +361,7 @@ static void do_recursive_merge(struct commit *base, struct commit *next,
|
||||||
fprintf(stderr, "Finished one %s.\n", me);
|
fprintf(stderr, "Finished one %s.\n", me);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int revert_or_cherry_pick(int argc, const char **argv)
|
static int do_pick_commit(void)
|
||||||
{
|
{
|
||||||
unsigned char head[20];
|
unsigned char head[20];
|
||||||
struct commit *base, *next, *parent;
|
struct commit *base, *next, *parent;
|
||||||
|
@ -374,28 +370,6 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
||||||
char *defmsg = NULL;
|
char *defmsg = NULL;
|
||||||
struct strbuf msgbuf = STRBUF_INIT;
|
struct strbuf msgbuf = STRBUF_INIT;
|
||||||
|
|
||||||
git_config(git_default_config, NULL);
|
|
||||||
me = action == REVERT ? "revert" : "cherry-pick";
|
|
||||||
setenv(GIT_REFLOG_ACTION, me, 0);
|
|
||||||
parse_args(argc, argv);
|
|
||||||
|
|
||||||
/* this is copied from the shell script, but it's never triggered... */
|
|
||||||
if (action == REVERT && !no_replay)
|
|
||||||
die("revert is incompatible with replay");
|
|
||||||
|
|
||||||
if (allow_ff) {
|
|
||||||
if (signoff)
|
|
||||||
die("cherry-pick --ff cannot be used with --signoff");
|
|
||||||
if (no_commit)
|
|
||||||
die("cherry-pick --ff cannot be used with --no-commit");
|
|
||||||
if (no_replay)
|
|
||||||
die("cherry-pick --ff cannot be used with -x");
|
|
||||||
if (edit)
|
|
||||||
die("cherry-pick --ff cannot be used with --edit");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_cache() < 0)
|
|
||||||
die("git %s: failed to read the index", me);
|
|
||||||
if (no_commit) {
|
if (no_commit) {
|
||||||
/*
|
/*
|
||||||
* We do not intend to commit immediately. We just want to
|
* We do not intend to commit immediately. We just want to
|
||||||
|
@ -506,12 +480,14 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
||||||
free_commit_list(remotes);
|
free_commit_list(remotes);
|
||||||
if (res) {
|
if (res) {
|
||||||
fprintf(stderr, "Automatic %s with strategy %s failed.%s\n",
|
fprintf(stderr, "Automatic %s with strategy %s failed.%s\n",
|
||||||
me, strategy, help_msg(commit_name));
|
me, strategy, help_msg());
|
||||||
rerere(allow_rerere_auto);
|
rerere(allow_rerere_auto);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_message(&msg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* If we are cherry-pick, and if the merge did not result in
|
* If we are cherry-pick, and if the merge did not result in
|
||||||
|
@ -524,7 +500,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
||||||
if (!no_commit) {
|
if (!no_commit) {
|
||||||
/* 6 is max possible length of our args array including NULL */
|
/* 6 is max possible length of our args array including NULL */
|
||||||
const char *args[6];
|
const char *args[6];
|
||||||
|
int res;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
args[i++] = "commit";
|
args[i++] = "commit";
|
||||||
args[i++] = "-n";
|
args[i++] = "-n";
|
||||||
if (signoff)
|
if (signoff)
|
||||||
|
@ -534,26 +512,86 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
||||||
args[i++] = defmsg;
|
args[i++] = defmsg;
|
||||||
}
|
}
|
||||||
args[i] = NULL;
|
args[i] = NULL;
|
||||||
return execv_git_cmd(args);
|
res = run_command_v_opt(args, RUN_GIT_CMD);
|
||||||
|
free(defmsg);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
free_message(&msg);
|
|
||||||
free(defmsg);
|
free(defmsg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void prepare_revs(struct rev_info *revs)
|
||||||
|
{
|
||||||
|
int argc = 0;
|
||||||
|
int i;
|
||||||
|
const char **argv = xmalloc((commit_argc + 4) * sizeof(*argv));
|
||||||
|
|
||||||
|
argv[argc++] = NULL;
|
||||||
|
argv[argc++] = "--no-walk";
|
||||||
|
if (action != REVERT)
|
||||||
|
argv[argc++] = "--reverse";
|
||||||
|
for (i = 0; i < commit_argc; i++)
|
||||||
|
argv[argc++] = commit_argv[i];
|
||||||
|
argv[argc++] = NULL;
|
||||||
|
|
||||||
|
init_revisions(revs, NULL);
|
||||||
|
setup_revisions(argc - 1, argv, revs, NULL);
|
||||||
|
if (prepare_revision_walk(revs))
|
||||||
|
die("revision walk setup failed");
|
||||||
|
|
||||||
|
if (!revs->commits)
|
||||||
|
die("empty commit set passed");
|
||||||
|
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int revert_or_cherry_pick(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
struct rev_info revs;
|
||||||
|
|
||||||
|
git_config(git_default_config, NULL);
|
||||||
|
me = action == REVERT ? "revert" : "cherry-pick";
|
||||||
|
setenv(GIT_REFLOG_ACTION, me, 0);
|
||||||
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
if (allow_ff) {
|
||||||
|
if (signoff)
|
||||||
|
die("cherry-pick --ff cannot be used with --signoff");
|
||||||
|
if (no_commit)
|
||||||
|
die("cherry-pick --ff cannot be used with --no-commit");
|
||||||
|
if (no_replay)
|
||||||
|
die("cherry-pick --ff cannot be used with -x");
|
||||||
|
if (edit)
|
||||||
|
die("cherry-pick --ff cannot be used with --edit");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_cache() < 0)
|
||||||
|
die("git %s: failed to read the index", me);
|
||||||
|
|
||||||
|
prepare_revs(&revs);
|
||||||
|
|
||||||
|
while ((commit = get_revision(&revs))) {
|
||||||
|
int res = do_pick_commit();
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_revert(int argc, const char **argv, const char *prefix)
|
int cmd_revert(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
if (isatty(0))
|
if (isatty(0))
|
||||||
edit = 1;
|
edit = 1;
|
||||||
no_replay = 1;
|
|
||||||
action = REVERT;
|
action = REVERT;
|
||||||
return revert_or_cherry_pick(argc, argv);
|
return revert_or_cherry_pick(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
|
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
no_replay = 0;
|
|
||||||
action = CHERRY_PICK;
|
action = CHERRY_PICK;
|
||||||
return revert_or_cherry_pick(argc, argv);
|
return revert_or_cherry_pick(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='test cherry-picking many commits'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_expect_success setup '
|
||||||
|
echo first > file1 &&
|
||||||
|
git add file1 &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "first" &&
|
||||||
|
git tag first &&
|
||||||
|
|
||||||
|
git checkout -b other &&
|
||||||
|
for val in second third fourth
|
||||||
|
do
|
||||||
|
echo $val >> file1 &&
|
||||||
|
git add file1 &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "$val" &&
|
||||||
|
git tag $val
|
||||||
|
done
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cherry-pick first..fourth works' '
|
||||||
|
git checkout master &&
|
||||||
|
git reset --hard first &&
|
||||||
|
test_tick &&
|
||||||
|
git cherry-pick first..fourth &&
|
||||||
|
git diff --quiet other &&
|
||||||
|
git diff --quiet HEAD other &&
|
||||||
|
test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cherry-pick --ff first..fourth works' '
|
||||||
|
git checkout master &&
|
||||||
|
git reset --hard first &&
|
||||||
|
test_tick &&
|
||||||
|
git cherry-pick --ff first..fourth &&
|
||||||
|
git diff --quiet other &&
|
||||||
|
git diff --quiet HEAD other &&
|
||||||
|
test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify fourth)"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cherry-pick -n first..fourth works' '
|
||||||
|
git checkout master &&
|
||||||
|
git reset --hard first &&
|
||||||
|
test_tick &&
|
||||||
|
git cherry-pick -n first..fourth &&
|
||||||
|
git diff --quiet other &&
|
||||||
|
git diff --cached --quiet other &&
|
||||||
|
git diff --quiet HEAD first
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'revert first..fourth works' '
|
||||||
|
git checkout master &&
|
||||||
|
git reset --hard fourth &&
|
||||||
|
test_tick &&
|
||||||
|
git revert first..fourth &&
|
||||||
|
git diff --quiet first &&
|
||||||
|
git diff --cached --quiet first &&
|
||||||
|
git diff --quiet HEAD first
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'revert ^first fourth works' '
|
||||||
|
git checkout master &&
|
||||||
|
git reset --hard fourth &&
|
||||||
|
test_tick &&
|
||||||
|
git revert ^first fourth &&
|
||||||
|
git diff --quiet first &&
|
||||||
|
git diff --cached --quiet first &&
|
||||||
|
git diff --quiet HEAD first
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'revert fourth fourth~1 fourth~2 works' '
|
||||||
|
git checkout master &&
|
||||||
|
git reset --hard fourth &&
|
||||||
|
test_tick &&
|
||||||
|
git revert fourth fourth~1 fourth~2 &&
|
||||||
|
git diff --quiet first &&
|
||||||
|
git diff --cached --quiet first &&
|
||||||
|
git diff --quiet HEAD first
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_failure 'cherry-pick -3 fourth works' '
|
||||||
|
git checkout master &&
|
||||||
|
git reset --hard first &&
|
||||||
|
test_tick &&
|
||||||
|
git cherry-pick -3 fourth &&
|
||||||
|
git diff --quiet other &&
|
||||||
|
git diff --quiet HEAD other &&
|
||||||
|
test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue