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

[RFC/PATCH 2/2] Teach commit to handle CHERRY_HEAD automatically

From
Jay Soffian <jaysoffian@gmail.com>
Date
Feb 15, 2011, 21:23 UTC
Message-ID
<1297805034-3512-3-git-send-email-jaysoffian@gmail.com>
In-Reply-To
<1297805034-3512-1-git-send-email-jaysoffian@gmail.com>

Now that cherry-pick records the original commit id in CHERRY_HEAD following a conflict, we can teach commit to handle it automatically.

The primary difference between this and 'commit -c CHERRY_HEAD' (besides saving the user some typing) is that we take only the authorship from CHERRY_HEAD, while taking the commit message from MERGE_MSG (which contains the list of conflicts as well as cherry-pick -x's annotation, if -x was used).

--reset-author can be used to reset authorship. --- There are several subtle interactions between the sundry commit options that make my head hurt. I did my best to integrate what happens when there is a CHERRY_HEAD, but I'm really not sure how CHERRY_HEAD ought to interact with things like --squash and --fixup, or the message specifying options.

For example, it should probably be an error to use --squash/--fixup when there's a CHERRY_HEAD, but then again, it should probably be an error to use those options when there's a MERGE_HEAD (but it's not).

OTOH, it seems valid to specify a commit message manually, so I allow that.
 Documentation/git-commit.txt           |    7 +++--
 builtin/commit.c                       |   35 ++++++++++++++++++++++++++-----
 builtin/revert.c                       |    5 +--
 contrib/completion/git-completion.bash |    2 +
 4 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index b586c0f..fd6a1f7 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -84,9 +84,10 @@ OPTIONS
 	linkgit:git-rebase[1] for details.
 
 --reset-author::
-	When used with -C/-c/--amend options, declare that the
-	authorship of the resulting commit now belongs of the committer.
-	This also renews the author timestamp.
+	When used with -C/-c/--amend options, or when committing after a
+	a conflicting cherry-pick, declare that the authorship of the
+	resulting commit now belongs of the committer. This also renews
+	the author timestamp.
 
 --short::
 	When doing a dry-run, give the output in the short-format. See
diff --git a/builtin/commit.c b/builtin/commit.c
index 8850621..2f0a8fc 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -70,7 +70,7 @@ static const char *logfile, *force_author;
 static const char *template_file;
 static char *edit_message, *use_message;
 static char *fixup_message, *squash_message;
-static int all, edit_flag, also, interactive, only, amend, signoff;
+static int all, edit_flag, also, interactive, only, amend, signoff, cherry_pick;
 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
 static int no_post_rewrite, allow_empty_message;
 static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
@@ -609,7 +609,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 			die_errno("could not read log file '%s'",
 				  logfile);
 		hook_arg1 = "message";
-	} else if (use_message) {
+	} else if (use_message && !cherry_pick) {
 		buffer = strstr(use_message_buffer, "\n\n");
 		if (!buffer || buffer[2] == '\0')
 			die("commit has empty message");
@@ -704,6 +704,15 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 				"#\n",
 				git_path("MERGE_HEAD"));
 
+		if (cherry_pick)
+			fprintf(fp,
+				"#\n"
+				"# It looks like you may be committing a cherry-pick.\n"
+				"# If this is not correct, please remove the file\n"
+				"#	%s\n"
+				"# and try again.\n"
+				"#\n",
+				git_path("CHERRY_HEAD"));
 		fprintf(fp,
 			"\n"
 			"# Please enter the commit message for your changes.");
@@ -898,6 +907,7 @@ static void handle_untracked_files_arg(struct wt_status *s)
 		die("Invalid untracked files mode '%s'", untracked_files_arg);
 }
 
+
 static int parse_and_validate_options(int argc, const char *argv[],
 				      const char * const usage[],
 				      const char *prefix,
@@ -929,6 +939,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
 		die("You have nothing to amend.");
 	if (amend && in_merge)
 		die("You are in the middle of a merge -- cannot amend.");
+	if (amend && cherry_pick)
+		die("You are in the middle of a cherry-pick -- cannot amend.");
 	if (fixup_message && squash_message)
 		die("Options --squash and --fixup cannot be used together");
 	if (use_message)
@@ -943,11 +955,19 @@ static int parse_and_validate_options(int argc, const char *argv[],
 		die("Only one of -c/-C/-F/--fixup can be used.");
 	if (message.len && f > 0)
 		die("Option -m cannot be combined with -c/-C/-F/--fixup.");
+	if (cherry_pick) {
+		/* Let message-specifying options override CHERRY_HEAD */
+		if (f > 0 || message.len)
+			cherry_pick = 0;
+		else
+			/* used for authorship side-effect only */
+			use_message = "CHERRY_HEAD";
+	}
 	if (edit_message)
 		use_message = edit_message;
 	if (amend && !use_message && !fixup_message)
 		use_message = "HEAD";
-	if (!use_message && renew_authorship)
+	if (!use_message && !cherry_pick && renew_authorship)
 		die("--reset-author can be used only with -C, -c or --amend.");
 	if (use_message) {
 		const char *out_enc;
@@ -1118,6 +1138,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 	gitmodules_config();
 	git_config(git_status_config, &s);
 	in_merge = file_exists(git_path("MERGE_HEAD"));
+	cherry_pick = file_exists(git_path("CHERRY_HEAD"));
 	argc = parse_options(argc, argv, prefix,
 			     builtin_status_options,
 			     builtin_status_usage, 0);
@@ -1140,7 +1161,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 	}
 
 	s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
-	s.in_merge = in_merge;
+	s.in_merge = in_merge || cherry_pick;
 	s.ignore_submodule_arg = ignore_submodule_arg;
 	wt_status_collect(&s);
 
@@ -1303,7 +1324,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 	wt_status_prepare(&s);
 	git_config(git_commit_config, &s);
 	in_merge = file_exists(git_path("MERGE_HEAD"));
-	s.in_merge = in_merge;
+	cherry_pick = file_exists(git_path("CHERRY_HEAD"));
+	s.in_merge = in_merge || cherry_pick;
 
 	if (s.use_color == -1)
 		s.use_color = git_use_color_default;
@@ -1369,7 +1391,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 			parents = reduce_heads(parents);
 	} else {
 		if (!reflog_msg)
-			reflog_msg = "commit";
+			reflog_msg = cherry_pick ? "commit (cherry-pick)"
+						 : "commit";
 		pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
 	}
 
diff --git a/builtin/revert.c b/builtin/revert.c
index c373e69..678fc8e 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -284,11 +284,10 @@ static void print_advice(void)
 
 	advise("after resolving the conflicts, mark the corrected paths");
 	advise("with 'git add <paths>' or 'git rm <paths>'");
+	advice("and commit the result with 'git commit'");
 
-	if (action == CHERRY_PICK) {
+	if (action == CHERRY_PICK)
 		write_cherry_head();
-		advise("and commit the result with 'git commit -c CHERRY_HEAD'");
-	}
 }
 
 static void write_message(struct strbuf *msgbuf, const char *filename)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 893b771..1d446cf 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -246,6 +246,8 @@ __git_ps1 ()
 				fi
 			elif [ -f "$g/MERGE_HEAD" ]; then
 				r="|MERGING"
+			elif [ -f "$g/CHERRY_HEAD" ]; then
+				r="|CHERRY-PICKING"
 			elif [ -f "$g/BISECT_LOG" ]; then
 				r="|BISECTING"
 			fi
-- 
1.7.4.5.g9affb
Previous: Jonathan NiederNext: Jay Soffian
Message 11 of 27 in “CHERRY_HEAD”
  1. 0/2 CHERRY_HEADJay Soffian, Feb 15, 2011
  2. 1/2 Introduce CHERRY_HEADJay Soffian, Feb 15, 2011
  3. Junio C HamanoFeb 15, 2011
  4. Jonathan NiederFeb 15, 2011
  5. Junio C HamanoFeb 15, 2011
  6. Bert WesargFeb 15, 2011
  7. Junio C HamanoFeb 15, 2011
  8. Bert WesargFeb 15, 2011
  9. Jay SoffianFeb 15, 2011
  10. Jonathan NiederFeb 15, 2011
  11. 2/2 Teach commit to handle CHERRY_HEAD automaticallyJay Soffian, Feb 15, 2011
  12. Jay SoffianFeb 15, 2011
  13. Junio C HamanoFeb 15, 2011
  14. Jonathan NiederFeb 15, 2011
  15. Jay SoffianFeb 15, 2011
  16. Jonathan NiederFeb 15, 2011
  17. Jay SoffianFeb 16, 2011
  18. Jonathan NiederFeb 16, 2011
  19. Documentation: clarify interaction of --reset-author with --authorJonathan Nieder, Feb 16, 2011
  20. Junio C HamanoFeb 16, 2011
  21. Ævar Arnfjörð BjarmasonFeb 15, 2011
  22. Junio C HamanoFeb 15, 2011
  23. Jay SoffianFeb 15, 2011
  24. Ævar Arnfjörð BjarmasonFeb 15, 2011
  25. Jay SoffianFeb 15, 2011
  26. Miles BaderFeb 16, 2011
  27. Christian CouderFeb 17, 2011

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.