{"thread":{"id":"58646","subject":"[PATCH] {merge,fmt-merge-msg}: Add the --from-name argument","startedAt":"2022-10-18T18:37:00Z","lastAt":"2022-10-18T18:37:00Z","messageCount":1,"participants":["Palmer Dabbelt"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"465215","messageId":"20221018183656.32185-1-palmer@rivosinc.com","threadId":"58646","inReplyTo":null,"subject":"[PATCH] {merge,fmt-merge-msg}: Add the --from-name argument","fromName":"Palmer Dabbelt","fromEmail":"palmer@rivosinc.com","sentAt":"2022-10-18T18:36:56Z","receivedAt":"2022-10-18T18:37:00Z","isPatch":true,"sender":{"key":"palmer@rivosinc.com","avatar":null},"body":"We have a \"--into-name\" to fake one side of the merge message, but\nthere's no way to fake the from branch that's being merged.  The\nspecific case I'm running into is \"b4 shazam -M\" with shortlogs enabled,\nwhich ends up putting a \"/tmp/tmp.XXXXXX\" as the from branch in the\nshortlog (the title is already overriden by b4).\n\nSigned-off-by: Palmer Dabbelt <palmer@rivosinc.com>\n\n---\n\nI saw tests were required by the patch submission docs, but I haven't\nwritten any.  That's both because I don't know how to do so (I haven't\ndone much hacking on git), and because I'm not sure this is useful\nenough for other people to warrant taking upstream.  Happy to do so, but\nfigured I'd send this along this as-is to start.\n---\n Documentation/git-fmt-merge-msg.txt |  4 ++\n Documentation/git-merge.txt         |  5 ++\n builtin/fmt-merge-msg.c             |  4 ++\n builtin/merge.c                     |  4 ++\n fmt-merge-msg.c                     | 89 ++++++++++++++++-------------\n fmt-merge-msg.h                     |  1 +\n 6 files changed, 66 insertions(+), 41 deletions(-)\n\ndiff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt\nindex 6f28812f38..1d8ea40216 100644\n--- a/Documentation/git-fmt-merge-msg.txt\n+++ b/Documentation/git-fmt-merge-msg.txt\n@@ -48,6 +48,10 @@ OPTIONS\n \tPrepare the merge message as if merging to the branch `<branch>`,\n \tinstead of the name of the real branch to which the merge is made.\n \n+--from-name <branch>::\n+\tPrepare the merge message as if merging from the branch `<branch>`,\n+\tinstead of the name of the real branch from which the merge is made.\n+\n -F <file>::\n --file <file>::\n \tTake the list of merged objects from <file> instead of\ndiff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt\nindex 2d6a1391c8..e9d02b8a6f 100644\n--- a/Documentation/git-merge.txt\n+++ b/Documentation/git-merge.txt\n@@ -82,6 +82,11 @@ invocations. The automated message can include the branch description.\n \t`<branch>`, instead of the name of the real branch to which\n \tthe merge is made.\n \n+--from-name <branch>::\n+\tPrepare the default merge message as if merging from the branch\n+\t`<branch>`, instead of the name of the real branch from which\n+\tthe merge is made.\n+\n -F <file>::\n --file=<file>::\n \tRead the commit message to be used for the merge commit (in\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex 8d8fd393f8..f0ea815162 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -13,6 +13,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \tconst char *inpath = NULL;\n \tconst char *message = NULL;\n \tchar *into_name = NULL;\n+\tchar *from_name = NULL;\n \tint shortlog_len = -1;\n \tstruct option options[] = {\n \t\t{ OPTION_INTEGER, 0, \"log\", &shortlog_len, N_(\"n\"),\n@@ -26,6 +27,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \t\t\tN_(\"use <text> as start of message\")),\n \t\tOPT_STRING(0, \"into-name\", &into_name, N_(\"name\"),\n \t\t\t   N_(\"use <name> instead of the real target branch\")),\n+\t\tOPT_STRING(0, \"from-name\", &from_name, N_(\"name\"),\n+\t\t\t   N_(\"use <name> instead of the real source branch\")),\n \t\tOPT_FILENAME('F', \"file\", &inpath, N_(\"file to read from\")),\n \t\tOPT_END()\n \t};\n@@ -60,6 +63,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \topts.credit_people = 1;\n \topts.shortlog_len = shortlog_len;\n \topts.into_name = into_name;\n+\topts.from_name = from_name;\n \n \tret = fmt_merge_msg(&input, &output, &opts);\n \tif (ret)\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 5900b81729..921aa39c50 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -88,6 +88,7 @@ static const char *sign_commit;\n static int autostash;\n static int no_verify;\n static char *into_name;\n+static char *from_name;\n \n static struct strategy all_strategy[] = {\n \t{ \"recursive\",  NO_TRIVIAL },\n@@ -289,6 +290,8 @@ static struct option builtin_merge_options[] = {\n \t\tNULL, 0, option_read_message },\n \tOPT_STRING(0, \"into-name\", &into_name, N_(\"name\"),\n \t\t   N_(\"use <name> instead of the real target\")),\n+\tOPT_STRING(0, \"from-name\", &from_name, N_(\"name\"),\n+\t\t   N_(\"use <name> instead of the real source\")),\n \tOPT__VERBOSITY(&verbosity),\n \tOPT_BOOL(0, \"abort\", &abort_current_merge,\n \t\tN_(\"abort the current in-progress merge\")),\n@@ -1144,6 +1147,7 @@ static void prepare_merge_message(struct strbuf *merge_names, struct strbuf *mer\n \topts.shortlog_len = shortlog_len;\n \topts.credit_people = (0 < option_edit);\n \topts.into_name = into_name;\n+\topts.from_name = from_name;\n \n \tfmt_merge_msg(merge_names, merge_msg, &opts);\n \tif (merge_msg->len)\ndiff --git a/fmt-merge-msg.c b/fmt-merge-msg.c\nindex f48f44f9cd..5d94ce9214 100644\n--- a/fmt-merge-msg.c\n+++ b/fmt-merge-msg.c\n@@ -353,6 +353,7 @@ static void shortlog(const char *name,\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst struct object_id *oid = &origin_data->oid;\n \tint limit = opts->shortlog_len;\n+\tconst char *from_name = opts->from_name ? opts->from_name : name;\n \n \tbranch = deref_tag(the_repository, parse_object(the_repository, oid),\n \t\t\t   oid_to_hex(oid),\n@@ -398,12 +399,12 @@ static void shortlog(const char *name,\n \tif (opts->credit_people)\n \t\tadd_people_info(out, &authors, &committers);\n \tif (count > limit)\n-\t\tstrbuf_addf(out, \"\\n* %s: (%d commits)\\n\", name, count);\n+\t\tstrbuf_addf(out, \"\\n* %s: (%d commits)\\n\", from_name, count);\n \telse\n-\t\tstrbuf_addf(out, \"\\n* %s:\\n\", name);\n+\t\tstrbuf_addf(out, \"\\n* %s:\\n\", from_name);\n \n \tif (origin_data->is_local_branch && use_branch_desc)\n-\t\tadd_branch_desc(out, name);\n+\t\tadd_branch_desc(out, from_name);\n \n \tfor (i = 0; i < subjects.nr; i++)\n \t\tif (i >= limit)\n@@ -441,51 +442,57 @@ static int dest_suppressed(const char *dest_branch)\n }\n \n static void fmt_merge_msg_title(struct strbuf *out,\n-\t\t\t\tconst char *current_branch)\n+\t\t\t\tconst char *current_branch,\n+\t\t\t\tconst char *into_branch)\n {\n \tint i = 0;\n \tchar *sep = \"\";\n \n \tstrbuf_addstr(out, \"Merge \");\n-\tfor (i = 0; i < srcs.nr; i++) {\n-\t\tstruct src_data *src_data = srcs.items[i].util;\n-\t\tconst char *subsep = \"\";\n \n-\t\tstrbuf_addstr(out, sep);\n-\t\tsep = \"; \";\n+\tif (into_branch) {\n+\t\tstrbuf_addstr(out, into_branch);\n+\t} else {\n+\t\tfor (i = 0; i < srcs.nr; i++) {\n+\t\t\tstruct src_data *src_data = srcs.items[i].util;\n+\t\t\tconst char *subsep = \"\";\n \n-\t\tif (src_data->head_status == 1) {\n-\t\t\tstrbuf_addstr(out, srcs.items[i].string);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (src_data->head_status == 3) {\n-\t\t\tsubsep = \", \";\n-\t\t\tstrbuf_addstr(out, \"HEAD\");\n-\t\t}\n-\t\tif (src_data->branch.nr) {\n-\t\t\tstrbuf_addstr(out, subsep);\n-\t\t\tsubsep = \", \";\n-\t\t\tprint_joined(\"branch \", \"branches \", &src_data->branch,\n-\t\t\t\t\tout);\n-\t\t}\n-\t\tif (src_data->r_branch.nr) {\n-\t\t\tstrbuf_addstr(out, subsep);\n-\t\t\tsubsep = \", \";\n-\t\t\tprint_joined(\"remote-tracking branch \", \"remote-tracking branches \",\n-\t\t\t\t\t&src_data->r_branch, out);\n-\t\t}\n-\t\tif (src_data->tag.nr) {\n-\t\t\tstrbuf_addstr(out, subsep);\n-\t\t\tsubsep = \", \";\n-\t\t\tprint_joined(\"tag \", \"tags \", &src_data->tag, out);\n-\t\t}\n-\t\tif (src_data->generic.nr) {\n-\t\t\tstrbuf_addstr(out, subsep);\n-\t\t\tprint_joined(\"commit \", \"commits \", &src_data->generic,\n-\t\t\t\t\tout);\n+\t\t\tstrbuf_addstr(out, sep);\n+\t\t\tsep = \"; \";\n+\n+\t\t\tif (src_data->head_status == 1) {\n+\t\t\t\tstrbuf_addstr(out, srcs.items[i].string);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (src_data->head_status == 3) {\n+\t\t\t\tsubsep = \", \";\n+\t\t\t\tstrbuf_addstr(out, \"HEAD\");\n+\t\t\t}\n+\t\t\tif (src_data->branch.nr) {\n+\t\t\t\tstrbuf_addstr(out, subsep);\n+\t\t\t\tsubsep = \", \";\n+\t\t\t\tprint_joined(\"branch \", \"branches \", &src_data->branch,\n+\t\t\t\t\t\tout);\n+\t\t\t}\n+\t\t\tif (src_data->r_branch.nr) {\n+\t\t\t\tstrbuf_addstr(out, subsep);\n+\t\t\t\tsubsep = \", \";\n+\t\t\t\tprint_joined(\"remote-tracking branch \", \"remote-tracking branches \",\n+\t\t\t\t\t\t&src_data->r_branch, out);\n+\t\t\t}\n+\t\t\tif (src_data->tag.nr) {\n+\t\t\t\tstrbuf_addstr(out, subsep);\n+\t\t\t\tsubsep = \", \";\n+\t\t\t\tprint_joined(\"tag \", \"tags \", &src_data->tag, out);\n+\t\t\t}\n+\t\t\tif (src_data->generic.nr) {\n+\t\t\t\tstrbuf_addstr(out, subsep);\n+\t\t\t\tprint_joined(\"commit \", \"commits \", &src_data->generic,\n+\t\t\t\t\t\tout);\n+\t\t\t}\n+\t\t\tif (strcmp(\".\", srcs.items[i].string))\n+\t\t\t\tstrbuf_addf(out, \" of %s\", srcs.items[i].string);\n \t\t}\n-\t\tif (strcmp(\".\", srcs.items[i].string))\n-\t\t\tstrbuf_addf(out, \" of %s\", srcs.items[i].string);\n \t}\n \n \tif (!dest_suppressed(current_branch))\n@@ -678,7 +685,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n \t}\n \n \tif (opts->add_title && srcs.nr)\n-\t\tfmt_merge_msg_title(out, current_branch);\n+\t\tfmt_merge_msg_title(out, current_branch, opts->from_name);\n \n \tif (origins.nr)\n \t\tfmt_merge_msg_sigs(out);\ndiff --git a/fmt-merge-msg.h b/fmt-merge-msg.h\nindex 99054042dc..fb3d93a317 100644\n--- a/fmt-merge-msg.h\n+++ b/fmt-merge-msg.h\n@@ -10,6 +10,7 @@ struct fmt_merge_msg_opts {\n \t\tcredit_people:1;\n \tint shortlog_len;\n \tconst char *into_name;\n+\tconst char *from_name;\n };\n \n extern int merge_log_config;\n-- \n2.38.0\n\n"}]}