git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 5/8] revert: allow cherry-picking more than one commit

From
Christian Couder <chriscool@tuxfamily.org>
Date
May 31, 2010, 19:42 UTC
Message-ID
<20100531194240.28729.9164.chriscool@tuxfamily.org>
In-Reply-To
<20100531193359.28729.55562.chriscool@tuxfamily.org>

This makes it possible to pass many commits or ranges of commits to "git cherry-pick" and to "git revert" to process many commits instead of just one.

In fact commits are now enumerated with an equivalent of
	git rev-list --no-walk "$@"
so all the following are now possible:
	git cherry-pick master~2..master
	git cherry-pick ^master~2 master
	git cherry-pick master^ master
The following should be possible but does not work:
	git cherry-pick -2 master

because "git rev-list --no-walk -2 master" only outputs one commit as "--no-walk" seems to take over "-2".

And there is currently no way to continue cherry-picking or reverting if there is a problem with one commit. It's also not possible to abort the whole process. Some future work should provide the --continue and --abort options to do just that.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 builtin/revert.c |   49 +++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/builtin/revert.c b/builtin/revert.c
index f0d78e5..b90955f 100644
--- a/builtin/revert.c
+++ b/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 enum { REVERT, CHERRY_PICK } action;
 static struct commit *commit;
-static const char *commit_name;
+static int commit_argc;
+static const char **commit_argv;
 static int allow_rerere_auto;
 
 static const char *me;
@@ -53,7 +54,6 @@ static void parse_args(int argc, const char **argv)
 {
 	const char * const * usage_str =
 		action == REVERT ?  revert_usage : cherry_pick_usage;
-	unsigned char sha1[20];
 	int noop;
 	struct option options[] = {
 		OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
@@ -78,15 +78,11 @@ static void parse_args(int argc, const char **argv)
 			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);
 
-	commit_name = argv[0];
-	if (get_sha1(commit_name, sha1))
-		die ("Cannot find '%s'", commit_name);
-	commit = lookup_commit_reference(sha1);
-	if (!commit)
-		exit(1);
+	commit_argv = argv;
 }
 
 struct commit_message {
@@ -520,8 +516,33 @@ static int do_pick_commit()
 	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");
+}
+
 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);
@@ -541,7 +562,15 @@ static int revert_or_cherry_pick(int argc, const char **argv)
 	if (read_cache() < 0)
 		die("git %s: failed to read the index", me);
 
-	return do_pick_commit();
+	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)
-- 
1.7.1.361.g42de.dirty
Previous: Jonathan NiederNext: Sverre Rabbelier
Message 11 of 30 in “implement cherry-picking many commits”
  1. 0/8 implement cherry-picking many commitsChristian Couder, May 31, 2010
  2. 1/8 revert: cleanup code for -x optionChristian Couder, May 31, 2010
  3. 2/8 revert: use run_command_v_opt() instead of execv_git_cmd()Christian Couder, May 31, 2010
  4. Jonathan NiederJun 1, 2010
  5. Christian CouderJun 1, 2010
  6. 3/8 revert: refactor code into a do_pick_commit() functionChristian Couder, May 31, 2010
  7. 4/8 revert: change help_msg() to take no argumentChristian Couder, May 31, 2010
  8. Jonathan NiederJun 1, 2010
  9. Jeff KingJun 1, 2010
  10. Jonathan NiederJun 1, 2010
  11. 5/8 revert: allow cherry-picking more than one commitChristian Couder, May 31, 2010
  12. Sverre RabbelierJun 1, 2010
  13. Jonathan NiederJun 1, 2010
  14. Junio C HamanoJun 2, 2010
  15. Christian CouderJun 3, 2010
  16. Jonathan NiederJun 1, 2010
  17. Christian CouderJun 2, 2010
  18. 6/8 revert: add tests to check cherry-picking many commitsChristian Couder, May 31, 2010
  19. 7/8 Documentation/cherry-pick: describe passing more than one commitChristian Couder, May 31, 2010
  20. Ramkumar RamachandraJun 1, 2010
  21. Christian CouderJun 2, 2010
  22. Jonathan NiederJun 1, 2010
  23. Ramkumar RamachandraJun 1, 2010
  24. Christian CouderJun 2, 2010
  25. Christian CouderJun 2, 2010
  26. Jonathan NiederJun 2, 2010
  27. Christian CouderJun 14, 2010
  28. 8/8 Documentation/revert: describe passing more than one commitChristian Couder, May 31, 2010
  29. Antriksh PanyJun 1, 2010
  30. Christian CouderJun 2, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.