Skip to contentSkip to conversation

CHERRY_PICK_HEAD

PATCH In review Jay Soffian 4 participants 18 messages Jun 15, 2016 Documentation

lore
Share & tools
lore
#0 lore raw

cover CHERRY_PICK_HEAD

Re-roll of http://thread.gmane.org/gmane.comp.version-control.git/166878

If not ready for inclusion, hopefully very close.

Jay Soffian (2):
Introduce CHERRY_PICK_HEAD
Teach commit about CHERRY_PICK_HEAD

 Documentation/git-cherry-pick.txt      |   19 +++++
 Documentation/git-commit.txt           |    7 +-
 Documentation/revisions.txt            |    5 +-
 branch.c                               |    1 +
 builtin/commit.c                       |  136 ++++++++++++++++++++++----------
 builtin/merge.c                        |    7 ++
 builtin/revert.c                       |   68 ++++------------
 contrib/completion/git-completion.bash |    2 +
 t/t3507-cherry-pick-conflict.sh        |   22 +++++-
 t/t7509-commit.sh                      |   29 +++++++
 wt-status.c                            |    4 +-
 wt-status.h                            |    8 ++-
 12 files changed, 204 insertions(+), 104 deletions(-)
Signature · 1 line
1.7.4.1.28.gd46b3
#1 lore raw

PATCH 1/2 Introduce CHERRY_PICK_HEAD

When a cherry-pick conflicts git advises to use:

 $ git commit -c <original commit id>

to preserve the original commit message and authorship. Instead, let's record the original commit id in CHERRY_PICK_HEAD and advise to use:

  $ git commit -c CHERRY_PICK_HEAD

In the next commit, we teach git to handle the '-c CHERRY_PICK_HEAD' part. Note that wWe record CHERRY_PICK_HEAD even in the case where there are no conflicts so that we may use it to communicate authorship to commit; this will then allow us to remove set_author_ident_env from revert.c.

---
 Documentation/git-cherry-pick.txt |   19 +++++++++++++++++++
 Documentation/revisions.txt       |    5 ++++-
 branch.c                          |    1 +
 builtin/commit.c                  |    1 +
 builtin/merge.c                   |    7 +++++++
 builtin/revert.c                  |   20 ++++++++++++++++++--
 t/t3507-cherry-pick-conflict.sh   |   22 +++++++++++++++++++++-
 7 files changed, 71 insertions(+), 4 deletions(-)
Documentation/git-cherry-pick.txt +19 -0
index 749d68a..5d85daa 100644
@@ -16,6 +16,25 @@ Given one or more existing commits, apply the change each one
 introduces, recording a new commit for each.  This requires your
 working tree to be clean (no modifications from the HEAD commit).
 
+When it is not obvious how to apply a change, the following
+happens:
+
+1. The current branch and `HEAD` pointer stay at the last commit
+   successfully made.
+2. The `CHERRY_PICK_HEAD` ref is set to point at the commit that
+   introduced the change that is difficult to apply.
+3. Paths in which the change applied cleanly are updated both
+   in the index file and in your working tree.
+4. For conflicting paths, the index file records up to three
+   versions, as described in the "TRUE MERGE" section of
+   linkgit:git-merge[1].  The working tree files will include
+   a description of the conflict bracketed by the usual
+   conflict markers `<<<<<<<` and `>>>>>>>`.
+5. No other modifications are made.
+
+See linkgit:git-merge[1] for some hints on resolving such
+conflicts.
+
 OPTIONS
 -------
 <commit>...::
Documentation/revisions.txt +4 -1
index 9e92734..04fceee 100644
@@ -25,7 +25,8 @@ blobs contained in a commit.
   first match in the following rules:
 
   . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
-    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);
+    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD`, `MERGE_HEAD`
+    and `CHERRY_PICK_HEAD`);
 
   . otherwise, `refs/<name>` if exists;
 
@@ -46,6 +47,8 @@ you can change the tip of the branch back to the state before you ran
 them easily.
 MERGE_HEAD records the commit(s) you are merging into your branch
 when you run 'git merge'.
+CHERRY_PICK_HEAD records the commit you are cherry-picking
+when you run 'git cherry-pick'.
 +
 Note that any of the `refs/*` cases above may come either from
 the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
branch.c +1 -0
index 93dc866..dc23e95 100644
@@ -217,6 +217,7 @@ void create_branch(const char *head,
 
 void remove_branch_state(void)
 {
+	unlink(git_path("CHERRY_PICK_HEAD"));
 	unlink(git_path("MERGE_HEAD"));
 	unlink(git_path("MERGE_RR"));
 	unlink(git_path("MERGE_MSG"));
builtin/commit.c +1 -0
index 03cff5a..0def540 100644
@@ -1424,6 +1424,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		die("cannot update HEAD ref");
 	}
 
+	unlink(git_path("CHERRY_PICK_HEAD"));
 	unlink(git_path("MERGE_HEAD"));
 	unlink(git_path("MERGE_MSG"));
 	unlink(git_path("MERGE_MODE"));
builtin/merge.c +7 -0
index 9403747..454dad2 100644
@@ -971,6 +971,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		else
 			die("You have not concluded your merge (MERGE_HEAD exists).");
 	}
+	if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
+		if (advice_resolve_conflict)
+			die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+			    "Please, commit your changes before you can merge.");
+		else
+			die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).");
+	}
 	resolve_undo_clear();
 
 	if (verbosity < 0)
builtin/revert.c +18 -2
index dc1b702..cced2e4 100644
@@ -248,6 +248,22 @@ static void set_author_ident_env(const char *message)
 			sha1_to_hex(commit->object.sha1));
 }
 
+static void write_cherry_pick_head(void)
+{
+	int fd;
+	struct strbuf buf = STRBUF_INIT;
+
+	strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
+
+	fd = open(git_path("CHERRY_PICK_HEAD"), O_WRONLY | O_CREAT, 0666);
+	if (fd < 0)
+		die_errno("Could not open '%s' for writing",
+			  git_path("CHERRY_PICK_HEAD"));
+	if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))
+		die_errno("Could not write to '%s'", git_path("CHERRY_PICK_HEAD"));
+	strbuf_release(&buf);
+}
+
 static void advise(const char *advice, ...)
 {
 	va_list params;
@@ -270,8 +286,7 @@ static void print_advice(void)
 	advise("with 'git add <paths>' or 'git rm <paths>'");
 
 	if (action == CHERRY_PICK)
-		advise("and commit the result with 'git commit -c %s'",
-		       find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+		advise("and commit the result with 'git commit -c CHERRY_PICK_HEAD'");
 }
 
 static void write_message(struct strbuf *msgbuf, const char *filename)
@@ -504,6 +519,7 @@ static int do_pick_commit(void)
 			strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));
 			strbuf_addstr(&msgbuf, ")\n");
 		}
+		write_cherry_pick_head();
 	}
 
 	if (!strategy || !strcmp(strategy, "recursive") || action == REVERT) {
t/t3507-cherry-pick-conflict.sh +21 -1
index 607bf25..fd569c8 100755
@@ -11,6 +11,12 @@ test_description='test cherry-pick and revert with conflicts
 
 . ./test-lib.sh
 
+test_cmp_rev () {
+	git rev-parse --verify "$1" >expect.rev &&
+	git rev-parse --verify "$2" >actual.rev &&
+	test_cmp expect.rev actual.rev
+}
+
 test_expect_success setup '
 
 	echo unrelated >unrelated &&
@@ -51,13 +57,27 @@ test_expect_success 'advice from failed cherry-pick' "
 	error: could not apply \$picked... picked
 	hint: after resolving the conflicts, mark the corrected paths
 	hint: with 'git add <paths>' or 'git rm <paths>'
-	hint: and commit the result with 'git commit -c \$picked'
+	hint: and commit the result with 'git commit -c CHERRY_PICK_HEAD'
 	EOF
 	test_must_fail git cherry-pick picked 2>actual &&
 
 	test_cmp expected actual
 "
 
+test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	test_must_fail git cherry-pick picked &&
+
+	test_cmp_rev picked CHERRY_PICK_HEAD
+'
+
 test_expect_success 'failed cherry-pick produces dirty index' '
 
 	git checkout -f initial^0 &&
Signature · 1 line
1.7.4.1.28.gd46b3
#2 lore raw

PATCH v2 1/1 Introduce CHERRY_PICK_HEAD

When a cherry-pick conflicts git advises to use:

 $ git commit -c <original commit id>

to preserve the original commit message and authorship. Instead, let's record the original commit id in CHERRY_PICK_HEAD and advise to use:

  $ git commit -c CHERRY_PICK_HEAD

In the next commit, we teach git to handle the '-c CHERRY_PICK_HEAD' part. Note that we record CHERRY_PICK_HEAD even in the case where there are no conflicts so that we may use it to communicate authorship to commit; this will then allow us to remove set_author_ident_env from revert.c.

---
Compared to the original patch, this removes CHERRY_PICK_HEAD when a conflict occurs during an interactive rebase. Also corrected a minor typo in the commit message. There were no changes to the next patch in the series, so I didn't resend it.

 Documentation/git-cherry-pick.txt |   19 +++++++++++++++++++
 Documentation/revisions.txt       |    5 ++++-
 branch.c                          |    1 +
 builtin/commit.c                  |    1 +
 builtin/merge.c                   |    7 +++++++
 builtin/revert.c                  |   25 +++++++++++++++++++++++--
 t/t3507-cherry-pick-conflict.sh   |   22 +++++++++++++++++++++-
 7 files changed, 76 insertions(+), 4 deletions(-)
Documentation/git-cherry-pick.txt +19 -0
index 749d68a..5d85daa 100644
@@ -16,6 +16,25 @@ Given one or more existing commits, apply the change each one
 introduces, recording a new commit for each.  This requires your
 working tree to be clean (no modifications from the HEAD commit).
 
+When it is not obvious how to apply a change, the following
+happens:
+
+1. The current branch and `HEAD` pointer stay at the last commit
+   successfully made.
+2. The `CHERRY_PICK_HEAD` ref is set to point at the commit that
+   introduced the change that is difficult to apply.
+3. Paths in which the change applied cleanly are updated both
+   in the index file and in your working tree.
+4. For conflicting paths, the index file records up to three
+   versions, as described in the "TRUE MERGE" section of
+   linkgit:git-merge[1].  The working tree files will include
+   a description of the conflict bracketed by the usual
+   conflict markers `<<<<<<<` and `>>>>>>>`.
+5. No other modifications are made.
+
+See linkgit:git-merge[1] for some hints on resolving such
+conflicts.
+
 OPTIONS
 -------
 <commit>...::
Documentation/revisions.txt +4 -1
index 9e92734..04fceee 100644
@@ -25,7 +25,8 @@ blobs contained in a commit.
   first match in the following rules:
 
   . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
-    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);
+    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD`, `MERGE_HEAD`
+    and `CHERRY_PICK_HEAD`);
 
   . otherwise, `refs/<name>` if exists;
 
@@ -46,6 +47,8 @@ you can change the tip of the branch back to the state before you ran
 them easily.
 MERGE_HEAD records the commit(s) you are merging into your branch
 when you run 'git merge'.
+CHERRY_PICK_HEAD records the commit you are cherry-picking
+when you run 'git cherry-pick'.
 +
 Note that any of the `refs/*` cases above may come either from
 the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
branch.c +1 -0
index 93dc866..dc23e95 100644
@@ -217,6 +217,7 @@ void create_branch(const char *head,
 
 void remove_branch_state(void)
 {
+	unlink(git_path("CHERRY_PICK_HEAD"));
 	unlink(git_path("MERGE_HEAD"));
 	unlink(git_path("MERGE_RR"));
 	unlink(git_path("MERGE_MSG"));
builtin/commit.c +1 -0
index 03cff5a..0def540 100644
@@ -1424,6 +1424,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		die("cannot update HEAD ref");
 	}
 
+	unlink(git_path("CHERRY_PICK_HEAD"));
 	unlink(git_path("MERGE_HEAD"));
 	unlink(git_path("MERGE_MSG"));
 	unlink(git_path("MERGE_MODE"));
builtin/merge.c +7 -0
index 9403747..454dad2 100644
@@ -971,6 +971,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		else
 			die("You have not concluded your merge (MERGE_HEAD exists).");
 	}
+	if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
+		if (advice_resolve_conflict)
+			die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+			    "Please, commit your changes before you can merge.");
+		else
+			die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).");
+	}
 	resolve_undo_clear();
 
 	if (verbosity < 0)
builtin/revert.c +23 -2
index dc1b702..88e3b2a 100644
@@ -248,6 +248,22 @@ static void set_author_ident_env(const char *message)
 			sha1_to_hex(commit->object.sha1));
 }
 
+static void write_cherry_pick_head(void)
+{
+	int fd;
+	struct strbuf buf = STRBUF_INIT;
+
+	strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
+
+	fd = open(git_path("CHERRY_PICK_HEAD"), O_WRONLY | O_CREAT, 0666);
+	if (fd < 0)
+		die_errno("Could not open '%s' for writing",
+			  git_path("CHERRY_PICK_HEAD"));
+	if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))
+		die_errno("Could not write to '%s'", git_path("CHERRY_PICK_HEAD"));
+	strbuf_release(&buf);
+}
+
 static void advise(const char *advice, ...)
 {
 	va_list params;
@@ -263,6 +279,11 @@ static void print_advice(void)
 
 	if (msg) {
 		fprintf(stderr, "%s\n", msg);
+		/*
+		 * rebase interactive takes care of the authorship
+		 * when the user invokes rebase --continue
+		 */
+		unlink(git_path("CHERRY_PICK_HEAD"));
 		return;
 	}
 
@@ -270,8 +291,7 @@ static void print_advice(void)
 	advise("with 'git add <paths>' or 'git rm <paths>'");
 
 	if (action == CHERRY_PICK)
-		advise("and commit the result with 'git commit -c %s'",
-		       find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+		advise("and commit the result with 'git commit -c CHERRY_PICK_HEAD'");
 }
 
 static void write_message(struct strbuf *msgbuf, const char *filename)
@@ -504,6 +524,7 @@ static int do_pick_commit(void)
 			strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));
 			strbuf_addstr(&msgbuf, ")\n");
 		}
+		write_cherry_pick_head();
 	}
 
 	if (!strategy || !strcmp(strategy, "recursive") || action == REVERT) {
t/t3507-cherry-pick-conflict.sh +21 -1
index 607bf25..fd569c8 100755
@@ -11,6 +11,12 @@ test_description='test cherry-pick and revert with conflicts
 
 . ./test-lib.sh
 
+test_cmp_rev () {
+	git rev-parse --verify "$1" >expect.rev &&
+	git rev-parse --verify "$2" >actual.rev &&
+	test_cmp expect.rev actual.rev
+}
+
 test_expect_success setup '
 
 	echo unrelated >unrelated &&
@@ -51,13 +57,27 @@ test_expect_success 'advice from failed cherry-pick' "
 	error: could not apply \$picked... picked
 	hint: after resolving the conflicts, mark the corrected paths
 	hint: with 'git add <paths>' or 'git rm <paths>'
-	hint: and commit the result with 'git commit -c \$picked'
+	hint: and commit the result with 'git commit -c CHERRY_PICK_HEAD'
 	EOF
 	test_must_fail git cherry-pick picked 2>actual &&
 
 	test_cmp expected actual
 "
 
+test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	test_must_fail git cherry-pick picked &&
+
+	test_cmp_rev picked CHERRY_PICK_HEAD
+'
+
 test_expect_success 'failed cherry-pick produces dirty index' '
 
 	git checkout -f initial^0 &&
Signature · 1 line
1.7.4.1.28.gb39462
Reviewed-by on v2 1/1
#3 lore raw

Re: [PATCH v2] Introduce CHERRY_PICK_HEAD

Quoted 7 lines · Jay Soffian

When a cherry-pick conflicts git advises to use:

 $ git commit -c <original commit id>

to preserve the original commit message and authorship. Instead, let's record the original commit id in CHERRY_PICK_HEAD and advise to use:

Quoted 7 lines
  $ git commit -c CHERRY_PICK_HEAD

In the next commit, we teach git to handle the '-c CHERRY_PICK_HEAD' part. Note that we record CHERRY_PICK_HEAD even in the case where there are no conflicts so that we may use it to communicate authorship to commit; this will then allow us to remove set_author_ident_env from revert.c.

This "In the next commit" phrasing is dangerous, since a person can build on top of your first commit at any time. :) I would say:

A later patch will teach "git commit" without -c to use CHERRY_PICK_HEAD to set the authorship automatically. Note that[...]

[...]

Review static void print_advice(void) · line 286

Quoted 10 lines

+++ b/builtin/revert.c

(quoted diff) +5 -0
@@ -263,6 +279,11 @@ static void print_advice(void)
 
 	if (msg) {
 		fprintf(stderr, "%s\n", msg);
+		/*
+		 * rebase interactive takes care of the authorship
+		 * when the user invokes rebase --continue
+		 */
+		unlink(git_path("CHERRY_PICK_HEAD"));

Nit: GIT_CHERRY_PICK_HELP is not just for rebase --interactive but for arbitrary porcelain that wants to take care of the commit itself (see v1.5.4-rc0~106^2~1, revert/cherry-pick: Allow overriding the help text by the calling Porcelain, 2007-11-28).

The conservative thing to do is indeed to remove CHERRY_PICK_HEAD in this case, I suppose. But I'd like to have the CHERRY_PICK_HEAD to get the --amend safety when rebasing. I can send a separate patch for it if you'd like.

Quoted 3 lines
t/t3507-cherry-pick-conflict.sh +0 -0
@@ -11,6 +11,12 @@ test_description='test cherry-pick and revert with conflicts

[...]

Quoted 1 line

+test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '

Some more tests. Yes, they are repetitive. A patch on top to factor out the setup into a function might help, but that feels out of scope here.

With whatever subset of the below looks good,

Thanks.

---
 t/t3507-cherry-pick-conflict.sh |  116 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 116 insertions(+), 0 deletions(-)
t/t3507-cherry-pick-conflict.sh +116 -0
index fd569c8..ea52720 100755
@@ -78,6 +78,122 @@ test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
 	test_cmp_rev picked CHERRY_PICK_HEAD
 '
 
+test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	git cherry-pick base &&
+
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
+test_expect_success 'cherry-pick --no-commit sets CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	git cherry-pick --no-commit base &&
+
+	test_cmp_rev base CHERRY_PICK_HEAD
+'
+
+test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	(
+		GIT_CHERRY_PICK_HELP="and then do something else" &&
+		export GIT_CHERRY_PICK_HELP &&
+		test_must_fail git cherry-pick picked
+	) &&
+
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
+test_expect_success 'git reset clears CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	test_must_fail git cherry-pick picked &&
+	git reset &&
+
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
+test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	test_must_fail git cherry-pick picked &&
+	test_must_fail git commit &&
+
+	test_cmp_rev picked CHERRY_PICK_HEAD
+'
+
+test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	test_must_fail git cherry-pick picked &&
+	echo resolved >foo &&
+	git add foo &&
+	git update-index --refresh -q &&
+	test_must_fail git diff-index --exit-code HEAD &&
+	(
+		GIT_EDITOR=false &&
+		export GIT_EDITOR &&
+		test_must_fail git commit
+	) &&
+
+	test_cmp_rev picked CHERRY_PICK_HEAD
+'
+
+test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '
+
+	git checkout -f initial^0 &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x &&
+
+	git update-index --refresh &&
+	git diff-index --exit-code HEAD &&
+
+	test_must_fail git cherry-pick picked &&
+	echo resolved >foo &&
+	git add foo &&
+	git commit &&
+
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
 test_expect_success 'failed cherry-pick produces dirty index' '
 
 	git checkout -f initial^0 &&
Signature · 1 line
1.7.4.1
#4 lore raw

Re: [PATCH v2] Introduce CHERRY_PICK_HEAD

Quoted 4 lines · Jonathan Nieder

Nit: GIT_CHERRY_PICK_HELP is not just for rebase --interactive but for arbitrary porcelain that wants to take care of the commit itself (see v1.5.4-rc0~106^2~1, revert/cherry-pick: Allow overriding the help text by the calling Porcelain, 2007-11-28).

What is the arbitrary porcelain you have in mind? :-)

Quoted 4 lines

The conservative thing to do is indeed to remove CHERRY_PICK_HEAD in this case, I suppose.  But I'd like to have the CHERRY_PICK_HEAD to get the --amend safety when rebasing.  I can send a separate patch for it if you'd like.

Please do, since I'm not really sure what you have in mind. If CHERRY_PICK_HEAD is left-behind, it interferes with the eventually commit done by rebase --continue. I suppose we could give commit.c some additional logic to detect when it's being called by rebase (setting whence = FROM_REBASE?).

In the mean time, I'll re-roll with your additional tests and Junio's prior feedback.

Thanks,

j.

#5 lore raw

Re: [PATCH v2] Introduce CHERRY_PICK_HEAD

Quoted 8 lines · Jay Soffian
Quoted 4 lines · Jonathan Nieder

Nit: GIT_CHERRY_PICK_HELP is not just for rebase --interactive but for arbitrary porcelain that wants to take care of the commit itself (see v1.5.4-rc0~106^2~1, revert/cherry-pick: Allow overriding the help text by the calling Porcelain, 2007-11-28).

What is the arbitrary porcelain you have in mind? :-)

git sequencer, for example. Or any out-of-tree tool that is using cherry-pick to move around commits and wants to know where they end up.

Quoted 8 lines
Quoted 4 lines

The conservative thing to do is indeed to remove CHERRY_PICK_HEAD in this case, I suppose.  But I'd like to have the CHERRY_PICK_HEAD to get the --amend safety when rebasing.  I can send a separate patch for it if you'd like.

Please do, since I'm not really sure what you have in mind. If CHERRY_PICK_HEAD is left-behind, it interferes with the eventually commit done by rebase --continue.

Wait, does this mean that -c/-C/--amend/CHERRY_PICK_HEAD overrides GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE?

*checks*

Yes, it does. The behavior is carried over from v0.99~185 (git-commit-script: get commit message from an existing one, 2005-06-25), but imho it is wrong.

Does this seem worth fixing?
Jonathan

#6 lore raw

Re: [PATCH v2] Introduce CHERRY_PICK_HEAD

Quoted 8 lines · Jonathan Nieder

Wait, does this mean that -c/-C/--amend/CHERRY_PICK_HEAD overrides GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE?

*checks*

Yes, it does. The behavior is carried over from v0.99~185 (git-commit-script: get commit message from an existing one, 2005-06-25), but imho it is wrong.

Hmph, -c/-C/--amend is like giving the identity with --author from the command line so overriding the values from the environment variables sounds like the right thing to do.

Where am I confused?

#7 lore raw

Re: [PATCH v2] Introduce CHERRY_PICK_HEAD

Quoted 4 lines · Junio C Hamano
Quoted 2 lines · Jonathan Nieder

Wait, does this mean that -c/-C/--amend/CHERRY_PICK_HEAD overrides GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE?

[...]

Quoted 3 lines

Hmph, -c/-C/--amend is like giving the identity with --author from the command line so overriding the values from the environment variables sounds like the right thing to do.

Good point. There are two principles at work here:

- options with more specific effect override more general ones
- options on the command line override the environment

On second thought, the latter does seem more relevant (though it need not apply to CHERRY_PICK_HEAD).

Thanks for a sanity check.
Jonathan

#8 lore raw

Re: [PATCH v2] Introduce CHERRY_PICK_HEAD

In reply to Jay Soffian

builtin/revert.c static void print_advice(void) · line 289

Quoted 13 lines · Jay Soffian
builtin/revert.c +5 -0
@@ -263,6 +279,11 @@ static void print_advice(void)
 
        if (msg) {
                fprintf(stderr, "%s\n", msg);
+               /*
+                * rebase interactive takes care of the authorship
+                * when the user invokes rebase --continue
+                */
+               unlink(git_path("CHERRY_PICK_HEAD"));
                return;
        }
 

Oops, I amended the comment and then fed the wrong commit to format-patch. That should be:

@@ -263,6 +279,11 @@ static void print_advice(void)

        if (msg) {
                fprintf(stderr, "%s\n", msg);
+               /*
+                * we're in the middle of an interactive rebase, we
+                * don't want it to look like we're cherry-picking.
+                */
+               unlink(git_path("CHERRY_PICK_HEAD"));
                return;
        }

Let me know if you want me to resend. (Sorry.)

j.

#9 lore raw

Re: [PATCH 1/2] Introduce CHERRY_PICK_HEAD

In reply to Jay Soffian
Quoted 8 lines · Jay Soffian

When a cherry-pick conflicts git advises to use:

 $ git commit -c <original commit id>

to preserve the original commit message and authorship. Instead, let's record the original commit id in CHERRY_PICK_HEAD and advise to use:

 $ git commit -c CHERRY_PICK_HEAD

Wouldn't it be more convenient to do "git cherry-pick --continue" instead of "git commit -c CHERRY_PICK_HEAD"?

Signature · 1 line
Duy
#10 lore raw

Re: [PATCH 1/2] Introduce CHERRY_PICK_HEAD

Quoted 5 lines · Nguyen Thai Ngoc Duy
Quoted 4 lines · Jay Soffian

When a cherry-pick conflicts git advises to use:

 $ git commit -c <original commit id>
Quoted 7 lines
Quoted 4 lines

to preserve the original commit message and authorship. Instead, let's record the original commit id in CHERRY_PICK_HEAD and advise to use:

 $ git commit -c CHERRY_PICK_HEAD

Wouldn't it be more convenient to do "git cherry-pick --continue" instead of "git commit -c CHERRY_PICK_HEAD"?

As mentioned in the part of the commit message you trimmed away: "In the next commit, we teach git to handle the '-c CHERRY_PICK_HEAD' part". Now, you may ask, why use "git commit" after resolving the conflict (a la merge) instead of "git cherry-pick --continue" (a la rebase).

I addressed this in the previous thread, see
http://article.gmane.org/gmane.comp.version-control.git/166884

j.

#11 lore raw

PATCH 2/2 Teach commit about CHERRY_PICK_HEAD

In reply to Jay Soffian

Previously the user was advised to use commit -c CHERRY_PICK_HEAD after a conflicting cherry-pick. While this would preserve the original commit's authorship, it would sadly discard cherry-pick's carefully crafted MERGE_MSG (which contains the list of conflicts as well as the original commit-id in the case of cherry-pick -x).

On the other hand, if a bare 'commit' were performed, it would preserve the MERGE_MSG while resetting the authorship.

In other words, there was no way to simultaneously take the authorship from CHERRY_PICK_HEAD and the commit message from MERGE_MSG.

This change fixes that situation. A bare 'commit' will now take the authorship from CHERRY_PICK_HEAD and the commit message from MERGE_MSG. If the user wishes to reset authorship, that must now be done explicitly via --reset-author.

A side-benefit of passing commit authorship along this way is that we can eliminate redundant authorship parsing code from revert.c.

A couple minor points:

* While we're at it, we update git-completion.bash to be CHERRY_PICK_HEAD aware.

* We remove a unused import from revert.c

---
 Documentation/git-commit.txt           |    7 +-
 builtin/commit.c                       |  137 +++++++++++++++++++++----------
 builtin/revert.c                       |   56 +-------------
 contrib/completion/git-completion.bash |    2 +
 t/t3507-cherry-pick-conflict.sh        |    2 +-
 t/t7509-commit.sh                      |   29 +++++++
 wt-status.c                            |    4 +-
 wt-status.h                            |    8 ++-
 8 files changed, 139 insertions(+), 106 deletions(-)
Documentation/git-commit.txt +4 -3
index b586c0f..fd6a1f7 100644
@@ -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
builtin/commit.c +93 -44

270 lines not on this page · raw message

builtin/revert.c +1 -55

80 lines not on this page · raw message

contrib/completion/git-completion.bash +2 -0
index 893b771..0b0b913 100755
@@ -246,6 +246,8 @@ __git_ps1 ()
 				fi
 			elif [ -f "$g/MERGE_HEAD" ]; then
 				r="|MERGING"
+			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+				r="|CHERRY-PICKING"
 			elif [ -f "$g/BISECT_LOG" ]; then
 				r="|BISECTING"
 			fi
t/t3507-cherry-pick-conflict.sh +1 -1
index fd569c8..365a1ba 100755
@@ -57,7 +57,7 @@ test_expect_success 'advice from failed cherry-pick' "
 	error: could not apply \$picked... picked
 	hint: after resolving the conflicts, mark the corrected paths
 	hint: with 'git add <paths>' or 'git rm <paths>'
-	hint: and commit the result with 'git commit -c CHERRY_PICK_HEAD'
+	hint: and commit the result with 'git commit'
 	EOF
 	test_must_fail git cherry-pick picked 2>actual &&
 
t/t7509-commit.sh +29 -0
index 77b6920..b61fd3c 100755
@@ -157,4 +157,33 @@ test_expect_success '--reset-author should be rejected without -c/-C/--amend' '
 	test_must_fail git commit -a --reset-author -m done
 '
 
+test_expect_success 'commit respects CHERRY_PICK_HEAD and MERGE_MSG' '
+	echo "cherry-pick 1a" >>foo &&
+	test_tick &&
+	git commit -am "cherry-pick 1" --author="Cherry <[email protected]>" &&
+	git tag cherry-pick-head &&
+	git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&
+	echo "This is a MERGE_MSG" >.git/MERGE_MSG &&
+	echo "cherry-pick 1b" >>foo &&
+	test_tick &&
+	git commit -a &&
+	author_header cherry-pick-head >expect &&
+	author_header HEAD >actual &&
+	test_cmp expect actual &&
+
+	echo "This is a MERGE_MSG" >expect &&
+	message_body HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--reset-author with CHERRY_PICK_HEAD' '
+	git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&
+	echo "cherry-pick 2" >>foo &&
+	test_tick &&
+	git commit -am "cherry-pick 2" --reset-author &&
+	echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
+	author_header HEAD >actual &&
+	test_cmp expect actual
+'
+
 test_done
wt-status.c +2 -2
index 123582b..fbaaf54 100644
@@ -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);
@@ -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"??? */
 	else if (!s->is_initial)
 		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference);
wt-status.h +7 -1
index 20b17cf..bf2eb27 100644
@@ -24,6 +24,12 @@ enum untracked_status_type {
 	SHOW_ALL_UNTRACKED_FILES
 };
 
+enum commit_whence {
+  FROM_COMMIT,
+  FROM_MERGE,
+  FROM_CHERRY_PICK
+};
+
 struct wt_status_change_data {
 	int worktree_status;
 	int index_status;
@@ -40,7 +46,7 @@ struct wt_status {
 	const char **pathspec;
 	int verbose;
 	int amend;
-	int in_merge;
+	enum commit_whence whence;
 	int nowarn;
 	int use_color;
 	int relative_paths;
Signature · 1 line
1.7.4.1.28.gd46b3
#12 lore raw

PATCH 1/1 bash: teach __git_ps1 about CHERRY_PICK_HEAD

From: Jay Soffian <[email protected]>

Make the git prompt (when enabled) show a CHERRY-PICKING indicator when we are in the middle of a conflicted cherry-pick, analogous to the existing MERGING and BISECTING flags.

---

Quoted 2 lines

* While we're at it, we update git-completion.bash to be CHERRY_PICK_HEAD aware.

Hmm, it seems I don't like this "while at it". :)

 contrib/completion/git-completion.bash |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
contrib/completion/git-completion.bash +2 -0
index 893b771..0b0b913 100755
@@ -246,6 +246,8 @@ __git_ps1 ()
 				fi
 			elif [ -f "$g/MERGE_HEAD" ]; then
 				r="|MERGING"
+			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+				r="|CHERRY-PICKING"
 			elif [ -f "$g/BISECT_LOG" ]; then
 				r="|BISECTING"
 			fi
Signature · 1 line
1.7.4.1
#13 lore raw

Re: [PATCH 1.5/2] bash: teach __git_ps1 about CHERRY_PICK_HEAD

Quoted 1 line · Jonathan Nieder

Hmm, it seems I don't like this "while at it". :)

I don't either. The series will be re-rolled so I don't have to pick this up myself, yes?

#14 lore raw

Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD

In reply to Jay Soffian
Quoted 4 lines · Jay Soffian

This change fixes that situation. A bare 'commit' will now take the authorship from CHERRY_PICK_HEAD and the commit message from MERGE_MSG. If the user wishes to reset authorship, that must now be done explicitly via --reset-author.

Might also be worth mentioning that it makes --amend fail in such a situation (a change worth celebrating).

builtin/commit.c static const char empty_amend_advice[] = · line 62

Quoted 11 lines
builtin/commit.c +3 -1
@@ -56,8 +56,10 @@ static const char empty_amend_advice[] =
 
 static unsigned char head_sha1[20];
 
-static char *use_message_buffer;
+static const char *use_message_buffer;
 static const char commit_editmsg[] = "COMMIT_EDITMSG";
+static const char cherry_pick_head[] = "CHERRY_PICK_HEAD";
+static const char merge_head[] = "MERGE_HEAD";

Hmm, these variables but not MERGE_MSG, MERGE_MODE, and SQUASH_MSG?

builtin/commit.c static enum { · line 73

Quoted 5 lines
builtin/commit.c +1 -0
@@ -68,6 +70,7 @@ static enum {
 
 static const char *logfile, *force_author;
 static const char *template_file;
+static const char *author_message, *author_message_buffer;

That's not a message at all, is it? On first reading I thought it would be a message about the author. Maybe a comment can help.

	/* name and content of commit from which to copy authorship */

builtin/commit.c static enum { · line 95

Quoted 7 lines
builtin/commit.c +2 -1
@@ -88,7 +91,8 @@ static enum {
 } cleanup_mode;
 static char *cleanup_arg;
 
-static int use_editor = 1, initial_commit, in_merge, include_status = 1;
+static enum commit_whence whence;
+static int use_editor = 1, initial_commit, include_status = 1;

The name "whence" is not so self-explanatory but I don't have any better ideas (I probably would have written "merge_or_cherry_pick"; we can be glad you came up with something better).

builtin/commit.c static struct option builtin_commit_options[] = { · line 173

Quoted 8 lines
builtin/commit.c +4 -0
@@ -163,6 +167,36 @@ static struct option builtin_commit_options[] = {
 	OPT_END()
 };
 
+static void determine_whence(struct wt_status *s)
+{
+	if (file_exists(git_path(merge_head)))
+		whence = FROM_MERGE;

Micronit: maybe COMMITTING_A_MERGE or COMMIT_DURING_MERGE to avoid using valuable namespace?

builtin/commit.c static int prepare_to_commit(const char *index_file, const char *prefix, · line 682

Quoted 7 lines
builtin/commit.c +1 -1
@@ -644,7 +678,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 	 * This final case does not modify the template message,
 	 * it just sets the argument to the prepare-commit-msg hook.
 	 */
-	else if (in_merge)
+	else if (whence == FROM_MERGE)
 		hook_arg1 = "merge";

Perhaps:

	else if (whence == CHERRY_PICK) {
		hook_arg1 = "commit";
		hook_arg2 = author_message;
	}
Quoted 1 line
builtin/commit.c +0 -0
@@ -694,16 +728,18 @@ static int prepare_to_commit(const char *index_file, const char *prefix,

[...]

builtin/commit.c static int prepare_to_commit(const char *index_file, const char *prefix, · line 742

Quoted 8 lines
builtin/commit.c +4 -0
 				"# If this is not correct, please remove the file\n"
 				"#	%s\n"
 				"# and try again.\n"
 				"#\n",
+				whence_s(),
+				git_path(whence == FROM_MERGE
+					 ? merge_head
+					 : cherry_pick_head));

Ok. We probably should move away from having to suggest "rm -f .git/whatever" in the future (maybe

git update-ref -d %s

is simpler advice? I dunno).

builtin/commit.c static void handle_untracked_files_arg(struct wt_status *s) · line 937

Quoted 5 lines
builtin/commit.c +1 -0
@@ -898,6 +934,27 @@ static void handle_untracked_files_arg(struct wt_status *s)
 		die("Invalid untracked files mode '%s'", untracked_files_arg);
 }
 
+static const char *read_commit_message(const char *name) {

Nice. Opening '{' should be in the first column.

Quoted 1 line
builtin/commit.c +1 -0
+++ b/builtin/revert.c

[...]

builtin/commit.c static void print_advice(void) · line 236

Quoted 8 lines
builtin/commit.c +1 -3
@@ -284,9 +233,7 @@ static void print_advice(void)
 
 	advise("after resolving the conflicts, mark the corrected paths");
 	advise("with 'git add <paths>' or 'git rm <paths>'");
-
-	if (action == CHERRY_PICK)
-		advise("and commit the result with 'git commit -c CHERRY_PICK_HEAD'");
+	advise("and commit the result with 'git commit'");

Hoorah!

wt-status.c static void wt_status_print_unmerged_header(struct wt_status *s) · line 66

Quoted 11 lines
wt-status.c +1 -1
@@ -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);

Isn't the advice of using "git reset -- <paths>" still good in the CHERRY_PICK case?

wt-status.c static void wt_status_print_cached_header(struct wt_status *s) · line 81

Quoted 7 lines
wt-status.c +1 -1
@@ -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 here.

wt-status.h enum untracked_status_type { · line 31

Quoted 11 lines
wt-status.h +5 -0
@@ -24,6 +24,12 @@ enum untracked_status_type {
 	SHOW_ALL_UNTRACKED_FILES
 };
 
+enum commit_whence {
+  FROM_COMMIT,
+  FROM_MERGE,
+  FROM_CHERRY_PICK
+};

Style: please use tabs to indent.

wt-status.h struct wt_status { · line 49

Quoted 6 lines
wt-status.h +1 -1
@@ -40,7 +46,7 @@ struct wt_status {
 	const char **pathspec;
 	int verbose;
 	int amend;
-	int in_merge;
+	enum commit_whence whence;

Might benefit from a comment.

	/* whether a merge or cherry-pick is in progress */
	enum commit_whence whence;

Thanks, very readable.

#15 lore raw

Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD

Quoted 2 lines · Jonathan Nieder

Might also be worth mentioning that it makes --amend fail in such a situation (a change worth celebrating).

Never made that particular mistake myself, but okay.

Quoted 6 lines
Quoted 6 lines
builtin/commit.c +0 -0
@@ -56,8 +56,10 @@ static const char empty_amend_advice[] =
 
  static unsigned char head_sha1[20];
 
Quoted 7 lines

builtin/commit.c static const char empty_amend_advice[] = · line 62

Quoted 5 lines
builtin/commit.c +3 -1
-static char *use_message_buffer;
+static const char *use_message_buffer;
  static const char commit_editmsg[] = "COMMIT_EDITMSG";
+static const char cherry_pick_head[] = "CHERRY_PICK_HEAD";
+static const char merge_head[] = "MERGE_HEAD";

Hmm, these variables but not MERGE_MSG, MERGE_MODE, and SQUASH_MSG?

I cleaned up the ones my patch touched. Cleaning up the rest of commit.c was out of my purview. :-)

I'll clean them up to be consistent, but I'll do it as a separate patch (before this one).

Quoted 10 lines

builtin/commit.c static enum { · line 73

Quoted 5 lines
builtin/commit.c +1 -0
@@ -68,6 +70,7 @@ static enum {
 
  static const char *logfile, *force_author;
  static const char *template_file;
+static const char *author_message, *author_message_buffer;

That's not a message at all, is it?  On first reading I thought it would be a message about the author.  Maybe a comment can help.

       /* name and content of commit from which to copy authorship */

The name is consistent with the other similar purpose variables:
use_message, edit_message, squash_message, fixup_message, which all take a committish and aren't actually messages. None of those others have comments, but it's obvious in context how they are used.

Quoted 11 lines

builtin/commit.c static enum { · line 95

Quoted 7 lines
builtin/commit.c +2 -1
@@ -88,7 +91,8 @@ static enum {
  } cleanup_mode;
  static char *cleanup_arg;
 
-static int use_editor = 1, initial_commit, in_merge, include_status = 1;
+static enum commit_whence whence;
+static int use_editor = 1, initial_commit, include_status = 1;

The name "whence" is not so self-explanatory but I don't have any better ideas (I probably would have written "merge_or_cherry_pick"; we can be glad you came up with something better).

Respectfully disagree. Whence means "from where something came" as in "from where did this commit we're about to make originate?" and I intentionally didn't use _ORIGIN as "origin" has another meaning already in git context.

Quoted 11 lines

builtin/commit.c static struct option builtin_commit_options[] = { · line 173

Quoted 8 lines
builtin/commit.c +4 -0
@@ -163,6 +167,36 @@ static struct option builtin_commit_options[] = {
       OPT_END()
  };
 
+static void determine_whence(struct wt_status *s)
+{
+     if (file_exists(git_path(merge_head)))
+             whence = FROM_MERGE;

Micronit: maybe COMMITTING_A_MERGE or COMMIT_DURING_MERGE to avoid using valuable namespace?

Respectfully disagree.

Quoted 6 lines

Perhaps:

       else if (whence == CHERRY_PICK) {
               hook_arg1 = "commit";
               hook_arg2 = author_message;
       }

Perhaps.

Quoted 6 lines

Ok.  We probably should move away from having to suggest "rm -f .git/whatever" in the future (maybe

       git update-ref -d %s

is simpler advice?  I dunno).

Out of scope for this patch. :-)

Quoted 1 line

Nice.  Opening '{' should be in the first column.

Good catch.

Quoted 2 lines

Isn't the advice of using "git reset -- <paths>" still good in the CHERRY_PICK case?

I don't know. I couldn't make up my mind. If it's a conflicted path you've edited in the working copy, then the advice should be "checkout --merge". I think. Maybe. I don't find wt-status.c to be very much fun, so I punted.

Quoted 5 lines
Quoted 3 lines
builtin/commit.c +1 -1
-     if (s->in_merge)
+     if (s->whence != FROM_COMMIT)

              ; /* NEEDSWORK: use "git reset --unresolve"??? */

Likewise here.

Checkout that NEEDSWORK. Someone should get on that. :-)

Quoted 1 line

Style: please use tabs to indent.

Who ate my tabs?

Quoted 4 lines

Might benefit from a comment.

       /* whether a merge or cherry-pick is in progress */ enum commit_whence whence;

Agreed.

Quoted 1 line

Thanks, very readable.

Good feedback.

j.

#16 lore raw

Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD

In reply to Jay Soffian
Quoted 2 lines · Jay Soffian

If the user wishes to reset authorship, that must now be done explicitly via --reset-author.

This is not a new requirement, is it? Even "commit -c $that_commit" before the previous "commit -c CHERRY_PICK_HEAD" does use the original, no?

I think the changed code is _MUCH_ easier to follow compared to the previous round; the only thing the reader needs to keep in mind is that the most of the change essentially is "s/in_merge/whence != FROM_COMMIT/" and making that work.

Quoted 1 line

* We remove a unused import from revert.c

Micronit: s/import/include/.

builtin/commit.c static int prepare_to_commit(const char *index_file, const char *prefix, · line 808

Quoted 9 lines
builtin/commit.c +1 -1
@@ -766,7 +802,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 
 	fclose(fp);
 
-	if (!commitable && !in_merge && !allow_empty &&
+	if (!commitable && whence != FROM_MERGE && !allow_empty &&
 	    !(amend && is_a_merge(head_sha1))) {
 		run_status(stdout, index_file, prefix, 0, s);
 		if (amend)

The original says that we reject an attempt to record a no-change commit when the user is making his own commit without an explicit --allow-empty request. Should cherry-pick change this?

"git cherry-pick $a_no_change_commit" does not cause conflicts but it does fail with "nothing added to commit". If you said "whence == FROM_COMMIT" here, you would end up allowing "git commit" following such a failure to commit without --allow-empty, and that inconsistency is to be avoided (note that I didn't check if you leave CHERRY_PICK_HEAD behind to trigger this codepath when this happens).

On the other hand, when the earlier cherry-pick did fail with conflict, but the resolution ended up to be a no-change commit, you would not blindly want to record the result as a no-change commit, either.

So I think the above is the right thing to do, but we probably need a bit of in-code comment to describe why we say "whence != FROM_MERGE" here.

Thanks.

#17 lore raw

Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD

Quoted 8 lines · Junio C Hamano
Quoted 2 lines · Jay Soffian

If the user wishes to reset authorship, that must now be done explicitly via --reset-author.

This is not a new requirement, is it?  Even "commit -c $that_commit" before the previous "commit -c CHERRY_PICK_HEAD" does use the original, no?

It is a new requirement for when the user does a bare "commit" _and_ CHERRY_PICK_HEAD exists.

Normally a bare "commit" creates new authorship, but when CHERRY_PICK_HEAD exists, authorship is taken from CHERRY_PICK_HEAD commit unless --reset-author is specified.

Quoted 4 lines

I think the changed code is _MUCH_ easier to follow compared to the previous round; the only thing the reader needs to keep in mind is that the most of the change essentially is "s/in_merge/whence != FROM_COMMIT/" and making that work.

I think I was trying to be too clever in the previous round.

Quoted 3 lines
Quoted 1 line

* We remove a unused import from revert.c

Micronit: s/import/include/.

Okay.

Quoted 2 lines

So I think the above is the right thing to do, but we probably need a bit of in-code comment to describe why we say "whence != FROM_MERGE" here.

Will do. It took me several tries to understand what that code block was trying to do, so a comment will certainly help future readers.

Thanks,

j.