git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/9] add --ff option to cherry-pick
@ 2010-03-03 20:11 Christian Couder
  2010-03-03 20:11 ` [PATCH v3 1/9] reset: refactor updating heads into a static function Christian Couder
                   ` (8 more replies)
  0 siblings, 9 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

The goal of this patch series is to make it possible for "git cherry-pick"
to fast forward instead of creating a new commit if the cherry picked commit
has the same parent as the one we are cherry-picking on.

The change since the previous series is that there is less refactoring
of builtin/revert.c before introducing the --ff option, so less code churn.
This also means that this series should be easier to merge.

Christian Couder (9):
  reset: refactor updating heads into a static function
  reset: refactor reseting in its own function
  reset: make reset function non static and declare it in "reset.h"
  revert: refactor checking parent in a check_parent() function
  revert: add --ff option to allow fast forward when cherry-picking
  cherry-pick: add tests for new --ff option
  Documentation: describe new cherry-pick --ff option
  cherry-pick: add a no-op --no-ff option to future proof scripts
  rebase -i: use new --ff cherry-pick option

 Documentation/git-cherry-pick.txt |   10 ++-
 builtin/reset.c                   |  178 ++++++++++++++++++++-----------------
 builtin/revert.c                  |   91 ++++++++++++-------
 git-rebase--interactive.sh        |   15 +---
 reset.h                           |   10 ++
 t/t3506-cherry-pick-ff.sh         |  106 ++++++++++++++++++++++
 6 files changed, 282 insertions(+), 128 deletions(-)
 create mode 100644 reset.h
 create mode 100755 t/t3506-cherry-pick-ff.sh

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [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

end of thread, other threads:[~2010-03-04  2:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH v3 3/9] reset: make reset function non static and declare it in "reset.h" Christian Couder
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 ` [PATCH v3 5/9] revert: add --ff option to allow fast forward when cherry-picking Christian Couder
2010-03-03 20:11 ` [PATCH v3 6/9] cherry-pick: add tests for new --ff option Christian Couder
2010-03-03 20:11 ` [PATCH v3 7/9] Documentation: describe new cherry-pick " 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).