Re: [PATCH] Teach commit about CHERRY_PICK_HEAD

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jay Soffian wrote:

> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -54,9 +54,16 @@ static const char empty_amend_advice[] =
>  "it empty. You can repeat your command with --allow-empty, or you can\n"
>  "remove the commit entirely with \"git reset HEAD^\".\n";
>  
> +static const char empty_cherry_pick_advice[] =
> +"The most recent cherry-pick is empty. If you wish to commit it, use:\n"
> +"\n"
> +"    git commit --allow-empty\n"
> +"\n"
> +"Otherwise, please remove the file %s\n";

After scratching my head a little, this seems to mean

	After conflict resolution, your last cherry-pick does not
	introduce any changes. To commit it as an empty commit, use:\n
	\n
	    git commit --allow-empty\n
	\n
	Alternatively, you can cancel the cherry-pick by removing\n
	the file %s\n

It suspect it might be more intuitive to say

	Alternatively, you can cancel the cherry-pick by running\n
	"git reset".\n

which works because the index is known to be clean at that point.

> +/*
> + * The _message variables are commit names from which to take
> + * the commit message and/or authorship.
> + */

Makes sense, thanks.  I'll think more about an intuitive and
consistent name for these and hopefully send a patch for it later as a
separate topic.

> +       if (whence == FROM_CHERRY_PICK && !renew_authorship) {
> +               author_message = "CHERRY_PICK_HEAD";
> +               author_message_buffer = read_commit_message(author_message);

I mentioned in a side thread that script authors might be happier if
their carefully prepared GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL do not
get overridden in this case, but I was wrong[*].  Might make sense
to add a test for that:

	GIT_AUTHOR_NAME="Someone else" &&
	GIT_AUTHOR_EMAIL=someone@xxxxxxxxxxxxxxxx &&
	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
	git cherry-pick something &&

	git diff-tree -s --format="%an <%ae>" >actual &&
	test_cmp expect actual

(This is just a side note; the patch is good.)

In the $GIT_CHERRY_PICK_HELP set case, won't the CHERRY_PICK_HEAD
behavior be harmless?  rebase --interactive --continue wants to set
GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL but that is only in order to copy
the author identity from the original commit.

> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -60,7 +60,7 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
>  	color_fprintf_ln(s->fp, c, "# Unmerged paths:");
>  	if (!advice_status_hints)
>  		return;
> -	if (s->in_merge)
> +	if (s->whence != FROM_COMMIT)
>  		;
>  	else if (!s->is_initial)
>  		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference);

The advice 'use "git reset HEAD -- <file>..." to unstage' makes
perfect sense to me in the cherry-pick case, no?  The operator is
replaying an existing commit, and tweaking the result amounts to
pretending she made the change herself and tweaking that.

> @@ -77,7 +77,7 @@ static void wt_status_print_cached_header(struct wt_status *s)
>  	color_fprintf_ln(s->fp, c, "# Changes to be committed:");
>  	if (!advice_status_hints)
>  		return;
> -	if (s->in_merge)
> +	if (s->whence != FROM_COMMIT)
>  		; /* NEEDSWORK: use "git reset --unresolve"??? */

Likewise.

> --- a/wt-status.h
> +++ b/wt-status.h
> @@ -24,6 +24,13 @@ enum untracked_status_type {
>  	SHOW_ALL_UNTRACKED_FILES
>  };
>  
> +/* from where does this commit originate */
> +enum commit_whence {
> +	FROM_COMMIT,     /* normal */
> +	FROM_MERGE,      /* commit came from merge */
> +	FROM_CHERRY_PICK /* commit came from cherry-pick */
> +};

I think these comments are not in a place that will help a person
understand the code, but I don't have the energy to go back and forth
on it.

Everything not mentioned above except the --no-commit case mentioned
by Junio looks good to me, though I haven't tested.

Thanks for your thoughtfulness.
Jonathan

[*]
-- 8< --
Subject: [BAD IDEA] commit: let GIT_AUTHOR_NAME/EMAIL take effect when commiting a cherry-pick

commit -c/-C/--amend to take the commit message and author from
another message has always overridden the GIT_AUTHOR_NAME and
GIT_AUTHOR_EMAIL variables.  Letting the command line override the
environment in this way is generally convenient and more intuitive if
a person has forgotten what is in the environment:

	GIT_AUTHOR_NAME=me
	GIT_AUTHOR_EMAIL=email@xxxxxxxxxxx
	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL

	...
	git commit;	# using identity from environment
	...
	git commit;	# another commit as me
	...
	# commit by someone else
	git commit --author='Someone Else <other@xxxxxxxxxxx>'
	...
	# commit by someone else
	git commit -c someone-elses-commit

The new CHERRY_PICK_HEAD feature inherits the same semantics.
Uncareful scripts that want to commit with a different author name and
email when taking over after a failed cherry-pick use authorship from
the cherry-picked commit instead of the environment:

	! git cherry-pick complicated;	# failed cherry-pick
	... resolve the conflict ...
	git commit

While that could theoretically break some scripts, it's worth it for
consistency, the intuitiveness-when-user-forgets-environment issue
mentioned above, and because cherry-pick itself, which internally
does something like

	git cherry-pick --no-commit $1;	# simple cherry-pick
	git commit

has always ignored the GIT_AUTHOR_NAME/EMAIL environment settings.

The patch below makes commit with CHERRY_PICK_HEAD respect
GIT_AUTHOR_NAME/EMAIL anyway, to demonstrate how broken that is.  It
breaks tests t3404 and t3506.

Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx>
---
 builtin/commit.c |   59 ++++++++++++++++++++++++++++++++---------------------
 1 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 35eb024..f398910 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -80,6 +80,7 @@ static const char *template_file;
  * the commit message and/or authorship.
  */
 static const char *author_message, *author_message_buffer;
+static int author_message_overrides_environ;
 static char *edit_message, *use_message;
 static char *fixup_message, *squash_message;
 static int all, edit_flag, also, interactive, only, amend, signoff;
@@ -504,6 +505,38 @@ static int is_a_merge(const unsigned char *sha1)
 
 static const char sign_off_header[] = "Signed-off-by: ";
 
+static void reuse_author_info(char **name, char **email, char **date)
+{
+	const char *a, *lb, *rb, *eol;
+
+	if (author_message_overrides_environ)
+		*name = *email = *date = NULL;
+
+	a = strstr(author_message_buffer, "\nauthor ");
+	if (!a)
+		die("invalid commit: %s", author_message);
+
+	lb = strchrnul(a + strlen("\nauthor "), '<');
+	rb = strchrnul(lb, '>');
+	eol = strchrnul(rb, '\n');
+	if (!*lb || !*rb || !*eol)
+		die("invalid commit: %s", author_message);
+
+	if (!*name) {
+		if (lb == a + strlen("\nauthor "))
+			/* \nauthor <foo@xxxxxxxxxxx> */
+			*name = xcalloc(1, 1);
+		else
+			*name = xmemdupz(a + strlen("\nauthor "),
+					 (lb - strlen(" ") -
+					  (a + strlen("\nauthor "))));
+	}
+	if (!*email)
+		*email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
+	if (!*date)
+		*date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
+}
+
 static void determine_author_info(struct strbuf *author_ident)
 {
 	char *name, *email, *date;
@@ -512,29 +545,8 @@ static void determine_author_info(struct strbuf *author_ident)
 	email = getenv("GIT_AUTHOR_EMAIL");
 	date = getenv("GIT_AUTHOR_DATE");
 
-	if (author_message) {
-		const char *a, *lb, *rb, *eol;
-
-		a = strstr(author_message_buffer, "\nauthor ");
-		if (!a)
-			die("invalid commit: %s", author_message);
-
-		lb = strchrnul(a + strlen("\nauthor "), '<');
-		rb = strchrnul(lb, '>');
-		eol = strchrnul(rb, '\n');
-		if (!*lb || !*rb || !*eol)
-			die("invalid commit: %s", author_message);
-
-		if (lb == a + strlen("\nauthor "))
-			/* \nauthor <foo@xxxxxxxxxxx> */
-			name = xcalloc(1, 1);
-		else
-			name = xmemdupz(a + strlen("\nauthor "),
-					(lb - strlen(" ") -
-					 (a + strlen("\nauthor "))));
-		email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
-		date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
-	}
+	if (author_message)
+		reuse_author_info(&name, &email, &date);
 
 	if (force_author) {
 		const char *lb = strstr(force_author, " <");
@@ -1034,6 +1046,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 			author_message = use_message;
 			author_message_buffer = use_message_buffer;
 		}
+		author_message_overrides_environ = 1;
 	}
 	if (whence == FROM_CHERRY_PICK && !renew_authorship) {
 		author_message = "CHERRY_PICK_HEAD";
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]