* [PATCH v3 1/9] reset: refactor updating heads into a static function
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 2/9] reset: refactor reseting in its own function Christian Couder
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin/reset.c | 42 ++++++++++++++++++++++++++----------------
1 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/builtin/reset.c b/builtin/reset.c
index 2c3a69a..7af1cb1 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -229,7 +229,30 @@ static void die_if_unmerged_cache(int reset_type)
if (is_merge() || read_cache() < 0 || unmerged_cache())
die("Cannot do a %s reset in the middle of a merge.",
reset_type_names[reset_type]);
+}
+
+/*
+ * Any resets update HEAD to the head being switched to,
+ * saving the previous head in ORIG_HEAD before.
+ */
+static int update_heads(unsigned char *sha1)
+{
+ unsigned char sha1_orig[20], *orig = NULL,
+ sha1_old_orig[20], *old_orig = NULL;
+ char msg[1024];
+
+ if (!get_sha1("ORIG_HEAD", sha1_old_orig))
+ old_orig = sha1_old_orig;
+ if (!get_sha1("HEAD", sha1_orig)) {
+ orig = sha1_orig;
+ prepend_reflog_action("updating ORIG_HEAD", msg, sizeof(msg));
+ update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
+ }
+ else if (old_orig)
+ delete_ref("ORIG_HEAD", old_orig, 0);
+ prepend_reflog_action("updating HEAD", msg, sizeof(msg));
+ return update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
}
int cmd_reset(int argc, const char **argv, const char *prefix)
@@ -237,10 +260,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;
int patch_mode = 0;
const char *rev = "HEAD";
- unsigned char sha1[20], *orig = NULL, sha1_orig[20],
- *old_orig = NULL, sha1_old_orig[20];
+ unsigned char sha1[20];
struct commit *commit;
- char *reflog_action, msg[1024];
+ char *reflog_action;
const struct option options[] = {
OPT__QUIET(&quiet),
OPT_SET_INT(0, "mixed", &reset_type,
@@ -350,19 +372,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
die("Could not reset index file to revision '%s'.", rev);
}
- /* Any resets update HEAD to the head being switched to,
- * saving the previous head in ORIG_HEAD before. */
- if (!get_sha1("ORIG_HEAD", sha1_old_orig))
- old_orig = sha1_old_orig;
- if (!get_sha1("HEAD", sha1_orig)) {
- orig = sha1_orig;
- prepend_reflog_action("updating ORIG_HEAD", msg, sizeof(msg));
- update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
- }
- else if (old_orig)
- delete_ref("ORIG_HEAD", old_orig, 0);
- prepend_reflog_action("updating HEAD", msg, sizeof(msg));
- update_ref_status = update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
+ update_ref_status = update_heads(sha1);
switch (reset_type) {
case HARD:
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 2/9] reset: refactor reseting in its own function
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
2010-03-03 20:11 ` [PATCH v3 1/9] reset: refactor updating heads into a static function Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 3/9] reset: make reset function non static and declare it in "reset.h" Christian Couder
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
This splits the reseting logic away from the argument parsing.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin/reset.c | 140 +++++++++++++++++++++++++++++--------------------------
1 files changed, 74 insertions(+), 66 deletions(-)
diff --git a/builtin/reset.c b/builtin/reset.c
index 7af1cb1..b2239d2 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -255,70 +255,13 @@ static int update_heads(unsigned char *sha1)
return update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
}
-int cmd_reset(int argc, const char **argv, const char *prefix)
+static int reset(const char *rev, const char *prefix,
+ int reset_type, int quiet, int patch_mode,
+ int argc, const char **argv)
{
- int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;
- int patch_mode = 0;
- const char *rev = "HEAD";
- unsigned char sha1[20];
struct commit *commit;
- char *reflog_action;
- const struct option options[] = {
- OPT__QUIET(&quiet),
- OPT_SET_INT(0, "mixed", &reset_type,
- "reset HEAD and index", MIXED),
- OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
- OPT_SET_INT(0, "hard", &reset_type,
- "reset HEAD, index and working tree", HARD),
- OPT_SET_INT(0, "merge", &reset_type,
- "reset HEAD, index and working tree", MERGE),
- OPT_SET_INT(0, "keep", &reset_type,
- "reset HEAD but keep local changes", KEEP),
- OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
- OPT_END()
- };
-
- git_config(git_default_config, NULL);
-
- argc = parse_options(argc, argv, prefix, options, git_reset_usage,
- PARSE_OPT_KEEP_DASHDASH);
- reflog_action = args_to_str(argv);
- setenv("GIT_REFLOG_ACTION", reflog_action, 0);
-
- /*
- * Possible arguments are:
- *
- * git reset [-opts] <rev> <paths>...
- * git reset [-opts] <rev> -- <paths>...
- * git reset [-opts] -- <paths>...
- * git reset [-opts] <paths>...
- *
- * At this point, argv[i] points immediately after [-opts].
- */
-
- if (i < argc) {
- if (!strcmp(argv[i], "--")) {
- i++; /* reset to HEAD, possibly with paths */
- } else if (i + 1 < argc && !strcmp(argv[i+1], "--")) {
- rev = argv[i];
- i += 2;
- }
- /*
- * Otherwise, argv[i] could be either <rev> or <paths> and
- * has to be unambiguous.
- */
- else if (!get_sha1(argv[i], sha1)) {
- /*
- * Ok, argv[i] looks like a rev; it should not
- * be a filename.
- */
- verify_non_filename(prefix, argv[i]);
- rev = argv[i++];
- } else {
- /* Otherwise we treat this as a filename */
- verify_filename(prefix, argv[i]);
- }
- }
+ unsigned char sha1[20];
+ int update_ref_status;
if (get_sha1(rev, sha1))
die("Failed to resolve '%s' as a valid ref.", rev);
@@ -331,19 +274,19 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (patch_mode) {
if (reset_type != NONE)
die("--patch is incompatible with --{hard,mixed,soft}");
- return interactive_reset(rev, argv + i, prefix);
+ return interactive_reset(rev, argv, prefix);
}
/* git reset tree [--] paths... can be used to
* load chosen paths from the tree into the index without
* affecting the working tree nor HEAD. */
- if (i < argc) {
+ if (argc > 0) {
if (reset_type == MIXED)
warning("--mixed option is deprecated with paths.");
else if (reset_type != NONE)
die("Cannot do %s reset with paths.",
reset_type_names[reset_type]);
- return read_from_tree(prefix, argv + i, sha1,
+ return read_from_tree(prefix, argv, sha1,
quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN);
}
if (reset_type == NONE)
@@ -389,7 +332,72 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
remove_branch_state();
+ return update_ref_status;
+}
+
+int cmd_reset(int argc, const char **argv, const char *prefix)
+{
+ int i = 0, reset_type = NONE, quiet = 0;
+ int patch_mode = 0;
+ const char *rev = "HEAD";
+ unsigned char sha1[20];
+ char *reflog_action;
+ const struct option options[] = {
+ OPT__QUIET(&quiet),
+ OPT_SET_INT(0, "mixed", &reset_type,
+ "reset HEAD and index", MIXED),
+ OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
+ OPT_SET_INT(0, "hard", &reset_type,
+ "reset HEAD, index and working tree", HARD),
+ OPT_SET_INT(0, "merge", &reset_type,
+ "reset HEAD, index and working tree", MERGE),
+ OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
+ OPT_END()
+ };
+
+ git_config(git_default_config, NULL);
+
+ argc = parse_options(argc, argv, prefix, options, git_reset_usage,
+ PARSE_OPT_KEEP_DASHDASH);
+ reflog_action = args_to_str(argv);
+ setenv("GIT_REFLOG_ACTION", reflog_action, 0);
free(reflog_action);
- return update_ref_status;
+ /*
+ * Possible arguments are:
+ *
+ * git reset [-opts] <rev> <paths>...
+ * git reset [-opts] <rev> -- <paths>...
+ * git reset [-opts] -- <paths>...
+ * git reset [-opts] <paths>...
+ *
+ * At this point, argv[i] points immediately after [-opts].
+ */
+
+ if (i < argc) {
+ if (!strcmp(argv[i], "--")) {
+ i++; /* reset to HEAD, possibly with paths */
+ } else if (i + 1 < argc && !strcmp(argv[i+1], "--")) {
+ rev = argv[i];
+ i += 2;
+ }
+ /*
+ * Otherwise, argv[i] could be either <rev> or <paths> and
+ * has to be unambiguous.
+ */
+ else if (!get_sha1(argv[i], sha1)) {
+ /*
+ * Ok, argv[i] looks like a rev; it should not
+ * be a filename.
+ */
+ verify_non_filename(prefix, argv[i]);
+ rev = argv[i++];
+ } else {
+ /* Otherwise we treat this as a filename */
+ verify_filename(prefix, argv[i]);
+ }
+ }
+
+ return reset(rev, prefix, reset_type, quiet, patch_mode,
+ argc - i, argv + i);
}
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 3/9] reset: make reset function non static and declare it in "reset.h"
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
2010-03-03 20:11 ` [PATCH v3 1/9] reset: refactor updating heads into a static function Christian Couder
2010-03-03 20:11 ` [PATCH v3 2/9] reset: refactor reseting in its own function Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 4/9] revert: refactor checking parent in a check_parent() function Christian Couder
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin/reset.c | 8 ++++----
reset.h | 10 ++++++++++
2 files changed, 14 insertions(+), 4 deletions(-)
create mode 100644 reset.h
diff --git a/builtin/reset.c b/builtin/reset.c
index b2239d2..f1d7a5a 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -20,6 +20,7 @@
#include "parse-options.h"
#include "unpack-trees.h"
#include "cache-tree.h"
+#include "reset.h"
static const char * const git_reset_usage[] = {
"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]",
@@ -27,7 +28,6 @@ static const char * const git_reset_usage[] = {
NULL
};
-enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };
static const char *reset_type_names[] = {
"mixed", "soft", "hard", "merge", "keep", NULL
};
@@ -255,9 +255,9 @@ static int update_heads(unsigned char *sha1)
return update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
}
-static int reset(const char *rev, const char *prefix,
- int reset_type, int quiet, int patch_mode,
- int argc, const char **argv)
+int reset(const char *rev, const char *prefix,
+ int reset_type, int quiet, int patch_mode,
+ int argc, const char **argv)
{
struct commit *commit;
unsigned char sha1[20];
diff --git a/reset.h b/reset.h
new file mode 100644
index 0000000..05d2205
--- /dev/null
+++ b/reset.h
@@ -0,0 +1,10 @@
+#ifndef RESET_H
+#define RESET_H
+
+enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };
+
+int reset(const char *rev, const char *prefix,
+ int reset_type, int quiet, int patch_mode,
+ int argc, const char **argv);
+
+#endif
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 4/9] revert: refactor checking parent in a check_parent() function
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
` (2 preceding siblings ...)
2010-03-03 20:11 ` [PATCH v3 3/9] reset: make reset function non static and declare it in "reset.h" Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 5/9] revert: add --ff option to allow fast forward when cherry-picking Christian Couder
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin/revert.c | 62 ++++++++++++++++++++++++++++++-----------------------
1 files changed, 35 insertions(+), 27 deletions(-)
diff --git a/builtin/revert.c b/builtin/revert.c
index eff5268..a611960 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -244,6 +244,40 @@ static NORETURN void die_dirty_index(const char *me)
}
}
+static struct commit * check_parent(struct commit *commit, int mainline)
+{
+ if (!commit->parents) {
+ if (action == REVERT)
+ die ("Cannot revert a root commit");
+ return NULL;
+ }
+
+ if (commit->parents->next) {
+ /* Reverting or cherry-picking a merge commit */
+ int cnt;
+ struct commit_list *p;
+
+ if (!mainline)
+ die("Commit %s is a merge but no -m option was given.",
+ sha1_to_hex(commit->object.sha1));
+
+ for (cnt = 1, p = commit->parents;
+ cnt != mainline && p;
+ cnt++)
+ p = p->next;
+ if (cnt != mainline || !p)
+ die("Commit %s does not have parent %d",
+ sha1_to_hex(commit->object.sha1), mainline);
+ return p->item;
+ }
+
+ if (0 < mainline)
+ die("Mainline was specified but commit %s is not a merge.",
+ sha1_to_hex(commit->object.sha1));
+
+ return commit->parents->item;
+}
+
static int revert_or_cherry_pick(int argc, const char **argv)
{
unsigned char head[20];
@@ -286,33 +320,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
index_fd = hold_locked_index(&index_lock, 1);
- if (!commit->parents) {
- if (action == REVERT)
- die ("Cannot revert a root commit");
- parent = NULL;
- }
- else if (commit->parents->next) {
- /* Reverting or cherry-picking a merge commit */
- int cnt;
- struct commit_list *p;
-
- if (!mainline)
- die("Commit %s is a merge but no -m option was given.",
- sha1_to_hex(commit->object.sha1));
-
- for (cnt = 1, p = commit->parents;
- cnt != mainline && p;
- cnt++)
- p = p->next;
- if (cnt != mainline || !p)
- die("Commit %s does not have parent %d",
- sha1_to_hex(commit->object.sha1), mainline);
- parent = p->item;
- } else if (0 < mainline)
- die("Mainline was specified but commit %s is not a merge.",
- sha1_to_hex(commit->object.sha1));
- else
- parent = commit->parents->item;
+ parent = check_parent(commit, mainline);
if (!(message = commit->buffer))
die ("Cannot get commit message for %s",
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 5/9] revert: add --ff option to allow fast forward when cherry-picking
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
` (3 preceding siblings ...)
2010-03-03 20:11 ` [PATCH v3 4/9] revert: refactor checking parent in a check_parent() function Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 6/9] cherry-pick: add tests for new --ff option Christian Couder
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
As "git merge" fast forwards if possible, it seems sensible to
have such a feature for "git cherry-pick" too, especially as it
could be used in git-rebase--interactive.sh.
Maybe this option could be made the default in the long run, with
another --no-ff option to disable this default behavior, but that
could make some scripts backward incompatible and/or that would
require testing if some GIT_AUTHOR_* environment variables are
set. So we don't do that for now.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin/revert.c | 32 ++++++++++++++++++++++----------
1 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/builtin/revert.c b/builtin/revert.c
index a611960..4799073 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -13,6 +13,7 @@
#include "revision.h"
#include "rerere.h"
#include "merge-recursive.h"
+#include "reset.h"
/*
* This implements the builtins revert and cherry-pick.
@@ -35,7 +36,7 @@ static const char * const cherry_pick_usage[] = {
NULL
};
-static int edit, no_replay, no_commit, mainline, signoff;
+static int edit, no_replay, no_commit, mainline, signoff, ff_ok;
static enum { REVERT, CHERRY_PICK } action;
static struct commit *commit;
static const char *commit_name;
@@ -57,6 +58,7 @@ static void parse_args(int argc, const char **argv)
OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"),
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
+ OPT_BOOLEAN(0, "ff", &ff_ok, "allow fast forward"),
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
OPT_END(),
@@ -278,7 +280,7 @@ static struct commit * check_parent(struct commit *commit, int mainline)
return commit->parents->item;
}
-static int revert_or_cherry_pick(int argc, const char **argv)
+static int revert_or_cherry_pick(int argc, const char **argv, const char *prefix)
{
unsigned char head[20];
struct commit *base, *next, *parent;
@@ -318,18 +320,28 @@ static int revert_or_cherry_pick(int argc, const char **argv)
}
discard_cache();
- index_fd = hold_locked_index(&index_lock, 1);
-
parent = check_parent(commit, mainline);
- if (!(message = commit->buffer))
- die ("Cannot get commit message for %s",
- sha1_to_hex(commit->object.sha1));
-
if (parent && parse_commit(parent) < 0)
die("%s: cannot parse parent commit %s",
me, sha1_to_hex(parent->object.sha1));
+ if (action == CHERRY_PICK && ff_ok &&
+ parent && !hashcmp(parent->object.sha1, head) &&
+ !edit && !no_commit && !no_replay && !signoff) {
+ char *hex = sha1_to_hex(commit->object.sha1);
+ int res = reset(hex, prefix, HARD, 0, 0, 0, NULL);
+ if (!res)
+ fprintf(stderr, "Fast-forward to %s\n", hex);
+ return res;
+ }
+
+ if (!(message = commit->buffer))
+ die ("Cannot get commit message for %s",
+ sha1_to_hex(commit->object.sha1));
+
+ index_fd = hold_locked_index(&index_lock, 1);
+
/*
* "commit" is an existing commit. We would want to apply
* the difference it introduces since its first parent "prev"
@@ -457,12 +469,12 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
edit = 1;
no_replay = 1;
action = REVERT;
- return revert_or_cherry_pick(argc, argv);
+ return revert_or_cherry_pick(argc, argv, prefix);
}
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
{
no_replay = 0;
action = CHERRY_PICK;
- return revert_or_cherry_pick(argc, argv);
+ return revert_or_cherry_pick(argc, argv, prefix);
}
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 6/9] cherry-pick: add tests for new --ff option
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
` (4 preceding siblings ...)
2010-03-03 20:11 ` [PATCH v3 5/9] revert: add --ff option to allow fast forward when cherry-picking Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 7/9] Documentation: describe new cherry-pick " Christian Couder
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
t/t3506-cherry-pick-ff.sh | 98 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 98 insertions(+), 0 deletions(-)
create mode 100755 t/t3506-cherry-pick-ff.sh
diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
new file mode 100755
index 0000000..e17ae71
--- /dev/null
+++ b/t/t3506-cherry-pick-ff.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+test_description='test cherry-picking with --ff option'
+
+. ./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 &&
+ echo second >> file1 &&
+ git add file1 &&
+ test_tick &&
+ git commit -m "second" &&
+ git tag second
+'
+
+test_expect_success 'cherry-pick using --ff fast forwards' '
+ git checkout master &&
+ git reset --hard first &&
+ test_tick &&
+ git cherry-pick --ff second &&
+ test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify second)"
+'
+
+test_expect_success 'cherry-pick not using --ff does not fast forwards' '
+ git checkout master &&
+ git reset --hard first &&
+ test_tick &&
+ git cherry-pick second &&
+ test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify second)"
+'
+
+#
+# We setup the following graph:
+#
+# B---C
+# / /
+# first---A
+#
+# (This has been taken from t3502-cherry-pick-merge.sh)
+#
+test_expect_success 'merge setup' '
+ git checkout master &&
+ git reset --hard first &&
+ echo new line >A &&
+ git add A &&
+ test_tick &&
+ git commit -m "add line to A" A &&
+ git tag A &&
+ git checkout -b side first &&
+ echo new line >B &&
+ git add B &&
+ test_tick &&
+ git commit -m "add line to B" B &&
+ git tag B &&
+ git checkout master &&
+ git merge side &&
+ git tag C &&
+ git checkout -b new A
+'
+
+test_expect_success 'cherry-pick a non-merge with --ff and -m should fail' '
+ git reset --hard A -- &&
+ test_must_fail git cherry-pick --ff -m 1 B &&
+ git diff --exit-code A --
+'
+
+test_expect_success 'cherry pick a merge with --ff but without -m should fail' '
+ git reset --hard A -- &&
+ test_must_fail git cherry-pick --ff C &&
+ git diff --exit-code A --
+'
+
+test_expect_success 'cherry pick with --ff a merge (1)' '
+ git reset --hard A -- &&
+ git cherry-pick --ff -m 1 C &&
+ git diff --exit-code C &&
+ test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify C)"
+'
+
+test_expect_success 'cherry pick with --ff a merge (2)' '
+ git reset --hard B -- &&
+ git cherry-pick --ff -m 2 C &&
+ git diff --exit-code C &&
+ test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify C)"
+'
+
+test_expect_success 'cherry pick a merge relative to nonexistent parent with --ff should fail' '
+ git reset --hard B -- &&
+ test_must_fail git cherry-pick --ff -m 3 C
+'
+
+test_done
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 7/9] Documentation: describe new cherry-pick --ff option
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
` (5 preceding siblings ...)
2010-03-03 20:11 ` [PATCH v3 6/9] cherry-pick: add tests for new --ff option Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 8/9] cherry-pick: add a no-op --no-ff option to future proof scripts Christian Couder
2010-03-03 20:11 ` [PATCH v3 9/9] rebase -i: use new --ff cherry-pick option Christian Couder
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Documentation/git-cherry-pick.txt | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 78f4714..d71607a 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit
SYNOPSIS
--------
-'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] <commit>
+'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>
DESCRIPTION
-----------
@@ -70,6 +70,10 @@ effect to your index in a row.
--signoff::
Add Signed-off-by line at the end of the commit message.
+--ff::
+ If the current HEAD is the same as the parent of the
+ cherry-pick'ed commit, then a fast forward to this commit will
+ be performed.
Author
------
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 8/9] cherry-pick: add a no-op --no-ff option to future proof scripts
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
` (6 preceding siblings ...)
2010-03-03 20:11 ` [PATCH v3 7/9] Documentation: describe new cherry-pick " Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
2010-03-03 20:11 ` [PATCH v3 9/9] rebase -i: use new --ff cherry-pick option Christian Couder
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
A --ff option to allow "git cherry-pick" to fast forward if
possible was added in a previous patch, and this behavior may
become the default one in the future.
So to future proof scripts that may rely on the current behavior
it is safer to add a --no-ff option to make sure that the current
behavior will be used.
Requested-by: Paolo Bonzini <bonzini@gnu.org>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Documentation/git-cherry-pick.txt | 6 +++++-
builtin/revert.c | 5 +++--
t/t3506-cherry-pick-ff.sh | 8 ++++++++
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index d71607a..dfc8243 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit
SYNOPSIS
--------
-'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>
+'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--[no-]ff] <commit>
DESCRIPTION
-----------
@@ -75,6 +75,10 @@ effect to your index in a row.
cherry-pick'ed commit, then a fast forward to this commit will
be performed.
+--no-ff::
+ Does nothing right now, but in the future this may disallow
+ fast forward if it becomes the default behavior.
+
Author
------
Written by Junio C Hamano <gitster@pobox.com>
diff --git a/builtin/revert.c b/builtin/revert.c
index 4799073..111853b 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -36,7 +36,7 @@ static const char * const cherry_pick_usage[] = {
NULL
};
-static int edit, no_replay, no_commit, mainline, signoff, ff_ok;
+static int edit, no_replay, no_commit, mainline, signoff, ff_ok, no_ff;
static enum { REVERT, CHERRY_PICK } action;
static struct commit *commit;
static const char *commit_name;
@@ -59,6 +59,7 @@ static void parse_args(int argc, const char **argv)
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
OPT_BOOLEAN(0, "ff", &ff_ok, "allow fast forward"),
+ OPT_BOOLEAN(0, "no-ff", &no_ff, "disallow fast forward"),
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
OPT_END(),
@@ -326,7 +327,7 @@ static int revert_or_cherry_pick(int argc, const char **argv, const char *prefix
die("%s: cannot parse parent commit %s",
me, sha1_to_hex(parent->object.sha1));
- if (action == CHERRY_PICK && ff_ok &&
+ if (action == CHERRY_PICK && ff_ok && !no_ff &&
parent && !hashcmp(parent->object.sha1, head) &&
!edit && !no_commit && !no_replay && !signoff) {
char *hex = sha1_to_hex(commit->object.sha1);
diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
index e17ae71..2d7e532 100755
--- a/t/t3506-cherry-pick-ff.sh
+++ b/t/t3506-cherry-pick-ff.sh
@@ -35,6 +35,14 @@ test_expect_success 'cherry-pick not using --ff does not fast forwards' '
test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify second)"
'
+test_expect_success 'cherry-pick using --no-ff does not fast forwards' '
+ git checkout master &&
+ git reset --hard first &&
+ test_tick &&
+ git cherry-pick --no-ff second &&
+ test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify second)"
+'
+
#
# We setup the following graph:
#
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 9/9] rebase -i: use new --ff cherry-pick option
2010-03-03 20:11 [PATCH v3 0/9] add --ff option to cherry-pick Christian Couder
` (7 preceding siblings ...)
2010-03-03 20:11 ` [PATCH v3 8/9] cherry-pick: add a no-op --no-ff option to future proof scripts Christian Couder
@ 2010-03-03 20:11 ` Christian Couder
8 siblings, 0 replies; 10+ messages in thread
From: Christian Couder @ 2010-03-03 20:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Johannes Schindelin, Stephan Beyer,
Daniel Barkalow, Paolo Bonzini, Stephen Boyd
This simplifies rebase -i a little bit.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
git-rebase--interactive.sh | 15 +++------------
1 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 415ae72..a57f043 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -230,8 +230,8 @@ do_with_author () {
}
pick_one () {
- no_ff=
- case "$1" in -n) sha1=$2; no_ff=t ;; *) sha1=$1 ;; esac
+ ff=--ff
+ case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac
output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
test -d "$REWRITTEN" &&
pick_one_preserving_merges "$@" && return
@@ -240,16 +240,7 @@ pick_one () {
output git cherry-pick "$@"
return
fi
- parent_sha1=$(git rev-parse --verify $sha1^) ||
- die "Could not get the parent of $sha1"
- current_sha1=$(git rev-parse --verify HEAD)
- if test -z "$no_ff" && test "$current_sha1" = "$parent_sha1"
- then
- output git reset --hard $sha1
- output warn Fast-forward to $(git rev-parse --short $sha1)
- else
- output git cherry-pick "$@"
- fi
+ output git cherry-pick $ff "$@"
}
pick_one_preserving_merges () {
--
1.7.0.315.gbc198
^ permalink raw reply related [flat|nested] 10+ messages in thread