{"thread":{"id":"26518","subject":"[PATCH 0/2] CHERRY_PICK_HEAD","startedAt":"2011-02-16T10:08:21Z","lastAt":"2011-02-17T22:16:45Z","messageCount":18,"participants":["Jay Soffian","Nguyen Thai Ngoc Duy","Junio C Hamano","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"161281","messageId":"1297850903-65038-1-git-send-email-jaysoffian@gmail.com","threadId":"26518","inReplyTo":null,"subject":"[PATCH 0/2] CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T10:08:21Z","receivedAt":"2011-02-16T10:08:21Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"Re-roll of http://thread.gmane.org/gmane.comp.version-control.git/166878\n\nIf not ready for inclusion, hopefully very close.\n\nJay Soffian (2):\n  Introduce CHERRY_PICK_HEAD\n  Teach commit about CHERRY_PICK_HEAD\n\n Documentation/git-cherry-pick.txt      |   19 +++++\n Documentation/git-commit.txt           |    7 +-\n Documentation/revisions.txt            |    5 +-\n branch.c                               |    1 +\n builtin/commit.c                       |  136 ++++++++++++++++++++++----------\n builtin/merge.c                        |    7 ++\n builtin/revert.c                       |   68 ++++------------\n contrib/completion/git-completion.bash |    2 +\n t/t3507-cherry-pick-conflict.sh        |   22 +++++-\n t/t7509-commit.sh                      |   29 +++++++\n wt-status.c                            |    4 +-\n wt-status.h                            |    8 ++-\n 12 files changed, 204 insertions(+), 104 deletions(-)\n\n-- \n1.7.4.1.28.gd46b3\n"},{"id":"161282","messageId":"1297850903-65038-2-git-send-email-jaysoffian@gmail.com","threadId":"26518","inReplyTo":"1297850903-65038-1-git-send-email-jaysoffian@gmail.com","subject":"[PATCH 1/2] Introduce CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T10:08:22Z","receivedAt":"2011-02-16T10:08:22Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"When a cherry-pick conflicts git advises to use:\n\n $ git commit -c <original commit id>\n\nto preserve the original commit message and authorship. Instead, let's\nrecord the original commit id in CHERRY_PICK_HEAD and advise to use:\n\n  $ git commit -c CHERRY_PICK_HEAD\n\nIn the next commit, we teach git to handle the '-c CHERRY_PICK_HEAD'\npart. Note that wWe record CHERRY_PICK_HEAD even in the case where there\nare no conflicts so that we may use it to communicate authorship to\ncommit; this will then allow us to remove set_author_ident_env from\nrevert.c.\n\nContributions-by: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Jay Soffian <jaysoffian@gmail.com>\n---\n Documentation/git-cherry-pick.txt |   19 +++++++++++++++++++\n Documentation/revisions.txt       |    5 ++++-\n branch.c                          |    1 +\n builtin/commit.c                  |    1 +\n builtin/merge.c                   |    7 +++++++\n builtin/revert.c                  |   20 ++++++++++++++++++--\n t/t3507-cherry-pick-conflict.sh   |   22 +++++++++++++++++++++-\n 7 files changed, 71 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt\nindex 749d68a..5d85daa 100644\n--- a/Documentation/git-cherry-pick.txt\n+++ b/Documentation/git-cherry-pick.txt\n@@ -16,6 +16,25 @@ Given one or more existing commits, apply the change each one\n introduces, recording a new commit for each.  This requires your\n working tree to be clean (no modifications from the HEAD commit).\n \n+When it is not obvious how to apply a change, the following\n+happens:\n+\n+1. The current branch and `HEAD` pointer stay at the last commit\n+   successfully made.\n+2. The `CHERRY_PICK_HEAD` ref is set to point at the commit that\n+   introduced the change that is difficult to apply.\n+3. Paths in which the change applied cleanly are updated both\n+   in the index file and in your working tree.\n+4. For conflicting paths, the index file records up to three\n+   versions, as described in the \"TRUE MERGE\" section of\n+   linkgit:git-merge[1].  The working tree files will include\n+   a description of the conflict bracketed by the usual\n+   conflict markers `<<<<<<<` and `>>>>>>>`.\n+5. No other modifications are made.\n+\n+See linkgit:git-merge[1] for some hints on resolving such\n+conflicts.\n+\n OPTIONS\n -------\n <commit>...::\ndiff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\nindex 9e92734..04fceee 100644\n--- a/Documentation/revisions.txt\n+++ b/Documentation/revisions.txt\n@@ -25,7 +25,8 @@ blobs contained in a commit.\n   first match in the following rules:\n \n   . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually\n-    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);\n+    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD`, `MERGE_HEAD`\n+    and `CHERRY_PICK_HEAD`);\n \n   . otherwise, `refs/<name>` if exists;\n \n@@ -46,6 +47,8 @@ you can change the tip of the branch back to the state before you ran\n them easily.\n MERGE_HEAD records the commit(s) you are merging into your branch\n when you run 'git merge'.\n+CHERRY_PICK_HEAD records the commit you are cherry-picking\n+when you run 'git cherry-pick'.\n +\n Note that any of the `refs/*` cases above may come either from\n the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.\ndiff --git a/branch.c b/branch.c\nindex 93dc866..dc23e95 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -217,6 +217,7 @@ void create_branch(const char *head,\n \n void remove_branch_state(void)\n {\n+\tunlink(git_path(\"CHERRY_PICK_HEAD\"));\n \tunlink(git_path(\"MERGE_HEAD\"));\n \tunlink(git_path(\"MERGE_RR\"));\n \tunlink(git_path(\"MERGE_MSG\"));\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 03cff5a..0def540 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1424,6 +1424,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tdie(\"cannot update HEAD ref\");\n \t}\n \n+\tunlink(git_path(\"CHERRY_PICK_HEAD\"));\n \tunlink(git_path(\"MERGE_HEAD\"));\n \tunlink(git_path(\"MERGE_MSG\"));\n \tunlink(git_path(\"MERGE_MODE\"));\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 9403747..454dad2 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -971,6 +971,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\telse\n \t\t\tdie(\"You have not concluded your merge (MERGE_HEAD exists).\");\n \t}\n+\tif (file_exists(git_path(\"CHERRY_PICK_HEAD\"))) {\n+\t\tif (advice_resolve_conflict)\n+\t\t\tdie(\"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\\n\"\n+\t\t\t    \"Please, commit your changes before you can merge.\");\n+\t\telse\n+\t\t\tdie(\"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\");\n+\t}\n \tresolve_undo_clear();\n \n \tif (verbosity < 0)\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex dc1b702..cced2e4 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -248,6 +248,22 @@ static void set_author_ident_env(const char *message)\n \t\t\tsha1_to_hex(commit->object.sha1));\n }\n \n+static void write_cherry_pick_head(void)\n+{\n+\tint fd;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\n+\tstrbuf_addf(&buf, \"%s\\n\", sha1_to_hex(commit->object.sha1));\n+\n+\tfd = open(git_path(\"CHERRY_PICK_HEAD\"), O_WRONLY | O_CREAT, 0666);\n+\tif (fd < 0)\n+\t\tdie_errno(\"Could not open '%s' for writing\",\n+\t\t\t  git_path(\"CHERRY_PICK_HEAD\"));\n+\tif (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))\n+\t\tdie_errno(\"Could not write to '%s'\", git_path(\"CHERRY_PICK_HEAD\"));\n+\tstrbuf_release(&buf);\n+}\n+\n static void advise(const char *advice, ...)\n {\n \tva_list params;\n@@ -270,8 +286,7 @@ static void print_advice(void)\n \tadvise(\"with 'git add <paths>' or 'git rm <paths>'\");\n \n \tif (action == CHERRY_PICK)\n-\t\tadvise(\"and commit the result with 'git commit -c %s'\",\n-\t\t       find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));\n+\t\tadvise(\"and commit the result with 'git commit -c CHERRY_PICK_HEAD'\");\n }\n \n static void write_message(struct strbuf *msgbuf, const char *filename)\n@@ -504,6 +519,7 @@ static int do_pick_commit(void)\n \t\t\tstrbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));\n \t\t\tstrbuf_addstr(&msgbuf, \")\\n\");\n \t\t}\n+\t\twrite_cherry_pick_head();\n \t}\n \n \tif (!strategy || !strcmp(strategy, \"recursive\") || action == REVERT) {\ndiff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh\nindex 607bf25..fd569c8 100755\n--- a/t/t3507-cherry-pick-conflict.sh\n+++ b/t/t3507-cherry-pick-conflict.sh\n@@ -11,6 +11,12 @@ test_description='test cherry-pick and revert with conflicts\n \n . ./test-lib.sh\n \n+test_cmp_rev () {\n+\tgit rev-parse --verify \"$1\" >expect.rev &&\n+\tgit rev-parse --verify \"$2\" >actual.rev &&\n+\ttest_cmp expect.rev actual.rev\n+}\n+\n test_expect_success setup '\n \n \techo unrelated >unrelated &&\n@@ -51,13 +57,27 @@ test_expect_success 'advice from failed cherry-pick' \"\n \terror: could not apply \\$picked... picked\n \thint: after resolving the conflicts, mark the corrected paths\n \thint: with 'git add <paths>' or 'git rm <paths>'\n-\thint: and commit the result with 'git commit -c \\$picked'\n+\thint: and commit the result with 'git commit -c CHERRY_PICK_HEAD'\n \tEOF\n \ttest_must_fail git cherry-pick picked 2>actual &&\n \n \ttest_cmp expected actual\n \"\n \n+test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\ttest_must_fail git cherry-pick picked &&\n+\n+\ttest_cmp_rev picked CHERRY_PICK_HEAD\n+'\n+\n test_expect_success 'failed cherry-pick produces dirty index' '\n \n \tgit checkout -f initial^0 &&\n-- \n1.7.4.1.28.gd46b3\n"},{"id":"161283","messageId":"1297850903-65038-3-git-send-email-jaysoffian@gmail.com","threadId":"26518","inReplyTo":"1297850903-65038-1-git-send-email-jaysoffian@gmail.com","subject":"[PATCH 2/2] Teach commit about CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T10:08:23Z","receivedAt":"2011-02-16T10:08:23Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"Previously the user was advised to use commit -c CHERRY_PICK_HEAD after\na conflicting cherry-pick. While this would preserve the original\ncommit's authorship, it would sadly discard cherry-pick's carefully\ncrafted MERGE_MSG (which contains the list of conflicts as well as the\noriginal commit-id in the case of cherry-pick -x).\n\nOn the other hand, if a bare 'commit' were performed, it would preserve\nthe MERGE_MSG while resetting the authorship.\n\nIn other words, there was no way to simultaneously take the authorship\nfrom CHERRY_PICK_HEAD and the commit message from MERGE_MSG.\n\nThis change fixes that situation. A bare 'commit' will now take the\nauthorship from CHERRY_PICK_HEAD and the commit message from MERGE_MSG.\nIf the user wishes to reset authorship, that must now be done explicitly\nvia --reset-author.\n\nA side-benefit of passing commit authorship along this way is that we\ncan eliminate redundant authorship parsing code from revert.c.\n\nA couple minor points:\n\n* While we're at it, we update git-completion.bash to be\n  CHERRY_PICK_HEAD aware.\n\n* We remove a unused import from revert.c\n\nSigned-off-by: Jay Soffian <jaysoffian@gmail.com>\n---\n Documentation/git-commit.txt           |    7 +-\n builtin/commit.c                       |  137 +++++++++++++++++++++----------\n builtin/revert.c                       |   56 +-------------\n contrib/completion/git-completion.bash |    2 +\n t/t3507-cherry-pick-conflict.sh        |    2 +-\n t/t7509-commit.sh                      |   29 +++++++\n wt-status.c                            |    4 +-\n wt-status.h                            |    8 ++-\n 8 files changed, 139 insertions(+), 106 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex b586c0f..fd6a1f7 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -84,9 +84,10 @@ OPTIONS\n \tlinkgit:git-rebase[1] for details.\n \n --reset-author::\n-\tWhen used with -C/-c/--amend options, declare that the\n-\tauthorship of the resulting commit now belongs of the committer.\n-\tThis also renews the author timestamp.\n+\tWhen used with -C/-c/--amend options, or when committing after a\n+\ta conflicting cherry-pick, declare that the authorship of the\n+\tresulting commit now belongs of the committer. This also renews\n+\tthe author timestamp.\n \n --short::\n \tWhen doing a dry-run, give the output in the short-format. See\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 0def540..9d8ad8e 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -56,8 +56,10 @@ static const char empty_amend_advice[] =\n \n static unsigned char head_sha1[20];\n \n-static char *use_message_buffer;\n+static const char *use_message_buffer;\n static const char commit_editmsg[] = \"COMMIT_EDITMSG\";\n+static const char cherry_pick_head[] = \"CHERRY_PICK_HEAD\";\n+static const char merge_head[] = \"MERGE_HEAD\";\n static struct lock_file index_lock; /* real index */\n static struct lock_file false_lock; /* used only for partial commits */\n static enum {\n@@ -68,6 +70,7 @@ static enum {\n \n static const char *logfile, *force_author;\n static const char *template_file;\n+static const char *author_message, *author_message_buffer;\n static char *edit_message, *use_message;\n static char *fixup_message, *squash_message;\n static int all, edit_flag, also, interactive, only, amend, signoff;\n@@ -88,7 +91,8 @@ static enum {\n } cleanup_mode;\n static char *cleanup_arg;\n \n-static int use_editor = 1, initial_commit, in_merge, include_status = 1;\n+static enum commit_whence whence;\n+static int use_editor = 1, initial_commit, include_status = 1;\n static int show_ignored_in_status;\n static const char *only_include_assumed;\n static struct strbuf message;\n@@ -163,6 +167,36 @@ static struct option builtin_commit_options[] = {\n \tOPT_END()\n };\n \n+static void determine_whence(struct wt_status *s)\n+{\n+\tif (file_exists(git_path(merge_head)))\n+\t\twhence = FROM_MERGE;\n+\telse if (file_exists(git_path(cherry_pick_head)))\n+\t\twhence = FROM_CHERRY_PICK;\n+\telse\n+\t\twhence = FROM_COMMIT;\n+\tif (s)\n+\t\ts->whence = whence;\n+}\n+\n+static const char *whence_s(void)\n+{\n+\tchar *s = \"\";\n+\n+\tswitch (whence) {\n+\tcase FROM_COMMIT:\n+\t\tbreak;\n+\tcase FROM_MERGE:\n+\t\ts = \"merge\";\n+\t\tbreak;\n+\tcase FROM_CHERRY_PICK:\n+\t\ts = \"cherry-pick\";\n+\t\tbreak;\n+\t}\n+\n+\treturn s;\n+}\n+\n static void rollback_index_files(void)\n {\n \tswitch (commit_style) {\n@@ -378,8 +412,8 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int\n \t */\n \tcommit_style = COMMIT_PARTIAL;\n \n-\tif (in_merge)\n-\t\tdie(\"cannot do a partial commit during a merge.\");\n+\tif (whence != FROM_COMMIT)\n+\t\tdie(\"cannot do a partial commit during a %s.\", whence_s());\n \n \tmemset(&partial, 0, sizeof(partial));\n \tpartial.strdup_strings = 1;\n@@ -469,18 +503,18 @@ static void determine_author_info(struct strbuf *author_ident)\n \temail = getenv(\"GIT_AUTHOR_EMAIL\");\n \tdate = getenv(\"GIT_AUTHOR_DATE\");\n \n-\tif (use_message && !renew_authorship) {\n+\tif (author_message) {\n \t\tconst char *a, *lb, *rb, *eol;\n \n-\t\ta = strstr(use_message_buffer, \"\\nauthor \");\n+\t\ta = strstr(author_message_buffer, \"\\nauthor \");\n \t\tif (!a)\n-\t\t\tdie(\"invalid commit: %s\", use_message);\n+\t\t\tdie(\"invalid commit: %s\", author_message);\n \n \t\tlb = strchrnul(a + strlen(\"\\nauthor \"), '<');\n \t\trb = strchrnul(lb, '>');\n \t\teol = strchrnul(rb, '\\n');\n \t\tif (!*lb || !*rb || !*eol)\n-\t\t\tdie(\"invalid commit: %s\", use_message);\n+\t\t\tdie(\"invalid commit: %s\", author_message);\n \n \t\tif (lb == a + strlen(\"\\nauthor \"))\n \t\t\t/* \\nauthor <foo@example.com> */\n@@ -644,7 +678,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t * This final case does not modify the template message,\n \t * it just sets the argument to the prepare-commit-msg hook.\n \t */\n-\telse if (in_merge)\n+\telse if (whence == FROM_MERGE)\n \t\thook_arg1 = \"merge\";\n \n \tif (squash_message) {\n@@ -694,16 +728,18 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \tstrbuf_addstr(&committer_ident, git_committer_info(0));\n \tif (use_editor && include_status) {\n \t\tchar *ai_tmp, *ci_tmp;\n-\t\tif (in_merge)\n+\t\tif (whence != FROM_COMMIT)\n \t\t\tfprintf(fp,\n \t\t\t\t\"#\\n\"\n-\t\t\t\t\"# It looks like you may be committing a MERGE.\\n\"\n+\t\t\t\t\"# It looks like you may be committing a %s.\\n\"\n \t\t\t\t\"# If this is not correct, please remove the file\\n\"\n \t\t\t\t\"#\t%s\\n\"\n \t\t\t\t\"# and try again.\\n\"\n \t\t\t\t\"#\\n\",\n-\t\t\t\tgit_path(\"MERGE_HEAD\"));\n-\n+\t\t\t\twhence_s(),\n+\t\t\t\tgit_path(whence == FROM_MERGE\n+\t\t\t\t\t ? merge_head\n+\t\t\t\t\t : cherry_pick_head));\n \t\tfprintf(fp,\n \t\t\t\"\\n\"\n \t\t\t\"# Please enter the commit message for your changes.\");\n@@ -766,7 +802,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \n \tfclose(fp);\n \n-\tif (!commitable && !in_merge && !allow_empty &&\n+\tif (!commitable && whence != FROM_MERGE && !allow_empty &&\n \t    !(amend && is_a_merge(head_sha1))) {\n \t\trun_status(stdout, index_file, prefix, 0, s);\n \t\tif (amend)\n@@ -898,6 +934,27 @@ static void handle_untracked_files_arg(struct wt_status *s)\n \t\tdie(\"Invalid untracked files mode '%s'\", untracked_files_arg);\n }\n \n+static const char *read_commit_message(const char *name) {\n+\tconst char *out_enc, *out;\n+\tstruct commit *commit;\n+\n+\tcommit = lookup_commit_reference_by_name(name);\n+\tif (!commit)\n+\t\tdie(\"could not lookup commit %s\", name);\n+\tout_enc = get_commit_output_encoding();\n+\tout = logmsg_reencode(commit, out_enc);\n+\n+\t/*\n+\t * If we failed to reencode the buffer, just copy it\n+\t * byte for byte so the user can try to fix it up.\n+\t * This also handles the case where input and output\n+\t * encodings are identical.\n+\t */\n+\tif (out == NULL)\n+\t\tout = xstrdup(commit->buffer);\n+\treturn out;\n+}\n+\n static int parse_and_validate_options(int argc, const char *argv[],\n \t\t\t\t      const char * const usage[],\n \t\t\t\t      const char *prefix,\n@@ -927,8 +984,8 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t/* Sanity check options */\n \tif (amend && initial_commit)\n \t\tdie(\"You have nothing to amend.\");\n-\tif (amend && in_merge)\n-\t\tdie(\"You are in the middle of a merge -- cannot amend.\");\n+\tif (amend && whence != FROM_COMMIT)\n+\t\tdie(\"You are in the middle of a %s -- cannot amend.\", whence_s());\n \tif (fixup_message && squash_message)\n \t\tdie(\"Options --squash and --fixup cannot be used together\");\n \tif (use_message)\n@@ -947,26 +1004,18 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tuse_message = edit_message;\n \tif (amend && !use_message && !fixup_message)\n \t\tuse_message = \"HEAD\";\n-\tif (!use_message && renew_authorship)\n+\tif (!use_message && whence != FROM_CHERRY_PICK && renew_authorship)\n \t\tdie(\"--reset-author can be used only with -C, -c or --amend.\");\n \tif (use_message) {\n-\t\tconst char *out_enc;\n-\t\tstruct commit *commit;\n-\n-\t\tcommit = lookup_commit_reference_by_name(use_message);\n-\t\tif (!commit)\n-\t\t\tdie(\"could not lookup commit %s\", use_message);\n-\t\tout_enc = get_commit_output_encoding();\n-\t\tuse_message_buffer = logmsg_reencode(commit, out_enc);\n-\n-\t\t/*\n-\t\t * If we failed to reencode the buffer, just copy it\n-\t\t * byte for byte so the user can try to fix it up.\n-\t\t * This also handles the case where input and output\n-\t\t * encodings are identical.\n-\t\t */\n-\t\tif (use_message_buffer == NULL)\n-\t\t\tuse_message_buffer = xstrdup(commit->buffer);\n+\t\tuse_message_buffer = read_commit_message(use_message);\n+\t\tif (!renew_authorship) {\n+\t\t\tauthor_message = use_message;\n+\t\t\tauthor_message_buffer = use_message_buffer;\n+\t\t}\n+\t}\n+\tif (whence == FROM_CHERRY_PICK && !renew_authorship) {\n+\t\tauthor_message = cherry_pick_head;\n+\t\tauthor_message_buffer = read_commit_message(author_message);\n \t}\n \n \tif (!!also + !!only + !!all + !!interactive > 1)\n@@ -1117,7 +1166,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)\n \twt_status_prepare(&s);\n \tgitmodules_config();\n \tgit_config(git_status_config, &s);\n-\tin_merge = file_exists(git_path(\"MERGE_HEAD\"));\n+\tdetermine_whence(&s);\n \targc = parse_options(argc, argv, prefix,\n \t\t\t     builtin_status_options,\n \t\t\t     builtin_status_usage, 0);\n@@ -1140,7 +1189,6 @@ int cmd_status(int argc, const char **argv, const char *prefix)\n \t}\n \n \ts.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;\n-\ts.in_merge = in_merge;\n \ts.ignore_submodule_arg = ignore_submodule_arg;\n \twt_status_collect(&s);\n \n@@ -1302,8 +1350,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \n \twt_status_prepare(&s);\n \tgit_config(git_commit_config, &s);\n-\tin_merge = file_exists(git_path(\"MERGE_HEAD\"));\n-\ts.in_merge = in_merge;\n+\tdetermine_whence(&s);\n \n \tif (s.use_color == -1)\n \t\ts.use_color = git_use_color_default;\n@@ -1340,17 +1387,17 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \n \t\tfor (c = commit->parents; c; c = c->next)\n \t\t\tpptr = &commit_list_insert(c->item, pptr)->next;\n-\t} else if (in_merge) {\n+\t} else if (whence == FROM_MERGE) {\n \t\tstruct strbuf m = STRBUF_INIT;\n \t\tFILE *fp;\n \n \t\tif (!reflog_msg)\n \t\t\treflog_msg = \"commit (merge)\";\n \t\tpptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;\n-\t\tfp = fopen(git_path(\"MERGE_HEAD\"), \"r\");\n+\t\tfp = fopen(git_path(merge_head), \"r\");\n \t\tif (fp == NULL)\n \t\t\tdie_errno(\"could not open '%s' for reading\",\n-\t\t\t\t  git_path(\"MERGE_HEAD\"));\n+\t\t\t\t  git_path(merge_head));\n \t\twhile (strbuf_getline(&m, fp, '\\n') != EOF) {\n \t\t\tunsigned char sha1[20];\n \t\t\tif (get_sha1_hex(m.buf, sha1) < 0)\n@@ -1369,7 +1416,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\t\tparents = reduce_heads(parents);\n \t} else {\n \t\tif (!reflog_msg)\n-\t\t\treflog_msg = \"commit\";\n+\t\t\treflog_msg = (whence == FROM_CHERRY_PICK)\n+\t\t\t\t\t? \"commit (cherry-pick)\"\n+\t\t\t\t\t: \"commit\";\n \t\tpptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;\n \t}\n \n@@ -1424,8 +1473,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tdie(\"cannot update HEAD ref\");\n \t}\n \n-\tunlink(git_path(\"CHERRY_PICK_HEAD\"));\n-\tunlink(git_path(\"MERGE_HEAD\"));\n+\tunlink(git_path(cherry_pick_head));\n+\tunlink(git_path(merge_head));\n \tunlink(git_path(\"MERGE_MSG\"));\n \tunlink(git_path(\"MERGE_MODE\"));\n \tunlink(git_path(\"SQUASH_MSG\"));\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex cced2e4..28d1d70 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -3,7 +3,6 @@\n #include \"object.h\"\n #include \"commit.h\"\n #include \"tag.h\"\n-#include \"wt-status.h\"\n #include \"run-command.h\"\n #include \"exec_cmd.h\"\n #include \"utf8.h\"\n@@ -198,56 +197,6 @@ static void add_message_to_msg(struct strbuf *msgbuf, const char *message)\n \tstrbuf_addstr(msgbuf, p);\n }\n \n-static void set_author_ident_env(const char *message)\n-{\n-\tconst char *p = message;\n-\tif (!p)\n-\t\tdie (\"Could not read commit message of %s\",\n-\t\t\t\tsha1_to_hex(commit->object.sha1));\n-\twhile (*p && *p != '\\n') {\n-\t\tconst char *eol;\n-\n-\t\tfor (eol = p; *eol && *eol != '\\n'; eol++)\n-\t\t\t; /* do nothing */\n-\t\tif (!prefixcmp(p, \"author \")) {\n-\t\t\tchar *line, *pend, *email, *timestamp;\n-\n-\t\t\tp += 7;\n-\t\t\tline = xmemdupz(p, eol - p);\n-\t\t\temail = strchr(line, '<');\n-\t\t\tif (!email)\n-\t\t\t\tdie (\"Could not extract author email from %s\",\n-\t\t\t\t\tsha1_to_hex(commit->object.sha1));\n-\t\t\tif (email == line)\n-\t\t\t\tpend = line;\n-\t\t\telse\n-\t\t\t\tfor (pend = email; pend != line + 1 &&\n-\t\t\t\t\t\tisspace(pend[-1]); pend--);\n-\t\t\t\t\t; /* do nothing */\n-\t\t\t*pend = '\\0';\n-\t\t\temail++;\n-\t\t\ttimestamp = strchr(email, '>');\n-\t\t\tif (!timestamp)\n-\t\t\t\tdie (\"Could not extract author time from %s\",\n-\t\t\t\t\tsha1_to_hex(commit->object.sha1));\n-\t\t\t*timestamp = '\\0';\n-\t\t\tfor (timestamp++; *timestamp && isspace(*timestamp);\n-\t\t\t\t\ttimestamp++)\n-\t\t\t\t; /* do nothing */\n-\t\t\tsetenv(\"GIT_AUTHOR_NAME\", line, 1);\n-\t\t\tsetenv(\"GIT_AUTHOR_EMAIL\", email, 1);\n-\t\t\tsetenv(\"GIT_AUTHOR_DATE\", timestamp, 1);\n-\t\t\tfree(line);\n-\t\t\treturn;\n-\t\t}\n-\t\tp = eol;\n-\t\tif (*p == '\\n')\n-\t\t\tp++;\n-\t}\n-\tdie (\"No author information found in %s\",\n-\t\t\tsha1_to_hex(commit->object.sha1));\n-}\n-\n static void write_cherry_pick_head(void)\n {\n \tint fd;\n@@ -284,9 +233,7 @@ static void print_advice(void)\n \n \tadvise(\"after resolving the conflicts, mark the corrected paths\");\n \tadvise(\"with 'git add <paths>' or 'git rm <paths>'\");\n-\n-\tif (action == CHERRY_PICK)\n-\t\tadvise(\"and commit the result with 'git commit -c CHERRY_PICK_HEAD'\");\n+\tadvise(\"and commit the result with 'git commit'\");\n }\n \n static void write_message(struct strbuf *msgbuf, const char *filename)\n@@ -512,7 +459,6 @@ static int do_pick_commit(void)\n \t\tbase_label = msg.parent_label;\n \t\tnext = commit;\n \t\tnext_label = msg.label;\n-\t\tset_author_ident_env(msg.message);\n \t\tadd_message_to_msg(&msgbuf, msg.message);\n \t\tif (no_replay) {\n \t\t\tstrbuf_addstr(&msgbuf, \"(cherry picked from commit \");\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 893b771..0b0b913 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -246,6 +246,8 @@ __git_ps1 ()\n \t\t\t\tfi\n \t\t\telif [ -f \"$g/MERGE_HEAD\" ]; then\n \t\t\t\tr=\"|MERGING\"\n+\t\t\telif [ -f \"$g/CHERRY_PICK_HEAD\" ]; then\n+\t\t\t\tr=\"|CHERRY-PICKING\"\n \t\t\telif [ -f \"$g/BISECT_LOG\" ]; then\n \t\t\t\tr=\"|BISECTING\"\n \t\t\tfi\ndiff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh\nindex fd569c8..365a1ba 100755\n--- a/t/t3507-cherry-pick-conflict.sh\n+++ b/t/t3507-cherry-pick-conflict.sh\n@@ -57,7 +57,7 @@ test_expect_success 'advice from failed cherry-pick' \"\n \terror: could not apply \\$picked... picked\n \thint: after resolving the conflicts, mark the corrected paths\n \thint: with 'git add <paths>' or 'git rm <paths>'\n-\thint: and commit the result with 'git commit -c CHERRY_PICK_HEAD'\n+\thint: and commit the result with 'git commit'\n \tEOF\n \ttest_must_fail git cherry-pick picked 2>actual &&\n \ndiff --git a/t/t7509-commit.sh b/t/t7509-commit.sh\nindex 77b6920..b61fd3c 100755\n--- a/t/t7509-commit.sh\n+++ b/t/t7509-commit.sh\n@@ -157,4 +157,33 @@ test_expect_success '--reset-author should be rejected without -c/-C/--amend' '\n \ttest_must_fail git commit -a --reset-author -m done\n '\n \n+test_expect_success 'commit respects CHERRY_PICK_HEAD and MERGE_MSG' '\n+\techo \"cherry-pick 1a\" >>foo &&\n+\ttest_tick &&\n+\tgit commit -am \"cherry-pick 1\" --author=\"Cherry <cherry@pick.er>\" &&\n+\tgit tag cherry-pick-head &&\n+\tgit rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&\n+\techo \"This is a MERGE_MSG\" >.git/MERGE_MSG &&\n+\techo \"cherry-pick 1b\" >>foo &&\n+\ttest_tick &&\n+\tgit commit -a &&\n+\tauthor_header cherry-pick-head >expect &&\n+\tauthor_header HEAD >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo \"This is a MERGE_MSG\" >expect &&\n+\tmessage_body HEAD >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '--reset-author with CHERRY_PICK_HEAD' '\n+\tgit rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&\n+\techo \"cherry-pick 2\" >>foo &&\n+\ttest_tick &&\n+\tgit commit -am \"cherry-pick 2\" --reset-author &&\n+\techo \"author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE\" >expect &&\n+\tauthor_header HEAD >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/wt-status.c b/wt-status.c\nindex 123582b..fbaaf54 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -60,7 +60,7 @@ static void wt_status_print_unmerged_header(struct wt_status *s)\n \tcolor_fprintf_ln(s->fp, c, \"# Unmerged paths:\");\n \tif (!advice_status_hints)\n \t\treturn;\n-\tif (s->in_merge)\n+\tif (s->whence != FROM_COMMIT)\n \t\t;\n \telse if (!s->is_initial)\n \t\tcolor_fprintf_ln(s->fp, c, \"#   (use \\\"git reset %s <file>...\\\" to unstage)\", s->reference);\n@@ -77,7 +77,7 @@ static void wt_status_print_cached_header(struct wt_status *s)\n \tcolor_fprintf_ln(s->fp, c, \"# Changes to be committed:\");\n \tif (!advice_status_hints)\n \t\treturn;\n-\tif (s->in_merge)\n+\tif (s->whence != FROM_COMMIT)\n \t\t; /* NEEDSWORK: use \"git reset --unresolve\"??? */\n \telse if (!s->is_initial)\n \t\tcolor_fprintf_ln(s->fp, c, \"#   (use \\\"git reset %s <file>...\\\" to unstage)\", s->reference);\ndiff --git a/wt-status.h b/wt-status.h\nindex 20b17cf..bf2eb27 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -24,6 +24,12 @@ enum untracked_status_type {\n \tSHOW_ALL_UNTRACKED_FILES\n };\n \n+enum commit_whence {\n+  FROM_COMMIT,\n+  FROM_MERGE,\n+  FROM_CHERRY_PICK\n+};\n+\n struct wt_status_change_data {\n \tint worktree_status;\n \tint index_status;\n@@ -40,7 +46,7 @@ struct wt_status {\n \tconst char **pathspec;\n \tint verbose;\n \tint amend;\n-\tint in_merge;\n+\tenum commit_whence whence;\n \tint nowarn;\n \tint use_color;\n \tint relative_paths;\n-- \n1.7.4.1.28.gd46b3\n"},{"id":"161296","messageId":"AANLkTim8m4uBjn_FJ-SWnARkv8rTiM1SrBTBFeg2R_hd@mail.gmail.com","threadId":"26518","inReplyTo":"1297850903-65038-2-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH 1/2] Introduce CHERRY_PICK_HEAD","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-02-16T11:13:45Z","receivedAt":"2011-02-16T11:13:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Feb 16, 2011 at 5:08 PM, Jay Soffian <jaysoffian@gmail.com> wrote:\n> When a cherry-pick conflicts git advises to use:\n>\n>  $ git commit -c <original commit id>\n>\n> to preserve the original commit message and authorship. Instead, let's\n> record the original commit id in CHERRY_PICK_HEAD and advise to use:\n>\n>  $ git commit -c CHERRY_PICK_HEAD\n\nWouldn't it be more convenient to do \"git cherry-pick --continue\"\ninstead of \"git commit -c CHERRY_PICK_HEAD\"?\n-- \nDuy\n"},{"id":"161311","messageId":"AANLkTike1Xf6+NNs0QJuzLibN8VyHVOTjQuX=zd_mqCe@mail.gmail.com","threadId":"26518","inReplyTo":"AANLkTim8m4uBjn_FJ-SWnARkv8rTiM1SrBTBFeg2R_hd@mail.gmail.com","subject":"Re: [PATCH 1/2] Introduce CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T16:50:31Z","receivedAt":"2011-02-16T16:50:31Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Feb 16, 2011 at 6:13 AM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n> On Wed, Feb 16, 2011 at 5:08 PM, Jay Soffian <jaysoffian@gmail.com> wrote:\n>> When a cherry-pick conflicts git advises to use:\n>>\n>>  $ git commit -c <original commit id>\n>>\n>> to preserve the original commit message and authorship. Instead, let's\n>> record the original commit id in CHERRY_PICK_HEAD and advise to use:\n>>\n>>  $ git commit -c CHERRY_PICK_HEAD\n>\n> Wouldn't it be more convenient to do \"git cherry-pick --continue\"\n> instead of \"git commit -c CHERRY_PICK_HEAD\"?\n\nAs mentioned in the part of the commit message you trimmed away: \"In\nthe next commit, we teach git to handle the '-c CHERRY_PICK_HEAD'\npart\". Now, you may ask, why use \"git commit\" after resolving the\nconflict (a la merge) instead of \"git cherry-pick --continue\" (a la\nrebase).\n\nI addressed this in the previous thread, see\nhttp://article.gmane.org/gmane.comp.version-control.git/166884\n\nj.\n"},{"id":"161314","messageId":"1297876835-70613-1-git-send-email-jaysoffian@gmail.com","threadId":"26518","inReplyTo":"1297850903-65038-2-git-send-email-jaysoffian@gmail.com","subject":"[PATCH v2] Introduce CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T17:20:35Z","receivedAt":"2011-02-16T17:20:35Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"When a cherry-pick conflicts git advises to use:\n\n $ git commit -c <original commit id>\n\nto preserve the original commit message and authorship. Instead, let's\nrecord the original commit id in CHERRY_PICK_HEAD and advise to use:\n\n  $ git commit -c CHERRY_PICK_HEAD\n\nIn the next commit, we teach git to handle the '-c CHERRY_PICK_HEAD'\npart. Note that we record CHERRY_PICK_HEAD even in the case where there\nare no conflicts so that we may use it to communicate authorship to\ncommit; this will then allow us to remove set_author_ident_env from\nrevert.c.\n\nContributions-by: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Jay Soffian <jaysoffian@gmail.com>\n---\nCompared to the original patch, this removes CHERRY_PICK_HEAD when\na conflict occurs during an interactive rebase. Also corrected a minor\ntypo in the commit message. There were no changes to the next patch\nin the series, so I didn't resend it.\n\n Documentation/git-cherry-pick.txt |   19 +++++++++++++++++++\n Documentation/revisions.txt       |    5 ++++-\n branch.c                          |    1 +\n builtin/commit.c                  |    1 +\n builtin/merge.c                   |    7 +++++++\n builtin/revert.c                  |   25 +++++++++++++++++++++++--\n t/t3507-cherry-pick-conflict.sh   |   22 +++++++++++++++++++++-\n 7 files changed, 76 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt\nindex 749d68a..5d85daa 100644\n--- a/Documentation/git-cherry-pick.txt\n+++ b/Documentation/git-cherry-pick.txt\n@@ -16,6 +16,25 @@ Given one or more existing commits, apply the change each one\n introduces, recording a new commit for each.  This requires your\n working tree to be clean (no modifications from the HEAD commit).\n \n+When it is not obvious how to apply a change, the following\n+happens:\n+\n+1. The current branch and `HEAD` pointer stay at the last commit\n+   successfully made.\n+2. The `CHERRY_PICK_HEAD` ref is set to point at the commit that\n+   introduced the change that is difficult to apply.\n+3. Paths in which the change applied cleanly are updated both\n+   in the index file and in your working tree.\n+4. For conflicting paths, the index file records up to three\n+   versions, as described in the \"TRUE MERGE\" section of\n+   linkgit:git-merge[1].  The working tree files will include\n+   a description of the conflict bracketed by the usual\n+   conflict markers `<<<<<<<` and `>>>>>>>`.\n+5. No other modifications are made.\n+\n+See linkgit:git-merge[1] for some hints on resolving such\n+conflicts.\n+\n OPTIONS\n -------\n <commit>...::\ndiff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\nindex 9e92734..04fceee 100644\n--- a/Documentation/revisions.txt\n+++ b/Documentation/revisions.txt\n@@ -25,7 +25,8 @@ blobs contained in a commit.\n   first match in the following rules:\n \n   . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually\n-    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);\n+    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD`, `MERGE_HEAD`\n+    and `CHERRY_PICK_HEAD`);\n \n   . otherwise, `refs/<name>` if exists;\n \n@@ -46,6 +47,8 @@ you can change the tip of the branch back to the state before you ran\n them easily.\n MERGE_HEAD records the commit(s) you are merging into your branch\n when you run 'git merge'.\n+CHERRY_PICK_HEAD records the commit you are cherry-picking\n+when you run 'git cherry-pick'.\n +\n Note that any of the `refs/*` cases above may come either from\n the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.\ndiff --git a/branch.c b/branch.c\nindex 93dc866..dc23e95 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -217,6 +217,7 @@ void create_branch(const char *head,\n \n void remove_branch_state(void)\n {\n+\tunlink(git_path(\"CHERRY_PICK_HEAD\"));\n \tunlink(git_path(\"MERGE_HEAD\"));\n \tunlink(git_path(\"MERGE_RR\"));\n \tunlink(git_path(\"MERGE_MSG\"));\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 03cff5a..0def540 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1424,6 +1424,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tdie(\"cannot update HEAD ref\");\n \t}\n \n+\tunlink(git_path(\"CHERRY_PICK_HEAD\"));\n \tunlink(git_path(\"MERGE_HEAD\"));\n \tunlink(git_path(\"MERGE_MSG\"));\n \tunlink(git_path(\"MERGE_MODE\"));\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 9403747..454dad2 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -971,6 +971,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\telse\n \t\t\tdie(\"You have not concluded your merge (MERGE_HEAD exists).\");\n \t}\n+\tif (file_exists(git_path(\"CHERRY_PICK_HEAD\"))) {\n+\t\tif (advice_resolve_conflict)\n+\t\t\tdie(\"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\\n\"\n+\t\t\t    \"Please, commit your changes before you can merge.\");\n+\t\telse\n+\t\t\tdie(\"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\");\n+\t}\n \tresolve_undo_clear();\n \n \tif (verbosity < 0)\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex dc1b702..88e3b2a 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -248,6 +248,22 @@ static void set_author_ident_env(const char *message)\n \t\t\tsha1_to_hex(commit->object.sha1));\n }\n \n+static void write_cherry_pick_head(void)\n+{\n+\tint fd;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\n+\tstrbuf_addf(&buf, \"%s\\n\", sha1_to_hex(commit->object.sha1));\n+\n+\tfd = open(git_path(\"CHERRY_PICK_HEAD\"), O_WRONLY | O_CREAT, 0666);\n+\tif (fd < 0)\n+\t\tdie_errno(\"Could not open '%s' for writing\",\n+\t\t\t  git_path(\"CHERRY_PICK_HEAD\"));\n+\tif (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))\n+\t\tdie_errno(\"Could not write to '%s'\", git_path(\"CHERRY_PICK_HEAD\"));\n+\tstrbuf_release(&buf);\n+}\n+\n static void advise(const char *advice, ...)\n {\n \tva_list params;\n@@ -263,6 +279,11 @@ static void print_advice(void)\n \n \tif (msg) {\n \t\tfprintf(stderr, \"%s\\n\", msg);\n+\t\t/*\n+\t\t * rebase interactive takes care of the authorship\n+\t\t * when the user invokes rebase --continue\n+\t\t */\n+\t\tunlink(git_path(\"CHERRY_PICK_HEAD\"));\n \t\treturn;\n \t}\n \n@@ -270,8 +291,7 @@ static void print_advice(void)\n \tadvise(\"with 'git add <paths>' or 'git rm <paths>'\");\n \n \tif (action == CHERRY_PICK)\n-\t\tadvise(\"and commit the result with 'git commit -c %s'\",\n-\t\t       find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));\n+\t\tadvise(\"and commit the result with 'git commit -c CHERRY_PICK_HEAD'\");\n }\n \n static void write_message(struct strbuf *msgbuf, const char *filename)\n@@ -504,6 +524,7 @@ static int do_pick_commit(void)\n \t\t\tstrbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));\n \t\t\tstrbuf_addstr(&msgbuf, \")\\n\");\n \t\t}\n+\t\twrite_cherry_pick_head();\n \t}\n \n \tif (!strategy || !strcmp(strategy, \"recursive\") || action == REVERT) {\ndiff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh\nindex 607bf25..fd569c8 100755\n--- a/t/t3507-cherry-pick-conflict.sh\n+++ b/t/t3507-cherry-pick-conflict.sh\n@@ -11,6 +11,12 @@ test_description='test cherry-pick and revert with conflicts\n \n . ./test-lib.sh\n \n+test_cmp_rev () {\n+\tgit rev-parse --verify \"$1\" >expect.rev &&\n+\tgit rev-parse --verify \"$2\" >actual.rev &&\n+\ttest_cmp expect.rev actual.rev\n+}\n+\n test_expect_success setup '\n \n \techo unrelated >unrelated &&\n@@ -51,13 +57,27 @@ test_expect_success 'advice from failed cherry-pick' \"\n \terror: could not apply \\$picked... picked\n \thint: after resolving the conflicts, mark the corrected paths\n \thint: with 'git add <paths>' or 'git rm <paths>'\n-\thint: and commit the result with 'git commit -c \\$picked'\n+\thint: and commit the result with 'git commit -c CHERRY_PICK_HEAD'\n \tEOF\n \ttest_must_fail git cherry-pick picked 2>actual &&\n \n \ttest_cmp expected actual\n \"\n \n+test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\ttest_must_fail git cherry-pick picked &&\n+\n+\ttest_cmp_rev picked CHERRY_PICK_HEAD\n+'\n+\n test_expect_success 'failed cherry-pick produces dirty index' '\n \n \tgit checkout -f initial^0 &&\n-- \n1.7.4.1.28.gb39462\n"},{"id":"161315","messageId":"AANLkTikNHJtWpZuZDKHrUDeGTqqEj-tzR2UbNXp98FOd@mail.gmail.com","threadId":"26518","inReplyTo":"1297876835-70613-1-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH v2] Introduce CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T17:25:21Z","receivedAt":"2011-02-16T17:25:21Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Feb 16, 2011 at 12:20 PM, Jay Soffian <jaysoffian@gmail.com> wrote:\n> @@ -263,6 +279,11 @@ static void print_advice(void)\n>\n>        if (msg) {\n>                fprintf(stderr, \"%s\\n\", msg);\n> +               /*\n> +                * rebase interactive takes care of the authorship\n> +                * when the user invokes rebase --continue\n> +                */\n> +               unlink(git_path(\"CHERRY_PICK_HEAD\"));\n>                return;\n>        }\n>\n>\n\nOops, I amended the comment and then fed the wrong commit to\nformat-patch. That should be:\n\n@@ -263,6 +279,11 @@ static void print_advice(void)\n\n        if (msg) {\n                fprintf(stderr, \"%s\\n\", msg);\n+               /*\n+                * we're in the middle of an interactive rebase, we\n+                * don't want it to look like we're cherry-picking.\n+                */\n+               unlink(git_path(\"CHERRY_PICK_HEAD\"));\n                return;\n        }\n\nLet me know if you want me to resend. (Sorry.)\n\nj.\n"},{"id":"161336","messageId":"7vpqqrit8r.fsf@alter.siamese.dyndns.org","threadId":"26518","inReplyTo":"1297850903-65038-3-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-02-16T21:07:00Z","receivedAt":"2011-02-16T21:07:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> If the user wishes to reset authorship, that must now be done explicitly\n> via --reset-author.\n\nThis is not a new requirement, is it?  Even \"commit -c $that_commit\"\nbefore the previous \"commit -c CHERRY_PICK_HEAD\" does use the original,\nno?\n\n\nI think the changed code is _MUCH_ easier to follow compared to the\nprevious round; the only thing the reader needs to keep in mind is that\nthe most of the change essentially is \"s/in_merge/whence != FROM_COMMIT/\"\nand making that work.\n\n> * We remove a unused import from revert.c\n\nMicronit: s/import/include/.\n\n\n> @@ -766,7 +802,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n>  \n>  \tfclose(fp);\n>  \n> -\tif (!commitable && !in_merge && !allow_empty &&\n> +\tif (!commitable && whence != FROM_MERGE && !allow_empty &&\n>  \t    !(amend && is_a_merge(head_sha1))) {\n>  \t\trun_status(stdout, index_file, prefix, 0, s);\n>  \t\tif (amend)\n\nThe original says that we reject an attempt to record a no-change commit\nwhen the user is making his own commit without an explicit --allow-empty\nrequest.  Should cherry-pick change this?\n\n\"git cherry-pick $a_no_change_commit\" does not cause conflicts but it does\nfail with \"nothing added to commit\".  If you said \"whence == FROM_COMMIT\"\nhere, you would end up allowing \"git commit\" following such a failure to\ncommit without --allow-empty, and that inconsistency is to be avoided\n(note that I didn't check if you leave CHERRY_PICK_HEAD behind to trigger\nthis codepath when this happens).\n\nOn the other hand, when the earlier cherry-pick did fail with conflict,\nbut the resolution ended up to be a no-change commit, you would not\nblindly want to record the result as a no-change commit, either.\n\nSo I think the above is the right thing to do, but we probably need a bit\nof in-code comment to describe why we say \"whence != FROM_MERGE\" here.\n\nThanks.\n"},{"id":"161340","messageId":"AANLkTi=YF51i41St6B=ZpdBYm5MRoMStea+i7TrYTtfF@mail.gmail.com","threadId":"26518","inReplyTo":"7vpqqrit8r.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T21:33:15Z","receivedAt":"2011-02-16T21:33:15Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Feb 16, 2011 at 4:07 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jay Soffian <jaysoffian@gmail.com> writes:\n>\n>> If the user wishes to reset authorship, that must now be done explicitly\n>> via --reset-author.\n>\n> This is not a new requirement, is it?  Even \"commit -c $that_commit\"\n> before the previous \"commit -c CHERRY_PICK_HEAD\" does use the original,\n> no?\n\nIt is a new requirement for when the user does a bare \"commit\" _and_\nCHERRY_PICK_HEAD exists.\n\nNormally a bare \"commit\" creates new authorship, but when\nCHERRY_PICK_HEAD exists, authorship is taken from CHERRY_PICK_HEAD\ncommit unless --reset-author is specified.\n\n> I think the changed code is _MUCH_ easier to follow compared to the\n> previous round; the only thing the reader needs to keep in mind is that\n> the most of the change essentially is \"s/in_merge/whence != FROM_COMMIT/\"\n> and making that work.\n\nI think I was trying to be too clever in the previous round.\n\n>> * We remove a unused import from revert.c\n>\n> Micronit: s/import/include/.\n\nOkay.\n\n> So I think the above is the right thing to do, but we probably need a bit\n> of in-code comment to describe why we say \"whence != FROM_MERGE\" here.\n\nWill do. It took me several tries to understand what that code block\nwas trying to do, so a comment will certainly help future readers.\n\nThanks,\n\nj.\n"},{"id":"161343","messageId":"20110216214236.GC2615@elie","threadId":"26518","inReplyTo":"1297876835-70613-1-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH v2] Introduce CHERRY_PICK_HEAD","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-02-16T21:42:36Z","receivedAt":"2011-02-16T21:42:36Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jay Soffian wrote:\n\n> When a cherry-pick conflicts git advises to use:\n>\n>  $ git commit -c <original commit id>\n>\n> to preserve the original commit message and authorship. Instead, let's\n> record the original commit id in CHERRY_PICK_HEAD and advise to use:\n>\n>   $ git commit -c CHERRY_PICK_HEAD\n>\n> In the next commit, we teach git to handle the '-c CHERRY_PICK_HEAD'\n> part. Note that we record CHERRY_PICK_HEAD even in the case where there\n> are no conflicts so that we may use it to communicate authorship to\n> commit; this will then allow us to remove set_author_ident_env from\n> revert.c.\n\nThis \"In the next commit\" phrasing is dangerous, since a person can\nbuild on top of your first commit at any time. :)  I would say:\n\n\tA later patch will teach \"git commit\" without -c to use\n\tCHERRY_PICK_HEAD to set the authorship automatically. Note\n\tthat[...]\n\n[...]\n> +++ b/builtin/revert.c\n> @@ -263,6 +279,11 @@ static void print_advice(void)\n>  \n>  \tif (msg) {\n>  \t\tfprintf(stderr, \"%s\\n\", msg);\n> +\t\t/*\n> +\t\t * rebase interactive takes care of the authorship\n> +\t\t * when the user invokes rebase --continue\n> +\t\t */\n> +\t\tunlink(git_path(\"CHERRY_PICK_HEAD\"));\n\nNit: GIT_CHERRY_PICK_HELP is not just for rebase --interactive but\nfor arbitrary porcelain that wants to take care of the commit itself\n(see v1.5.4-rc0~106^2~1, revert/cherry-pick: Allow overriding the\nhelp text by the calling Porcelain, 2007-11-28).\n\nThe conservative thing to do is indeed to remove CHERRY_PICK_HEAD in\nthis case, I suppose.  But I'd like to have the CHERRY_PICK_HEAD to\nget the --amend safety when rebasing.  I can send a separate patch\nfor it if you'd like.\n\n> --- a/t/t3507-cherry-pick-conflict.sh\n> +++ b/t/t3507-cherry-pick-conflict.sh\n> @@ -11,6 +11,12 @@ test_description='test cherry-pick and revert with conflicts\n[...]\n> +test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '\n\nSome more tests.  Yes, they are repetitive.  A patch on top to factor\nout the setup into a function might help, but that feels out of scope\nhere.\n\nWith whatever subset of the below looks good,\nReviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n\nThanks.\n---\n t/t3507-cherry-pick-conflict.sh |  116 +++++++++++++++++++++++++++++++++++++++\n 1 files changed, 116 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh\nindex fd569c8..ea52720 100755\n--- a/t/t3507-cherry-pick-conflict.sh\n+++ b/t/t3507-cherry-pick-conflict.sh\n@@ -78,6 +78,122 @@ test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '\n \ttest_cmp_rev picked CHERRY_PICK_HEAD\n '\n \n+test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\tgit cherry-pick base &&\n+\n+\ttest_must_fail git rev-parse --verify CHERRY_PICK_HEAD\n+'\n+\n+test_expect_success 'cherry-pick --no-commit sets CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\tgit cherry-pick --no-commit base &&\n+\n+\ttest_cmp_rev base CHERRY_PICK_HEAD\n+'\n+\n+test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\t(\n+\t\tGIT_CHERRY_PICK_HELP=\"and then do something else\" &&\n+\t\texport GIT_CHERRY_PICK_HELP &&\n+\t\ttest_must_fail git cherry-pick picked\n+\t) &&\n+\n+\ttest_must_fail git rev-parse --verify CHERRY_PICK_HEAD\n+'\n+\n+test_expect_success 'git reset clears CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\ttest_must_fail git cherry-pick picked &&\n+\tgit reset &&\n+\n+\ttest_must_fail git rev-parse --verify CHERRY_PICK_HEAD\n+'\n+\n+test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\ttest_must_fail git cherry-pick picked &&\n+\ttest_must_fail git commit &&\n+\n+\ttest_cmp_rev picked CHERRY_PICK_HEAD\n+'\n+\n+test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\ttest_must_fail git cherry-pick picked &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit update-index --refresh -q &&\n+\ttest_must_fail git diff-index --exit-code HEAD &&\n+\t(\n+\t\tGIT_EDITOR=false &&\n+\t\texport GIT_EDITOR &&\n+\t\ttest_must_fail git commit\n+\t) &&\n+\n+\ttest_cmp_rev picked CHERRY_PICK_HEAD\n+'\n+\n+test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '\n+\n+\tgit checkout -f initial^0 &&\n+\tgit read-tree -u --reset HEAD &&\n+\tgit clean -d -f -f -q -x &&\n+\n+\tgit update-index --refresh &&\n+\tgit diff-index --exit-code HEAD &&\n+\n+\ttest_must_fail git cherry-pick picked &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit commit &&\n+\n+\ttest_must_fail git rev-parse --verify CHERRY_PICK_HEAD\n+'\n+\n test_expect_success 'failed cherry-pick produces dirty index' '\n \n \tgit checkout -f initial^0 &&\n-- \n1.7.4.1\n"},{"id":"161345","messageId":"20110216215541.GD2615@elie","threadId":"26518","inReplyTo":"1297850903-65038-3-git-send-email-jaysoffian@gmail.com","subject":"[PATCH 1.5/2] bash: teach __git_ps1 about CHERRY_PICK_HEAD","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-02-16T21:55:41Z","receivedAt":"2011-02-16T21:55:41Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"From: Jay Soffian <jaysoffian@gmail.com>\n\nMake the git prompt (when enabled) show a CHERRY-PICKING indicator\nwhen we are in the middle of a conflicted cherry-pick, analogous\nto the existing MERGING and BISECTING flags.\n\nSigned-off-by: Jay Soffian <jaysoffian@gmail.com>\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n> * While we're at it, we update git-completion.bash to be\n>   CHERRY_PICK_HEAD aware.\n\nHmm, it seems I don't like this \"while at it\". :)\n\n contrib/completion/git-completion.bash |    2 ++\n 1 files changed, 2 insertions(+), 0 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 893b771..0b0b913 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -246,6 +246,8 @@ __git_ps1 ()\n \t\t\t\tfi\n \t\t\telif [ -f \"$g/MERGE_HEAD\" ]; then\n \t\t\t\tr=\"|MERGING\"\n+\t\t\telif [ -f \"$g/CHERRY_PICK_HEAD\" ]; then\n+\t\t\t\tr=\"|CHERRY-PICKING\"\n \t\t\telif [ -f \"$g/BISECT_LOG\" ]; then\n \t\t\t\tr=\"|BISECTING\"\n \t\t\tfi\n-- \n1.7.4.1\n"},{"id":"161347","messageId":"AANLkTimBExej1mF=4UuTszcSoKy_xnj7bB3BaT5ze2vH@mail.gmail.com","threadId":"26518","inReplyTo":"20110216214236.GC2615@elie","subject":"Re: [PATCH v2] Introduce CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-16T22:13:15Z","receivedAt":"2011-02-16T22:13:15Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Feb 16, 2011 at 4:42 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> Nit: GIT_CHERRY_PICK_HELP is not just for rebase --interactive but\n> for arbitrary porcelain that wants to take care of the commit itself\n> (see v1.5.4-rc0~106^2~1, revert/cherry-pick: Allow overriding the\n> help text by the calling Porcelain, 2007-11-28).\n\nWhat is the arbitrary porcelain you have in mind? :-)\n\n> The conservative thing to do is indeed to remove CHERRY_PICK_HEAD in\n> this case, I suppose.  But I'd like to have the CHERRY_PICK_HEAD to\n> get the --amend safety when rebasing.  I can send a separate patch\n> for it if you'd like.\n\nPlease do, since I'm not really sure what you have in mind. If\nCHERRY_PICK_HEAD is left-behind, it interferes with the eventually\ncommit done by rebase --continue. I suppose we could give commit.c\nsome additional logic to detect when it's being called by rebase\n(setting whence = FROM_REBASE?).\n\nIn the mean time, I'll re-roll with your additional tests and Junio's\nprior feedback.\n\nThanks,\n\nj.\n"},{"id":"161351","messageId":"20110216224349.GE2615@elie","threadId":"26518","inReplyTo":"1297850903-65038-3-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-02-16T22:43:50Z","receivedAt":"2011-02-16T22:43:50Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jay Soffian wrote:\n\n> This change fixes that situation. A bare 'commit' will now take the\n> authorship from CHERRY_PICK_HEAD and the commit message from MERGE_MSG.\n> If the user wishes to reset authorship, that must now be done explicitly\n> via --reset-author.\n\nMight also be worth mentioning that it makes --amend fail in such a\nsituation (a change worth celebrating).\n\n> --- a/builtin/commit.c\n> +++ b/builtin/commit.c\n> @@ -56,8 +56,10 @@ static const char empty_amend_advice[] =\n>  \n>  static unsigned char head_sha1[20];\n>  \n> -static char *use_message_buffer;\n> +static const char *use_message_buffer;\n>  static const char commit_editmsg[] = \"COMMIT_EDITMSG\";\n> +static const char cherry_pick_head[] = \"CHERRY_PICK_HEAD\";\n> +static const char merge_head[] = \"MERGE_HEAD\";\n\nHmm, these variables but not MERGE_MSG, MERGE_MODE, and SQUASH_MSG?\n\n> @@ -68,6 +70,7 @@ static enum {\n>  \n>  static const char *logfile, *force_author;\n>  static const char *template_file;\n> +static const char *author_message, *author_message_buffer;\n\nThat's not a message at all, is it?  On first reading I thought it\nwould be a message about the author.  Maybe a comment can help.\n\n\t/* name and content of commit from which to copy authorship */\n\n> @@ -88,7 +91,8 @@ static enum {\n>  } cleanup_mode;\n>  static char *cleanup_arg;\n>  \n> -static int use_editor = 1, initial_commit, in_merge, include_status = 1;\n> +static enum commit_whence whence;\n> +static int use_editor = 1, initial_commit, include_status = 1;\n\nThe name \"whence\" is not so self-explanatory but I don't have any\nbetter ideas (I probably would have written \"merge_or_cherry_pick\"; we\ncan be glad you came up with something better).\n\n> @@ -163,6 +167,36 @@ static struct option builtin_commit_options[] = {\n>  \tOPT_END()\n>  };\n>  \n> +static void determine_whence(struct wt_status *s)\n> +{\n> +\tif (file_exists(git_path(merge_head)))\n> +\t\twhence = FROM_MERGE;\n\nMicronit: maybe COMMITTING_A_MERGE or COMMIT_DURING_MERGE to avoid\nusing valuable namespace?\n\n> @@ -644,7 +678,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n>  \t * This final case does not modify the template message,\n>  \t * it just sets the argument to the prepare-commit-msg hook.\n>  \t */\n> -\telse if (in_merge)\n> +\telse if (whence == FROM_MERGE)\n>  \t\thook_arg1 = \"merge\";\n\nPerhaps:\n\n\telse if (whence == CHERRY_PICK) {\n\t\thook_arg1 = \"commit\";\n\t\thook_arg2 = author_message;\n\t}\n\n> @@ -694,16 +728,18 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n[...]\n>  \t\t\t\t\"# If this is not correct, please remove the file\\n\"\n>  \t\t\t\t\"#\t%s\\n\"\n>  \t\t\t\t\"# and try again.\\n\"\n>  \t\t\t\t\"#\\n\",\n> +\t\t\t\twhence_s(),\n> +\t\t\t\tgit_path(whence == FROM_MERGE\n> +\t\t\t\t\t ? merge_head\n> +\t\t\t\t\t : cherry_pick_head));\n\nOk.  We probably should move away from having to suggest\n\"rm -f .git/whatever\" in the future (maybe\n\n\tgit update-ref -d %s\n\nis simpler advice?  I dunno).\n\n> @@ -898,6 +934,27 @@ static void handle_untracked_files_arg(struct wt_status *s)\n>  \t\tdie(\"Invalid untracked files mode '%s'\", untracked_files_arg);\n>  }\n>  \n> +static const char *read_commit_message(const char *name) {\n\nNice.  Opening '{' should be in the first column.\n\n> +++ b/builtin/revert.c\n[...]\n> @@ -284,9 +233,7 @@ static void print_advice(void)\n>  \n>  \tadvise(\"after resolving the conflicts, mark the corrected paths\");\n>  \tadvise(\"with 'git add <paths>' or 'git rm <paths>'\");\n> -\n> -\tif (action == CHERRY_PICK)\n> -\t\tadvise(\"and commit the result with 'git commit -c CHERRY_PICK_HEAD'\");\n> +\tadvise(\"and commit the result with 'git commit'\");\n\nHoorah!\n\n> --- a/wt-status.c\n> +++ b/wt-status.c\n> @@ -60,7 +60,7 @@ static void wt_status_print_unmerged_header(struct wt_status *s)\n>  \tcolor_fprintf_ln(s->fp, c, \"# Unmerged paths:\");\n>  \tif (!advice_status_hints)\n>  \t\treturn;\n> -\tif (s->in_merge)\n> +\tif (s->whence != FROM_COMMIT)\n>  \t\t;\n>  \telse if (!s->is_initial)\n>  \t\tcolor_fprintf_ln(s->fp, c, \"#   (use \\\"git reset %s <file>...\\\" to unstage)\", s->reference);\n\nIsn't the advice of using \"git reset -- <paths>\" still good in the\nCHERRY_PICK case?\n\n> @@ -77,7 +77,7 @@ static void wt_status_print_cached_header(struct wt_status *s)\n>  \tcolor_fprintf_ln(s->fp, c, \"# Changes to be committed:\");\n>  \tif (!advice_status_hints)\n>  \t\treturn;\n> -\tif (s->in_merge)\n> +\tif (s->whence != FROM_COMMIT)\n>  \t\t; /* NEEDSWORK: use \"git reset --unresolve\"??? */\n\nLikewise here.\n\n> --- a/wt-status.h\n> +++ b/wt-status.h\n> @@ -24,6 +24,12 @@ enum untracked_status_type {\n>  \tSHOW_ALL_UNTRACKED_FILES\n>  };\n>  \n> +enum commit_whence {\n> +  FROM_COMMIT,\n> +  FROM_MERGE,\n> +  FROM_CHERRY_PICK\n> +};\n\nStyle: please use tabs to indent.\n\n> @@ -40,7 +46,7 @@ struct wt_status {\n>  \tconst char **pathspec;\n>  \tint verbose;\n>  \tint amend;\n> -\tint in_merge;\n> +\tenum commit_whence whence;\n\nMight benefit from a comment.\n\n\t/* whether a merge or cherry-pick is in progress */\n\tenum commit_whence whence;\n\nThanks, very readable.\n"},{"id":"161352","messageId":"7vpqqrh9xo.fsf@alter.siamese.dyndns.org","threadId":"26518","inReplyTo":"20110216215541.GD2615@elie","subject":"Re: [PATCH 1.5/2] bash: teach __git_ps1 about CHERRY_PICK_HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-02-16T22:49:23Z","receivedAt":"2011-02-16T22:49:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> Hmm, it seems I don't like this \"while at it\". :)\n\nI don't either.  The series will be re-rolled so I don't have to pick this\nup myself, yes?\n"},{"id":"161354","messageId":"20110216230250.GF2615@elie","threadId":"26518","inReplyTo":"AANLkTimBExej1mF=4UuTszcSoKy_xnj7bB3BaT5ze2vH@mail.gmail.com","subject":"Re: [PATCH v2] Introduce CHERRY_PICK_HEAD","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-02-16T23:02:50Z","receivedAt":"2011-02-16T23:02:50Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jay Soffian wrote:\n> On Wed, Feb 16, 2011 at 4:42 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n\n>> Nit: GIT_CHERRY_PICK_HELP is not just for rebase --interactive but\n>> for arbitrary porcelain that wants to take care of the commit itself\n>> (see v1.5.4-rc0~106^2~1, revert/cherry-pick: Allow overriding the\n>> help text by the calling Porcelain, 2007-11-28).\n>\n> What is the arbitrary porcelain you have in mind? :-)\n\ngit sequencer, for example.  Or any out-of-tree tool that is using\ncherry-pick to move around commits and wants to know where they end\nup.\n\n>> The conservative thing to do is indeed to remove CHERRY_PICK_HEAD in\n>> this case, I suppose.  But I'd like to have the CHERRY_PICK_HEAD to\n>> get the --amend safety when rebasing.  I can send a separate patch\n>> for it if you'd like.\n>\n> Please do, since I'm not really sure what you have in mind. If\n> CHERRY_PICK_HEAD is left-behind, it interferes with the eventually\n> commit done by rebase --continue.\n\nWait, does this mean that -c/-C/--amend/CHERRY_PICK_HEAD overrides\nGIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE?\n\n*checks*\n\nYes, it does.  The behavior is carried over from v0.99~185\n(git-commit-script: get commit message from an existing one,\n2005-06-25), but imho it is wrong.\n\nDoes this seem worth fixing?\nJonathan\n"},{"id":"161359","messageId":"AANLkTinUec=HJVpGL_3v=4tvkGiMiNT1QLzWsChF411Z@mail.gmail.com","threadId":"26518","inReplyTo":"20110216224349.GE2615@elie","subject":"Re: [PATCH 2/2] Teach commit about CHERRY_PICK_HEAD","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-17T00:05:59Z","receivedAt":"2011-02-17T00:05:59Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Feb 16, 2011 at 5:43 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> Might also be worth mentioning that it makes --amend fail in such a\n> situation (a change worth celebrating).\n\nNever made that particular mistake myself, but okay.\n\n>> --- a/builtin/commit.c\n>> +++ b/builtin/commit.c\n>> @@ -56,8 +56,10 @@ static const char empty_amend_advice[] =\n>>\n>>  static unsigned char head_sha1[20];\n>>\n>> -static char *use_message_buffer;\n>> +static const char *use_message_buffer;\n>>  static const char commit_editmsg[] = \"COMMIT_EDITMSG\";\n>> +static const char cherry_pick_head[] = \"CHERRY_PICK_HEAD\";\n>> +static const char merge_head[] = \"MERGE_HEAD\";\n>\n> Hmm, these variables but not MERGE_MSG, MERGE_MODE, and SQUASH_MSG?\n\nI cleaned up the ones my patch touched. Cleaning up the rest of\ncommit.c was out of my purview. :-)\n\nI'll clean them up to be consistent, but I'll do it as a separate\npatch (before this one).\n\n>> @@ -68,6 +70,7 @@ static enum {\n>>\n>>  static const char *logfile, *force_author;\n>>  static const char *template_file;\n>> +static const char *author_message, *author_message_buffer;\n>\n> That's not a message at all, is it?  On first reading I thought it\n> would be a message about the author.  Maybe a comment can help.\n>\n>        /* name and content of commit from which to copy authorship */\n\nThe name is consistent with the other similar purpose variables:\nuse_message, edit_message, squash_message, fixup_message, which all\ntake a committish and aren't actually messages. None of those others\nhave comments, but it's obvious in context how they are used.\n\n>> @@ -88,7 +91,8 @@ static enum {\n>>  } cleanup_mode;\n>>  static char *cleanup_arg;\n>>\n>> -static int use_editor = 1, initial_commit, in_merge, include_status = 1;\n>> +static enum commit_whence whence;\n>> +static int use_editor = 1, initial_commit, include_status = 1;\n>\n> The name \"whence\" is not so self-explanatory but I don't have any\n> better ideas (I probably would have written \"merge_or_cherry_pick\"; we\n> can be glad you came up with something better).\n\nRespectfully disagree. Whence means \"from where something came\" as in\n\"from where did this commit we're about to make originate?\" and I\nintentionally didn't use _ORIGIN as \"origin\" has another meaning\nalready in git context.\n\n>> @@ -163,6 +167,36 @@ static struct option builtin_commit_options[] = {\n>>       OPT_END()\n>>  };\n>>\n>> +static void determine_whence(struct wt_status *s)\n>> +{\n>> +     if (file_exists(git_path(merge_head)))\n>> +             whence = FROM_MERGE;\n>\n> Micronit: maybe COMMITTING_A_MERGE or COMMIT_DURING_MERGE to avoid\n> using valuable namespace?\n\nRespectfully disagree.\n\n> Perhaps:\n>\n>        else if (whence == CHERRY_PICK) {\n>                hook_arg1 = \"commit\";\n>                hook_arg2 = author_message;\n>        }\n\nPerhaps.\n\n> Ok.  We probably should move away from having to suggest\n> \"rm -f .git/whatever\" in the future (maybe\n>\n>        git update-ref -d %s\n>\n> is simpler advice?  I dunno).\n\nOut of scope for this patch. :-)\n\n> Nice.  Opening '{' should be in the first column.\n\nGood catch.\n\n> Isn't the advice of using \"git reset -- <paths>\" still good in the\n> CHERRY_PICK case?\n\nI don't know. I couldn't make up my mind. If it's a conflicted path\nyou've edited in the working copy, then the advice should be \"checkout\n--merge\". I think. Maybe. I don't find wt-status.c to be very much\nfun, so I punted.\n\n>> -     if (s->in_merge)\n>> +     if (s->whence != FROM_COMMIT)\n>>               ; /* NEEDSWORK: use \"git reset --unresolve\"??? */\n>\n> Likewise here.\n\nCheckout that NEEDSWORK. Someone should get on that. :-)\n\n> Style: please use tabs to indent.\n\nWho ate my tabs?\n\n> Might benefit from a comment.\n>\n>        /* whether a merge or cherry-pick is in progress */\n>        enum commit_whence whence;\n\nAgreed.\n\n> Thanks, very readable.\n\nGood feedback.\n\nj.\n"},{"id":"161443","messageId":"7vpqqqbfgr.fsf@alter.siamese.dyndns.org","threadId":"26518","inReplyTo":"20110216230250.GF2615@elie","subject":"Re: [PATCH v2] Introduce CHERRY_PICK_HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-02-17T19:58:44Z","receivedAt":"2011-02-17T19:58:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> Wait, does this mean that -c/-C/--amend/CHERRY_PICK_HEAD overrides\n> GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE?\n>\n> *checks*\n>\n> Yes, it does.  The behavior is carried over from v0.99~185\n> (git-commit-script: get commit message from an existing one,\n> 2005-06-25), but imho it is wrong.\n\nHmph, -c/-C/--amend is like giving the identity with --author from the\ncommand line so overriding the values from the environment variables\nsounds like the right thing to do.\n\nWhere am I confused?\n"},{"id":"161463","messageId":"20110217221645.GA10007@elie","threadId":"26518","inReplyTo":"7vpqqqbfgr.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] Introduce CHERRY_PICK_HEAD","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-02-17T22:16:45Z","receivedAt":"2011-02-17T22:16:45Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Junio C Hamano wrote:\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>> Wait, does this mean that -c/-C/--amend/CHERRY_PICK_HEAD overrides\n>> GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE?\n[...]\n> Hmph, -c/-C/--amend is like giving the identity with --author from the\n> command line so overriding the values from the environment variables\n> sounds like the right thing to do.\n\nGood point.  There are two principles at work here:\n\n - options with more specific effect override more general ones\n - options on the command line override the environment\n\nOn second thought, the latter does seem more relevant (though it need\nnot apply to CHERRY_PICK_HEAD).\n\nThanks for a sanity check.\nJonathan\n"}]}