{"thread":{"id":"65248","subject":"[PATCH 1/7] pretty.c: better die message %(count) and %(total)","startedAt":"2026-03-14T23:21:00Z","lastAt":"2026-03-27T16:47:29Z","messageCount":42,"participants":["Mirko Faina","Kristoffer Haugsbakk","Junio C Hamano","Phillip Wood","D. Ben Knoble"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"538999","messageId":"cover.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":null,"subject":"[PATCH 0/7] improve \"git format-patch --commit-list-format\"","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:43Z","receivedAt":"2026-03-14T23:21:00Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"This series aims to improve the --commit-list-format (former\n--cover-letter-format) option for format-patch by improving a bit the\nuser interaction with the option (and its configuration variable\ncounterpart), removing the ability to use the configuration variable in\nan ambiguous way (which also causes problems when interacting with it\nthrough the cli interface) and introducing a new format preset.\n\nThis series is based on top of 67006b9db8 (The 15th batch, 2026-03-12)\nwith the following series merged into it:\n  - mf/format-patch-cover-letter-format at 51ed9f7e72 (docs: add usage\n\tfor the cover-letter fmt feature, 2026-03-07)\n\n[1/7] pretty.c: better die message %(count) and %(total) (Mirko Faina)\n[2/7] format-patch: refactor generate_commit_list_cover (Mirko Faina)\n[3/7] format-patch: rename --cover-letter-format option (Mirko Faina)\n[4/7] format.commitListFormat: strip meaning from empty (Mirko Faina)\n[5/7] format-patch: wrap generate_commit_list_cover() (Mirko Faina)\n[6/7] format-patch: add preset for --commit-list-format (Mirko Faina)\n[7/7] format-patch: --commit-list-format without prefix (Mirko Faina)\n\n Documentation/config/format.adoc    |  2 +-\n Documentation/git-format-patch.adoc | 19 ++++----\n builtin/log.c                       | 35 +++++++-------\n pretty.c                            |  4 +-\n t/t4014-format-patch.sh             | 72 +++++++++++++++++++----------\n t/t9902-completion.sh               |  1 -\n 6 files changed, 80 insertions(+), 53 deletions(-)\n\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"538995","messageId":"f71d15476ac857550108347ef1664bf9cd9e174d.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH 1/7] pretty.c: better die message %(count) and %(total)","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:44Z","receivedAt":"2026-03-14T23:21:01Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Improve die messages for commands that do not support %(count) and\n%(total)\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n pretty.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 74673714c8..814803980b 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1551,7 +1551,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \n \tif (starts_with(placeholder, \"(count)\")) {\n \t\tif (!c->pretty_ctx->rev)\n-\t\t\tdie(_(\"this format specifier can't be used with this command\"));\n+\t\t\tdie(_(\"%s is not supported by this command\"), \"%(count)\");\n \t\tstrbuf_addf(sb, \"%0*d\", decimal_width(c->pretty_ctx->rev->total),\n \t\t\t    c->pretty_ctx->rev->nr);\n \t\treturn 7;\n@@ -1559,7 +1559,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \n \tif (starts_with(placeholder, \"(total)\")) {\n \t\tif (!c->pretty_ctx->rev)\n-\t\t\tdie(_(\"this format specifier can't be used with this command\"));\n+\t\t\tdie(_(\"%s is not supported by this command\"), \"%(total)\");\n \t\tstrbuf_addf(sb, \"%d\", c->pretty_ctx->rev->total);\n \t\treturn 7;\n \t}\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"538996","messageId":"f8d1359eaa1c05d76b3dcce7596e60f48f577b63.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH 3/7] format-patch: rename --cover-letter-format option","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:46Z","receivedAt":"2026-03-14T23:21:01Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"To align the name of the configuration variable and the name of the\ncommand line option, either one should change name. By changing the name\nof the option we get the added benefit of having --cover-<TAB> expand to\n--cover-letter without ambiguity.\n\nIf the user gives the --cover-letter-format option it would be\nreasonable to expect that the user wants to generate the cover letter\ndespite not giving --cover-letter.\n\nRename --cover-letter-format to --commit-list-format and make it imply\n--cover-letter unless --no-cover-letter is given.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/git-format-patch.adoc | 17 ++++++------\n builtin/log.c                       |  4 ++-\n t/t4014-format-patch.sh             | 41 +++++++++++++++--------------\n t/t9902-completion.sh               |  1 -\n 4 files changed, 32 insertions(+), 31 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 31fa492335..45ca72e670 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -24,7 +24,7 @@ SYNOPSIS\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n-\t\t   [--cover-letter-format=<format-spec>]\n+\t\t   [--commit-list-format=<format-spec>]\n \t\t   [--[no-]encode-email-headers]\n \t\t   [--no-notes | --notes[=<ref>]]\n \t\t   [--interdiff=<previous>]\n@@ -323,16 +323,15 @@ feeding the result to `git send-email`.\n \tcontaining the branch description, shortlog and the overall diffstat.  You can\n \tfill in a description in the file before sending it out.\n \n---cover-letter-format=<format-spec>::\n-\tSpecify the format in which to generate the commit list of the\n-\tpatch series. This option is available if the user wants to use\n-\tan alternative to the default `shortlog` format. The accepted\n-\tvalues for format-spec are \"shortlog\" or a format string\n-\tprefixed with `log:`.\n+--commit-list-format=<format-spec>::\n+\tSpecify the format in which to generate the commit list of the patch\n+\tseries. The accepted values for format-spec are \"shortlog\" or a format\n+\tstring prefixed with `log:`.\n \te.g. `log: %s (%an)`\n-\tIf defined, defaults to the `format.commitListFormat` configuration\n+\tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\n-\tThis option is relevant only if a cover letter is generated.\n+\tThis option implies the use of `--cover-letter` unless\n+\t`--no-cover-letter` is given.\n \n --encode-email-headers::\n --no-encode-email-headers::\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 997bdd608e..a7f129d583 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2014,7 +2014,7 @@ int cmd_format_patch(int argc,\n \t\t\t    N_(\"print patches to standard out\")),\n \t\tOPT_BOOL(0, \"cover-letter\", &cover_letter,\n \t\t\t    N_(\"generate a cover letter\")),\n-\t\tOPT_STRING(0, \"cover-letter-format\", &cover_letter_fmt, N_(\"format-spec\"),\n+\t\tOPT_STRING(0, \"commit-list-format\", &cover_letter_fmt, N_(\"format-spec\"),\n \t\t\t    N_(\"format spec used for the commit list in the cover letter\")),\n \t\tOPT_BOOL(0, \"numbered-files\", &just_numbers,\n \t\t\t    N_(\"use simple number sequence for output file names\")),\n@@ -2358,6 +2358,8 @@ int cmd_format_patch(int argc,\n \t\tcover_letter_fmt = cfg.fmt_cover_letter_commit_list;\n \t\tif (!cover_letter_fmt)\n \t\t\tcover_letter_fmt = \"shortlog\";\n+\t} else if (cover_letter == -1) {\n+\t\tcover_letter = 1;\n \t}\n \n \tif (cover_letter == -1) {\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7c67bdf922..d2a775f78d 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -383,49 +383,50 @@ test_expect_success 'filename limit applies only to basename' '\n test_expect_success 'cover letter with subject, author and count' '\n \trm -rf patches &&\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter \\\n-\t--cover-letter-format=\"log:[%(count)/%(total)] %s (%an)\" -o patches HEAD~1 &&\n-\tgrep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %s (%an)\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n-test_expected_success 'cover letter with author and count' '\n+test_expect_success 'cover letter with author and count' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter \\\n-\t--cover-letter-format=\"log:[%(count)/%(total)] %an\" -o patches HEAD~1 &&\n-\tgrep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %an\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch\n '\n \n test_expect_success 'cover letter shortlog' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf expect patches result test_file\" &&\n+\tcat >expect <<-\"EOF\" &&\n+\tA U Thor (1):\n+\t  This is a subject\n+\tEOF\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter --cover-letter-format=shortlog \\\n-\t-o patches HEAD~1 &&\n-\tsed -n -e \"/^A U Thor/p;\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=shortlog -o patches HEAD~1 &&\n+\tgrep -E -A 1 \"^A U Thor \\([[:digit:]]+\\):$\" patches/0000-cover-letter.patch >result &&\n+\tcat result &&\n+\ttest_cmp expect result\n '\n \n-test_expect_success 'cover letter no format' '\n+test_expect_success 'no cover letter but with format specified' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches result test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter -o patches HEAD~1 &&\n-\tsed -n -e \"/^A U Thor/p;\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --no-cover-letter --commit-list-format=\"[%(count)] %s\" -o patches HEAD~1 &&\n+\ttest_path_is_missing patches/0000-cover-letter.patch\n '\n \n test_expect_success 'cover letter config with count, subject and author' '\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 35e20b5351..2f9a597ec7 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -2775,7 +2775,6 @@ test_expect_success PERL 'send-email' '\n \ttest_completion \"git send-email --cov\" <<-\\EOF &&\n \t--cover-from-description=Z\n \t--cover-letter Z\n-\t--cover-letter-format=Z\n \tEOF\n \ttest_completion \"git send-email --val\" <<-\\EOF &&\n \t--validate Z\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"538998","messageId":"086cdfd57206735ed90416e6859ea0067172d708.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH 2/7] format-patch: refactor generate_commit_list_cover","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:45Z","receivedAt":"2026-03-14T23:21:01Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Refactor for readability and remove unnecessary initialization.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c | 7 +++----\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 716ebc2701..997bdd608e 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1376,12 +1376,11 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \tstruct pretty_print_context ctx = {0};\n \tstruct rev_info rev = REV_INFO_INIT;\n \n-\tstrbuf_init(&commit_line, 0);\n \trev.total = n;\n \tctx.rev = &rev;\n-\tfor (int i = n - 1; i >= 0; i--) {\n-\t\trev.nr = n - i;\n-\t\trepo_format_commit_message(the_repository, list[i], format,\n+\tfor (int i = 1; i <= n; i++) {\n+\t\trev.nr = i;\n+\t\trepo_format_commit_message(the_repository, list[n - i], format,\n \t\t\t\t&commit_line, &ctx);\n \t\tfprintf(cover_file, \"%s\\n\", commit_line.buf);\n \t\tstrbuf_reset(&commit_line);\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"538997","messageId":"1eb2b76eebe8aa7b876c8aaceba4241ccd81ba4f.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH 4/7] format.commitListFormat: strip meaning from empty","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:47Z","receivedAt":"2026-03-14T23:21:02Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"The configuration variable format.commitListFormat allows for an empty\nvalue. This is unusual and can create issues when interacting with this\nconfiguration variable through the cli interface.\n\nStrip meaning to format.commitListFormat with an empty value.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c           | 11 +----------\n t/t4014-format-patch.sh | 11 -----------\n 2 files changed, 1 insertion(+), 21 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex a7f129d583..47126f9064 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1055,17 +1055,8 @@ static int git_format_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \tif (!strcmp(var, \"format.commitlistformat\")) {\n-\t\tstruct strbuf tmp = STRBUF_INIT;\n-\t\tstrbuf_init(&tmp, 0);\n-\t\tif (value)\n-\t\t\tstrbuf_addstr(&tmp, value);\n-\t\telse\n-\t\t\tstrbuf_addstr(&tmp, \"log:[%(count)/%(total)] %s\");\n-\n \t\tFREE_AND_NULL(cfg->fmt_cover_letter_commit_list);\n-\t\tgit_config_string(&cfg->fmt_cover_letter_commit_list, var, tmp.buf);\n-\t\tstrbuf_release(&tmp);\n-\t\treturn 0;\n+\t\treturn git_config_string(&cfg->fmt_cover_letter_commit_list, var, value);\n \t}\n \tif (!strcmp(var, \"format.outputdirectory\")) {\n \t\tFREE_AND_NULL(cfg->config_output_directory);\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex d2a775f78d..ca37f40a6a 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -451,17 +451,6 @@ test_expect_success 'cover letter config with count and author' '\n \ttest_line_count = 2 result\n '\n \n-test_expect_success 'cover letter config commitlistformat set but no format' '\n-\ttest_when_finished \"rm -rf patches result\" &&\n-\ttest_when_finished \"git config unset format.coverletter\" &&\n-\ttest_when_finished \"git config unset format.commitlistformat\" &&\n-\tgit config set format.coverletter true &&\n-\tprintf \"\\tcommitlistformat\" >> .git/config &&\n-\tgit format-patch -o patches HEAD~2 &&\n-\tgrep -E \"^[[[:digit:]]+/[[:digit:]]+] .*\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 2 result\n-'\n-\n test_expect_success 'cover letter config commitlistformat set to shortlog' '\n \ttest_when_finished \"rm -rf patches result\" &&\n \ttest_when_finished \"git config unset format.coverletter\" &&\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"539000","messageId":"7be0d6c49d09158739784cc70d17ddcbcd0a1fed.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH 5/7] format-patch: wrap generate_commit_list_cover()","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:48Z","receivedAt":"2026-03-14T23:21:04Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"While most conventions should not allow for the text lines in commit\nmessages to get too long, when they do it could make emails harder to\nread.\n\nTeach generate_commit_list_cover() to wrap its commit lines if they\nhappend to be too long.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c | 8 +++++++-\n 1 file changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 47126f9064..d1765ce4ad 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -40,6 +40,7 @@\n #include \"progress.h\"\n #include \"commit-slab.h\"\n #include \"advice.h\"\n+#include \"utf8.h\"\n \n #include \"commit-reach.h\"\n #include \"range-diff.h\"\n@@ -1364,6 +1365,7 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \t\t\t\t       struct commit **list, int n)\n {\n \tstruct strbuf commit_line = STRBUF_INIT;\n+\tstruct strbuf wrapped_line = STRBUF_INIT;\n \tstruct pretty_print_context ctx = {0};\n \tstruct rev_info rev = REV_INFO_INIT;\n \n@@ -1373,12 +1375,16 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \t\trev.nr = i;\n \t\trepo_format_commit_message(the_repository, list[n - i], format,\n \t\t\t\t&commit_line, &ctx);\n-\t\tfprintf(cover_file, \"%s\\n\", commit_line.buf);\n+\t\tstrbuf_add_wrapped_text(&wrapped_line, commit_line.buf, 0, 0,\n+\t\t\t\t\tMAIL_DEFAULT_WRAP);\n+\t\tfprintf(cover_file, \"%s\\n\", wrapped_line.buf);\n \t\tstrbuf_reset(&commit_line);\n+\t\tstrbuf_reset(&wrapped_line);\n \t}\n \tfprintf(cover_file, \"\\n\");\n \n \tstrbuf_release(&commit_line);\n+\tstrbuf_release(&wrapped_line);\n }\n \n static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"539001","messageId":"2a29c31fbb7143867b680ce488f97e9b51150b97.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH 6/7] format-patch: add preset for --commit-list-format","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:49Z","receivedAt":"2026-03-14T23:21:04Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"\"git format-patch --commit-list-format\" enables the user to make their\nown format for the commit list in the cover letter. It would be nice to\nhave a ready to use format to replace shortlog.\n\nTeach make_cover_letter() the \"modern\" format preset.\nThis new format is the same as: \"log:[%(count)/%(total)] %s\".\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/config/format.adoc    |  2 +-\n Documentation/git-format-patch.adoc |  4 ++--\n builtin/log.c                       |  3 +++\n t/t4014-format-patch.sh             | 20 +++++++++++++++-----\n 4 files changed, 21 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/config/format.adoc b/Documentation/config/format.adoc\nindex ea5ec5df7a..ef1ed1d250 100644\n--- a/Documentation/config/format.adoc\n+++ b/Documentation/config/format.adoc\n@@ -104,7 +104,7 @@ format.coverLetter::\n format.commitListFormat::\n \tWhen the `--cover-letter-format` option is not given, `format-patch`\n \tuses the value of this variable to decide how to format the title of\n-\teach commit. Default to `shortlog`.\n+\teach commit. Defaults to `shortlog`.\n \n format.outputDirectory::\n \tSet a custom directory to store the resulting files instead of the\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 45ca72e670..55cc680685 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -325,8 +325,8 @@ feeding the result to `git send-email`.\n \n --commit-list-format=<format-spec>::\n \tSpecify the format in which to generate the commit list of the patch\n-\tseries. The accepted values for format-spec are \"shortlog\" or a format\n-\tstring prefixed with `log:`.\n+\tseries. The accepted values for format-spec are `shortlog`, `modern` or a\n+\tformat string prefixed with `log:`.\n \te.g. `log: %s (%an)`\n \tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\ndiff --git a/builtin/log.c b/builtin/log.c\nindex d1765ce4ad..c6cf04350a 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1445,6 +1445,9 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n \t\tgenerate_commit_list_cover(rev->diffopt.file, format, list, nr);\n \telse if (!strcmp(format, \"shortlog\"))\n \t\tgenerate_shortlog_cover_letter(&log, rev, list, nr);\n+\telse if (!strcmp(format, \"modern\"))\n+\t\tgenerate_commit_list_cover(rev->diffopt.file, \"[%(count)/%(total)] %s\",\n+\t\t\t\t\t   list, nr);\n \telse\n \t\tdie(_(\"'%s' is not a valid format string\"), format);\n \ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca37f40a6a..7571cc582b 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -392,18 +392,17 @@ test_expect_success 'cover letter with subject, author and count' '\n \ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n-test_expect_success 'cover letter with author and count' '\n+test_expect_success 'cover letter modern format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %an\" \\\n-\t-o patches HEAD~1 &&\n-\ttest_grep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch\n+\tgit format-patch --commit-list-format=\"modern\" -o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject$\" patches/0000-cover-letter.patch\n '\n \n-test_expect_success 'cover letter shortlog' '\n+test_expect_success 'cover letter shortlog format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf expect patches result test_file\" &&\n \tcat >expect <<-\"EOF\" &&\n@@ -451,6 +450,17 @@ test_expect_success 'cover letter config with count and author' '\n \ttest_line_count = 2 result\n '\n \n+test_expect_success 'cover letter config commitlistformat set to modern' '\n+\ttest_when_finished \"rm -rf patches result\" &&\n+\ttest_when_finished \"git config unset format.coverletter\" &&\n+\ttest_when_finished \"git config unset format.commitlistformat\" &&\n+\tgit config set format.coverletter true &&\n+\tgit config set format.commitlistformat modern &&\n+\tgit format-patch -o patches HEAD~2 &&\n+\tgrep -E \"^[[[:digit:]]+/[[:digit:]]+] .*$\" patches/0000-cover-letter.patch >result &&\n+\ttest_line_count = 2 result\n+'\n+\n test_expect_success 'cover letter config commitlistformat set to shortlog' '\n \ttest_when_finished \"rm -rf patches result\" &&\n \ttest_when_finished \"git config unset format.coverletter\" &&\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"539002","messageId":"aa7802b653a44838ef78f5ae4a82b341c9853b33.1773530191.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH 7/7] format-patch: --commit-list-format without prefix","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-14T23:20:50Z","receivedAt":"2026-03-14T23:21:04Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Having to prefix a custom format-string with \"log:\" when passed from the\ncli interface can be annoying for many users. It would be great if it\ncould be dropped an it were still accepted.\n\nTeach make_cover_letter() to accept custom format-strings if a\nplaceholder is detected.\n\nNote that both here and in \"git log --format\" the check is done naively\nby just checking for the presence of a '%'.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/git-format-patch.adoc |  4 +++-\n builtin/log.c                       |  2 ++\n t/t4014-format-patch.sh             | 24 ++++++++++++++++++++++++\n 3 files changed, 29 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 55cc680685..c52dbcc170 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -326,8 +326,10 @@ feeding the result to `git send-email`.\n --commit-list-format=<format-spec>::\n \tSpecify the format in which to generate the commit list of the patch\n \tseries. The accepted values for format-spec are `shortlog`, `modern` or a\n-\tformat string prefixed with `log:`.\n+\tformat-string prefixed with `log:`.\n \te.g. `log: %s (%an)`\n+\tThe user is allowed to drop the prefix if the format-string contains a\n+\t`%<placeholder>`.\n \tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\n \tThis option implies the use of `--cover-letter` unless\ndiff --git a/builtin/log.c b/builtin/log.c\nindex c6cf04350a..ad7b7215fe 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1448,6 +1448,8 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n \telse if (!strcmp(format, \"modern\"))\n \t\tgenerate_commit_list_cover(rev->diffopt.file, \"[%(count)/%(total)] %s\",\n \t\t\t\t\t   list, nr);\n+\telse if (strchr(format, '%'))\n+\t\tgenerate_commit_list_cover(rev->diffopt.file, format, list, nr);\n \telse\n \t\tdie(_(\"'%s' is not a valid format string\"), format);\n \ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7571cc582b..7517094bd6 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -392,6 +392,30 @@ test_expect_success 'cover letter with subject, author and count' '\n \ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n+test_expect_success 'cover letter with custom format no prefix' '\n+\trm -rf patches &&\n+\ttest_when_finished \"git reset --hard HEAD~1\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n+\ttouch test_file &&\n+\tgit add test_file &&\n+\tgit commit -m \"This is a subject\" &&\n+\tgit format-patch --commit-list-format=\"[%(count)/%(total)] %s (%an)\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n+'\n+\n+test_expect_success 'cover letter fail when no prefix and no placeholder' '\n+\trm -rf patches &&\n+\ttest_when_finished \"git reset --hard HEAD~1\" &&\n+\ttest_when_finished \"rm -rf patches test_file err\" &&\n+\ttouch test_file &&\n+\tgit add test_file &&\n+\tgit commit -m \"This is a subject\" &&\n+\ttest_must_fail git format-patch --commit-list-format=\"this should fail\" \\\n+\t-o patches HEAD~1 2>err &&\n+\ttest_grep \"is not a valid format string\" err\n+'\n+\n test_expect_success 'cover letter modern format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches test_file\" &&\n-- \n2.53.0.959.g497ff81fa9\n\n"},{"id":"539226","messageId":"0294b771-2d0b-452c-90c1-82baa8344689@app.fastmail.com","threadId":"65248","inReplyTo":"aa7802b653a44838ef78f5ae4a82b341c9853b33.1773530191.git.mroik@delayed.space","subject":"Re: [PATCH 7/7] format-patch: --commit-list-format without prefix","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-03-17T15:29:23Z","receivedAt":"2026-03-17T15:29:44Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Sun, Mar 15, 2026, at 00:20, Mirko Faina wrote:\n> Having to prefix a custom format-string with \"log:\" when passed from the\n> cli interface can be annoying for many users. It would be great if it\n\ns/cli interface/CLI/\n\ns/for many users// ? It’s a general assertion.\n\n> could be dropped an it were still accepted.\n\ns/an/and/\n\nBut maybe instead:\n\n    I would be great if this prefix wasn't required.\n\n>\n> Teach make_cover_letter() to accept custom format-strings if a\n> placeholder is detected.\n>\n> Note that both here and in \"git log --format\" the check is done naively\n> by just checking for the presence of a '%'.\n>\n> Signed-off-by: Mirko Faina <mroik@delayed.space>\n> ---\n>[snip]\n"},{"id":"539227","messageId":"f471643e-b434-47d6-9664-e834a92abe6c@app.fastmail.com","threadId":"65248","inReplyTo":"7be0d6c49d09158739784cc70d17ddcbcd0a1fed.1773530191.git.mroik@delayed.space","subject":"Re: [PATCH 5/7] format-patch: wrap generate_commit_list_cover()","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-03-17T15:32:26Z","receivedAt":"2026-03-17T15:32:47Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Sun, Mar 15, 2026, at 00:20, Mirko Faina wrote:\n> While most conventions should not allow for the text lines in commit\n> messages to get too long, when they do it could make emails harder to\n> read.\n>\n> Teach generate_commit_list_cover() to wrap its commit lines if they\n> happend to be too long.\n\ns/happend/happen/\n\nBut “happen to be” is a bit redundant. You can just say: wrap if they\nare too long.\n\n>\n> Signed-off-by: Mirko Faina <mroik@delayed.space>\n>[snip]\n"},{"id":"539232","messageId":"abl-29SN9ChGkkzd@exploit","threadId":"65248","inReplyTo":"0294b771-2d0b-452c-90c1-82baa8344689@app.fastmail.com","subject":"Re: [PATCH 7/7] format-patch: --commit-list-format without prefix","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-17T16:20:00Z","receivedAt":"2026-03-17T16:20:04Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"On Tue, Mar 17, 2026 at 04:29:23PM +0100, Kristoffer Haugsbakk wrote:\n> On Sun, Mar 15, 2026, at 00:20, Mirko Faina wrote:\n> > Having to prefix a custom format-string with \"log:\" when passed from the\n> > cli interface can be annoying for many users. It would be great if it\n> \n> s/cli interface/CLI/\n> \n> s/for many users// ? It’s a general assertion.\n> \n> > could be dropped an it were still accepted.\n> \n> s/an/and/\n> \n> But maybe instead:\n> \n>     I would be great if this prefix wasn't required.\n\ns/I/It/ :P\n\nWill do, thank you\n"},{"id":"539236","messageId":"abl-U6jJaMQsfxWj@exploit","threadId":"65248","inReplyTo":"f471643e-b434-47d6-9664-e834a92abe6c@app.fastmail.com","subject":"Re: [PATCH 5/7] format-patch: wrap generate_commit_list_cover()","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-17T16:18:28Z","receivedAt":"2026-03-17T16:28:36Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"On Tue, Mar 17, 2026 at 04:32:26PM +0100, Kristoffer Haugsbakk wrote:\n> On Sun, Mar 15, 2026, at 00:20, Mirko Faina wrote:\n> > While most conventions should not allow for the text lines in commit\n> > messages to get too long, when they do it could make emails harder to\n> > read.\n> >\n> > Teach generate_commit_list_cover() to wrap its commit lines if they\n> > happend to be too long.\n> \n> s/happend/happen/\n> \n> But “happen to be” is a bit redundant. You can just say: wrap if they\n> are too long.\n\nWill do, thanks\n"},{"id":"539435","messageId":"cover.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773530191.git.mroik@delayed.space","subject":"[PATCH v2 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:10Z","receivedAt":"2026-03-19T22:38:45Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"I've applied the suggestions that Kristoffer made and added an\nadditional patch that documents %(count) and %(total), but I'm not sure\nif I've placed them in the right location. It's in the \"Placeholders\nthat expand to information extracted from the commit\" section despite\nnot being the most accurate, but making a new section just for\n\"Placeholders that expand to information from patch series\" didn't seem\nright.\n\nThis series is based on top of 67006b9db8 (The 15th batch, 2026-03-12)\nwith the following series merged into it:\n  - mf/format-patch-cover-letter-format at 51ed9f7e72 (docs: add usage\n\tfor the cover-letter fmt feature, 2026-03-07)\n\n[1/8] pretty.c: better die message %(count) and %(total) (Mirko Faina)\n[2/8] format-patch: refactor generate_commit_list_cover (Mirko Faina)\n[3/8] format-patch: rename --cover-letter-format option (Mirko Faina)\n[4/8] docs/pretty-formats: add %(count) and %(total) (Mirko Faina)\n[5/8] format.commitListFormat: strip meaning from empty (Mirko Faina)\n[6/8] format-patch: wrap generate_commit_list_cover() (Mirko Faina)\n[7/8] format-patch: add preset for --commit-list-format (Mirko Faina)\n[8/8] format-patch: --commit-list-format without prefix (Mirko Faina)\n\n Documentation/config/format.adoc    |  2 +-\n Documentation/git-format-patch.adoc | 19 ++++----\n Documentation/pretty-formats.adoc   |  4 ++\n builtin/log.c                       | 35 +++++++-------\n pretty.c                            |  4 +-\n t/t4014-format-patch.sh             | 72 +++++++++++++++++++----------\n t/t9902-completion.sh               |  1 -\n 7 files changed, 84 insertions(+), 53 deletions(-)\n\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539434","messageId":"a0d26c5999980f87b12022d12031d9f0dabbd864.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 1/8] pretty.c: better die message %(count) and %(total)","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:11Z","receivedAt":"2026-03-19T22:38:46Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Improve die messages for commands that do not support %(count) and\n%(total)\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n pretty.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 74673714c8..814803980b 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1551,7 +1551,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \n \tif (starts_with(placeholder, \"(count)\")) {\n \t\tif (!c->pretty_ctx->rev)\n-\t\t\tdie(_(\"this format specifier can't be used with this command\"));\n+\t\t\tdie(_(\"%s is not supported by this command\"), \"%(count)\");\n \t\tstrbuf_addf(sb, \"%0*d\", decimal_width(c->pretty_ctx->rev->total),\n \t\t\t    c->pretty_ctx->rev->nr);\n \t\treturn 7;\n@@ -1559,7 +1559,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \n \tif (starts_with(placeholder, \"(total)\")) {\n \t\tif (!c->pretty_ctx->rev)\n-\t\t\tdie(_(\"this format specifier can't be used with this command\"));\n+\t\t\tdie(_(\"%s is not supported by this command\"), \"%(total)\");\n \t\tstrbuf_addf(sb, \"%d\", c->pretty_ctx->rev->total);\n \t\treturn 7;\n \t}\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539436","messageId":"883dd358b6d69ab8430a4fcd95318150a6fca870.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 2/8] format-patch: refactor generate_commit_list_cover","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:12Z","receivedAt":"2026-03-19T22:38:46Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Refactor for readability and remove unnecessary initialization.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c | 7 +++----\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 716ebc2701..997bdd608e 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1376,12 +1376,11 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \tstruct pretty_print_context ctx = {0};\n \tstruct rev_info rev = REV_INFO_INIT;\n \n-\tstrbuf_init(&commit_line, 0);\n \trev.total = n;\n \tctx.rev = &rev;\n-\tfor (int i = n - 1; i >= 0; i--) {\n-\t\trev.nr = n - i;\n-\t\trepo_format_commit_message(the_repository, list[i], format,\n+\tfor (int i = 1; i <= n; i++) {\n+\t\trev.nr = i;\n+\t\trepo_format_commit_message(the_repository, list[n - i], format,\n \t\t\t\t&commit_line, &ctx);\n \t\tfprintf(cover_file, \"%s\\n\", commit_line.buf);\n \t\tstrbuf_reset(&commit_line);\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539437","messageId":"7b1e5cbb243cf3421a4affd77bb45d31f3e7146c.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 4/8] docs/pretty-formats: add %(count) and %(total)","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:14Z","receivedAt":"2026-03-19T22:38:47Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"When --commit-list-format has been introduced to format-patch, two new\nplaceholders have been added to the PRETTY FORMATS code without being\ndocumented. Do so now.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/pretty-formats.adoc | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/Documentation/pretty-formats.adoc b/Documentation/pretty-formats.adoc\nindex 5405e57a60..67dc0f2a82 100644\n--- a/Documentation/pretty-formats.adoc\n+++ b/Documentation/pretty-formats.adoc\n@@ -253,6 +253,10 @@ The placeholders are:\n \tlinkgit:git-rev-list[1])\n +%d+:: ref names, like the --decorate option of linkgit:git-log[1]\n +%D+:: ref names without the \" (\", \")\" wrapping.\n++%(count)+:: the number of a patch within a patch series. Used only in\n+\t`--commit-list-format` in `format-patch`\n++%(total)+:: the number of tatal patches in a patch series. Used only in\n+\t`--commit-list-format` in `format-patch`\n ++%(decorate++`[:<option>,...]`++)++::\n ref names with custom decorations. The `decorate` string may be followed by a\n colon and zero or more comma-separated options. Option values may contain\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539438","messageId":"5d061d6398bae368a7cc95700b5df44854d1d8e8.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 3/8] format-patch: rename --cover-letter-format option","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:13Z","receivedAt":"2026-03-19T22:38:47Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"To align the name of the configuration variable and the name of the\ncommand line option, either one should change name. By changing the name\nof the option we get the added benefit of having --cover-<TAB> expand to\n--cover-letter without ambiguity.\n\nIf the user gives the --cover-letter-format option it would be\nreasonable to expect that the user wants to generate the cover letter\ndespite not giving --cover-letter.\n\nRename --cover-letter-format to --commit-list-format and make it imply\n--cover-letter unless --no-cover-letter is given.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/git-format-patch.adoc | 17 ++++++------\n builtin/log.c                       |  4 ++-\n t/t4014-format-patch.sh             | 41 +++++++++++++++--------------\n t/t9902-completion.sh               |  1 -\n 4 files changed, 32 insertions(+), 31 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 31fa492335..45ca72e670 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -24,7 +24,7 @@ SYNOPSIS\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n-\t\t   [--cover-letter-format=<format-spec>]\n+\t\t   [--commit-list-format=<format-spec>]\n \t\t   [--[no-]encode-email-headers]\n \t\t   [--no-notes | --notes[=<ref>]]\n \t\t   [--interdiff=<previous>]\n@@ -323,16 +323,15 @@ feeding the result to `git send-email`.\n \tcontaining the branch description, shortlog and the overall diffstat.  You can\n \tfill in a description in the file before sending it out.\n \n---cover-letter-format=<format-spec>::\n-\tSpecify the format in which to generate the commit list of the\n-\tpatch series. This option is available if the user wants to use\n-\tan alternative to the default `shortlog` format. The accepted\n-\tvalues for format-spec are \"shortlog\" or a format string\n-\tprefixed with `log:`.\n+--commit-list-format=<format-spec>::\n+\tSpecify the format in which to generate the commit list of the patch\n+\tseries. The accepted values for format-spec are \"shortlog\" or a format\n+\tstring prefixed with `log:`.\n \te.g. `log: %s (%an)`\n-\tIf defined, defaults to the `format.commitListFormat` configuration\n+\tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\n-\tThis option is relevant only if a cover letter is generated.\n+\tThis option implies the use of `--cover-letter` unless\n+\t`--no-cover-letter` is given.\n \n --encode-email-headers::\n --no-encode-email-headers::\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 997bdd608e..a7f129d583 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2014,7 +2014,7 @@ int cmd_format_patch(int argc,\n \t\t\t    N_(\"print patches to standard out\")),\n \t\tOPT_BOOL(0, \"cover-letter\", &cover_letter,\n \t\t\t    N_(\"generate a cover letter\")),\n-\t\tOPT_STRING(0, \"cover-letter-format\", &cover_letter_fmt, N_(\"format-spec\"),\n+\t\tOPT_STRING(0, \"commit-list-format\", &cover_letter_fmt, N_(\"format-spec\"),\n \t\t\t    N_(\"format spec used for the commit list in the cover letter\")),\n \t\tOPT_BOOL(0, \"numbered-files\", &just_numbers,\n \t\t\t    N_(\"use simple number sequence for output file names\")),\n@@ -2358,6 +2358,8 @@ int cmd_format_patch(int argc,\n \t\tcover_letter_fmt = cfg.fmt_cover_letter_commit_list;\n \t\tif (!cover_letter_fmt)\n \t\t\tcover_letter_fmt = \"shortlog\";\n+\t} else if (cover_letter == -1) {\n+\t\tcover_letter = 1;\n \t}\n \n \tif (cover_letter == -1) {\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7c67bdf922..d2a775f78d 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -383,49 +383,50 @@ test_expect_success 'filename limit applies only to basename' '\n test_expect_success 'cover letter with subject, author and count' '\n \trm -rf patches &&\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter \\\n-\t--cover-letter-format=\"log:[%(count)/%(total)] %s (%an)\" -o patches HEAD~1 &&\n-\tgrep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %s (%an)\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n-test_expected_success 'cover letter with author and count' '\n+test_expect_success 'cover letter with author and count' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter \\\n-\t--cover-letter-format=\"log:[%(count)/%(total)] %an\" -o patches HEAD~1 &&\n-\tgrep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %an\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch\n '\n \n test_expect_success 'cover letter shortlog' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf expect patches result test_file\" &&\n+\tcat >expect <<-\"EOF\" &&\n+\tA U Thor (1):\n+\t  This is a subject\n+\tEOF\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter --cover-letter-format=shortlog \\\n-\t-o patches HEAD~1 &&\n-\tsed -n -e \"/^A U Thor/p;\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=shortlog -o patches HEAD~1 &&\n+\tgrep -E -A 1 \"^A U Thor \\([[:digit:]]+\\):$\" patches/0000-cover-letter.patch >result &&\n+\tcat result &&\n+\ttest_cmp expect result\n '\n \n-test_expect_success 'cover letter no format' '\n+test_expect_success 'no cover letter but with format specified' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches result test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter -o patches HEAD~1 &&\n-\tsed -n -e \"/^A U Thor/p;\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --no-cover-letter --commit-list-format=\"[%(count)] %s\" -o patches HEAD~1 &&\n+\ttest_path_is_missing patches/0000-cover-letter.patch\n '\n \n test_expect_success 'cover letter config with count, subject and author' '\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 35e20b5351..2f9a597ec7 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -2775,7 +2775,6 @@ test_expect_success PERL 'send-email' '\n \ttest_completion \"git send-email --cov\" <<-\\EOF &&\n \t--cover-from-description=Z\n \t--cover-letter Z\n-\t--cover-letter-format=Z\n \tEOF\n \ttest_completion \"git send-email --val\" <<-\\EOF &&\n \t--validate Z\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539439","messageId":"3cb0a0a088f3ca7d4a1d8f97e428cb94b0901968.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 5/8] format.commitListFormat: strip meaning from empty","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:15Z","receivedAt":"2026-03-19T22:38:48Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"The configuration variable format.commitListFormat allows for an empty\nvalue. This is unusual and can create issues when interacting with this\nconfiguration variable through the cli interface.\n\nStrip meaning to format.commitListFormat with an empty value.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c           | 11 +----------\n t/t4014-format-patch.sh | 11 -----------\n 2 files changed, 1 insertion(+), 21 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex a7f129d583..47126f9064 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1055,17 +1055,8 @@ static int git_format_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \tif (!strcmp(var, \"format.commitlistformat\")) {\n-\t\tstruct strbuf tmp = STRBUF_INIT;\n-\t\tstrbuf_init(&tmp, 0);\n-\t\tif (value)\n-\t\t\tstrbuf_addstr(&tmp, value);\n-\t\telse\n-\t\t\tstrbuf_addstr(&tmp, \"log:[%(count)/%(total)] %s\");\n-\n \t\tFREE_AND_NULL(cfg->fmt_cover_letter_commit_list);\n-\t\tgit_config_string(&cfg->fmt_cover_letter_commit_list, var, tmp.buf);\n-\t\tstrbuf_release(&tmp);\n-\t\treturn 0;\n+\t\treturn git_config_string(&cfg->fmt_cover_letter_commit_list, var, value);\n \t}\n \tif (!strcmp(var, \"format.outputdirectory\")) {\n \t\tFREE_AND_NULL(cfg->config_output_directory);\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex d2a775f78d..ca37f40a6a 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -451,17 +451,6 @@ test_expect_success 'cover letter config with count and author' '\n \ttest_line_count = 2 result\n '\n \n-test_expect_success 'cover letter config commitlistformat set but no format' '\n-\ttest_when_finished \"rm -rf patches result\" &&\n-\ttest_when_finished \"git config unset format.coverletter\" &&\n-\ttest_when_finished \"git config unset format.commitlistformat\" &&\n-\tgit config set format.coverletter true &&\n-\tprintf \"\\tcommitlistformat\" >> .git/config &&\n-\tgit format-patch -o patches HEAD~2 &&\n-\tgrep -E \"^[[[:digit:]]+/[[:digit:]]+] .*\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 2 result\n-'\n-\n test_expect_success 'cover letter config commitlistformat set to shortlog' '\n \ttest_when_finished \"rm -rf patches result\" &&\n \ttest_when_finished \"git config unset format.coverletter\" &&\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539440","messageId":"3f547451a22e12ed04969fc0ed73dc1b72c15259.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 6/8] format-patch: wrap generate_commit_list_cover()","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:16Z","receivedAt":"2026-03-19T22:38:48Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"While most conventions should not allow for the text lines in commit\nmessages to get too long, when they do it could make emails harder to\nread.\n\nTeach generate_commit_list_cover() to wrap its commit lines if they are\ntoo long.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c | 8 +++++++-\n 1 file changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 47126f9064..d1765ce4ad 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -40,6 +40,7 @@\n #include \"progress.h\"\n #include \"commit-slab.h\"\n #include \"advice.h\"\n+#include \"utf8.h\"\n \n #include \"commit-reach.h\"\n #include \"range-diff.h\"\n@@ -1364,6 +1365,7 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \t\t\t\t       struct commit **list, int n)\n {\n \tstruct strbuf commit_line = STRBUF_INIT;\n+\tstruct strbuf wrapped_line = STRBUF_INIT;\n \tstruct pretty_print_context ctx = {0};\n \tstruct rev_info rev = REV_INFO_INIT;\n \n@@ -1373,12 +1375,16 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \t\trev.nr = i;\n \t\trepo_format_commit_message(the_repository, list[n - i], format,\n \t\t\t\t&commit_line, &ctx);\n-\t\tfprintf(cover_file, \"%s\\n\", commit_line.buf);\n+\t\tstrbuf_add_wrapped_text(&wrapped_line, commit_line.buf, 0, 0,\n+\t\t\t\t\tMAIL_DEFAULT_WRAP);\n+\t\tfprintf(cover_file, \"%s\\n\", wrapped_line.buf);\n \t\tstrbuf_reset(&commit_line);\n+\t\tstrbuf_reset(&wrapped_line);\n \t}\n \tfprintf(cover_file, \"\\n\");\n \n \tstrbuf_release(&commit_line);\n+\tstrbuf_release(&wrapped_line);\n }\n \n static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539441","messageId":"ef0d3ed876d210503c85a547b8d7e78bdbd8f32a.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 8/8] format-patch: --commit-list-format without prefix","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:18Z","receivedAt":"2026-03-19T22:38:49Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Having to prefix a custom format-string with \"log:\" when passed from the\nCLI can be annoying. It would be great if this prefix wasn't required.\n\nTeach make_cover_letter() to accept custom format-strings without the\n\"log:\" prefix if a placeholder is detected.\n\nNote that both here and in \"git log --format\" the check is done naively\nby just checking for the presence of a '%'.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/git-format-patch.adoc |  4 +++-\n builtin/log.c                       |  2 ++\n t/t4014-format-patch.sh             | 24 ++++++++++++++++++++++++\n 3 files changed, 29 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 55cc680685..c52dbcc170 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -326,8 +326,10 @@ feeding the result to `git send-email`.\n --commit-list-format=<format-spec>::\n \tSpecify the format in which to generate the commit list of the patch\n \tseries. The accepted values for format-spec are `shortlog`, `modern` or a\n-\tformat string prefixed with `log:`.\n+\tformat-string prefixed with `log:`.\n \te.g. `log: %s (%an)`\n+\tThe user is allowed to drop the prefix if the format-string contains a\n+\t`%<placeholder>`.\n \tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\n \tThis option implies the use of `--cover-letter` unless\ndiff --git a/builtin/log.c b/builtin/log.c\nindex c6cf04350a..ad7b7215fe 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1448,6 +1448,8 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n \telse if (!strcmp(format, \"modern\"))\n \t\tgenerate_commit_list_cover(rev->diffopt.file, \"[%(count)/%(total)] %s\",\n \t\t\t\t\t   list, nr);\n+\telse if (strchr(format, '%'))\n+\t\tgenerate_commit_list_cover(rev->diffopt.file, format, list, nr);\n \telse\n \t\tdie(_(\"'%s' is not a valid format string\"), format);\n \ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7571cc582b..7517094bd6 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -392,6 +392,30 @@ test_expect_success 'cover letter with subject, author and count' '\n \ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n+test_expect_success 'cover letter with custom format no prefix' '\n+\trm -rf patches &&\n+\ttest_when_finished \"git reset --hard HEAD~1\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n+\ttouch test_file &&\n+\tgit add test_file &&\n+\tgit commit -m \"This is a subject\" &&\n+\tgit format-patch --commit-list-format=\"[%(count)/%(total)] %s (%an)\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n+'\n+\n+test_expect_success 'cover letter fail when no prefix and no placeholder' '\n+\trm -rf patches &&\n+\ttest_when_finished \"git reset --hard HEAD~1\" &&\n+\ttest_when_finished \"rm -rf patches test_file err\" &&\n+\ttouch test_file &&\n+\tgit add test_file &&\n+\tgit commit -m \"This is a subject\" &&\n+\ttest_must_fail git format-patch --commit-list-format=\"this should fail\" \\\n+\t-o patches HEAD~1 2>err &&\n+\ttest_grep \"is not a valid format string\" err\n+'\n+\n test_expect_success 'cover letter modern format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches test_file\" &&\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539442","messageId":"fdcb68e650e09a2a8432b7164ac28ca5b90ab670.1773959395.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v2 7/8] format-patch: add preset for --commit-list-format","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-19T22:38:17Z","receivedAt":"2026-03-19T22:38:49Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"\"git format-patch --commit-list-format\" enables the user to make their\nown format for the commit list in the cover letter. It would be nice to\nhave a ready to use format to replace shortlog.\n\nTeach make_cover_letter() the \"modern\" format preset.\nThis new format is the same as: \"log:[%(count)/%(total)] %s\".\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/config/format.adoc    |  2 +-\n Documentation/git-format-patch.adoc |  4 ++--\n builtin/log.c                       |  3 +++\n t/t4014-format-patch.sh             | 20 +++++++++++++++-----\n 4 files changed, 21 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/config/format.adoc b/Documentation/config/format.adoc\nindex ea5ec5df7a..ef1ed1d250 100644\n--- a/Documentation/config/format.adoc\n+++ b/Documentation/config/format.adoc\n@@ -104,7 +104,7 @@ format.coverLetter::\n format.commitListFormat::\n \tWhen the `--cover-letter-format` option is not given, `format-patch`\n \tuses the value of this variable to decide how to format the title of\n-\teach commit. Default to `shortlog`.\n+\teach commit. Defaults to `shortlog`.\n \n format.outputDirectory::\n \tSet a custom directory to store the resulting files instead of the\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 45ca72e670..55cc680685 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -325,8 +325,8 @@ feeding the result to `git send-email`.\n \n --commit-list-format=<format-spec>::\n \tSpecify the format in which to generate the commit list of the patch\n-\tseries. The accepted values for format-spec are \"shortlog\" or a format\n-\tstring prefixed with `log:`.\n+\tseries. The accepted values for format-spec are `shortlog`, `modern` or a\n+\tformat string prefixed with `log:`.\n \te.g. `log: %s (%an)`\n \tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\ndiff --git a/builtin/log.c b/builtin/log.c\nindex d1765ce4ad..c6cf04350a 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1445,6 +1445,9 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n \t\tgenerate_commit_list_cover(rev->diffopt.file, format, list, nr);\n \telse if (!strcmp(format, \"shortlog\"))\n \t\tgenerate_shortlog_cover_letter(&log, rev, list, nr);\n+\telse if (!strcmp(format, \"modern\"))\n+\t\tgenerate_commit_list_cover(rev->diffopt.file, \"[%(count)/%(total)] %s\",\n+\t\t\t\t\t   list, nr);\n \telse\n \t\tdie(_(\"'%s' is not a valid format string\"), format);\n \ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca37f40a6a..7571cc582b 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -392,18 +392,17 @@ test_expect_success 'cover letter with subject, author and count' '\n \ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n-test_expect_success 'cover letter with author and count' '\n+test_expect_success 'cover letter modern format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %an\" \\\n-\t-o patches HEAD~1 &&\n-\ttest_grep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch\n+\tgit format-patch --commit-list-format=\"modern\" -o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject$\" patches/0000-cover-letter.patch\n '\n \n-test_expect_success 'cover letter shortlog' '\n+test_expect_success 'cover letter shortlog format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf expect patches result test_file\" &&\n \tcat >expect <<-\"EOF\" &&\n@@ -451,6 +450,17 @@ test_expect_success 'cover letter config with count and author' '\n \ttest_line_count = 2 result\n '\n \n+test_expect_success 'cover letter config commitlistformat set to modern' '\n+\ttest_when_finished \"rm -rf patches result\" &&\n+\ttest_when_finished \"git config unset format.coverletter\" &&\n+\ttest_when_finished \"git config unset format.commitlistformat\" &&\n+\tgit config set format.coverletter true &&\n+\tgit config set format.commitlistformat modern &&\n+\tgit format-patch -o patches HEAD~2 &&\n+\tgrep -E \"^[[[:digit:]]+/[[:digit:]]+] .*$\" patches/0000-cover-letter.patch >result &&\n+\ttest_line_count = 2 result\n+'\n+\n test_expect_success 'cover letter config commitlistformat set to shortlog' '\n \ttest_when_finished \"rm -rf patches result\" &&\n \ttest_when_finished \"git config unset format.coverletter\" &&\n-- \n2.53.0.1018.g2bb0e51243\n\n"},{"id":"539722","messageId":"73663cf1-3112-4e8c-a6ab-10a30670d355@app.fastmail.com","threadId":"65248","inReplyTo":"7b1e5cbb243cf3421a4affd77bb45d31f3e7146c.1773959395.git.mroik@delayed.space","subject":"Re: [PATCH v2 4/8] docs/pretty-formats: add %(count) and %(total)","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-03-23T10:29:21Z","receivedAt":"2026-03-23T10:29:42Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Thu, Mar 19, 2026, at 23:38, Mirko Faina wrote:\n> When --commit-list-format has been introduced to format-patch, two new\n\nThe past tense here is wrong.\n\ns/has been/was/\n\n> placeholders have been added to the PRETTY FORMATS code without being\n\ns/have been/were/\n\n> documented. Do so now.\n>\n> Signed-off-by: Mirko Faina <mroik@delayed.space>\n> ---\n>  Documentation/pretty-formats.adoc | 4 ++++\n>  1 file changed, 4 insertions(+)\n>\n> diff --git a/Documentation/pretty-formats.adoc\n> b/Documentation/pretty-formats.adoc\n> index 5405e57a60..67dc0f2a82 100644\n> --- a/Documentation/pretty-formats.adoc\n> +++ b/Documentation/pretty-formats.adoc\n> @@ -253,6 +253,10 @@ The placeholders are:\n>  \tlinkgit:git-rev-list[1])\n>  +%d+:: ref names, like the --decorate option of linkgit:git-log[1]\n>  +%D+:: ref names without the \" (\", \")\" wrapping.\n> ++%(count)+:: the number of a patch within a patch series. Used only in\n> +\t`--commit-list-format` in `format-patch`\n> ++%(total)+:: the number of tatal patches in a patch series. Used only\n\ns/the number of tatal patches/the total number of patches/ ?\n\n> in\n> +\t`--commit-list-format` in `format-patch`\n>  ++%(decorate++`[:<option>,...]`++)++::\n>  ref names with custom decorations. The `decorate` string may be\n> followed by a\n>  colon and zero or more comma-separated options. Option values may\n> contain\n> --\n> 2.53.0.1018.g2bb0e51243\n"},{"id":"539732","messageId":"acFG_4NbhvvyHbVO@exploit","threadId":"65248","inReplyTo":"73663cf1-3112-4e8c-a6ab-10a30670d355@app.fastmail.com","subject":"Re: [PATCH v2 4/8] docs/pretty-formats: add %(count) and %(total)","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T14:00:30Z","receivedAt":"2026-03-23T14:00:40Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"On Mon, Mar 23, 2026 at 11:29:21AM +0100, Kristoffer Haugsbakk wrote:\n> On Thu, Mar 19, 2026, at 23:38, Mirko Faina wrote:\n> > When --commit-list-format has been introduced to format-patch, two new\n> \n> The past tense here is wrong.\n> \n> s/has been/was/\n> \n> > placeholders have been added to the PRETTY FORMATS code without being\n> \n> s/have been/were/\n\nWill fix.\n\n> > documented. Do so now.\n> >\n> > Signed-off-by: Mirko Faina <mroik@delayed.space>\n> > ---\n> >  Documentation/pretty-formats.adoc | 4 ++++\n> >  1 file changed, 4 insertions(+)\n> >\n> > diff --git a/Documentation/pretty-formats.adoc\n> > b/Documentation/pretty-formats.adoc\n> > index 5405e57a60..67dc0f2a82 100644\n> > --- a/Documentation/pretty-formats.adoc\n> > +++ b/Documentation/pretty-formats.adoc\n> > @@ -253,6 +253,10 @@ The placeholders are:\n> >  \tlinkgit:git-rev-list[1])\n> >  +%d+:: ref names, like the --decorate option of linkgit:git-log[1]\n> >  +%D+:: ref names without the \" (\", \")\" wrapping.\n> > ++%(count)+:: the number of a patch within a patch series. Used only in\n> > +\t`--commit-list-format` in `format-patch`\n> > ++%(total)+:: the number of tatal patches in a patch series. Used only\n> \n> s/the number of tatal patches/the total number of patches/ ?\n\nWill fix.\n\nThank you for the review\n"},{"id":"539761","messageId":"a0d26c5999980f87b12022d12031d9f0dabbd864.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 1/8] pretty.c: better die message %(count) and %(total)","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:28Z","receivedAt":"2026-03-23T16:57:58Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Improve die messages for commands that do not support %(count) and\n%(total)\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n pretty.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 74673714c8..814803980b 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1551,7 +1551,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \n \tif (starts_with(placeholder, \"(count)\")) {\n \t\tif (!c->pretty_ctx->rev)\n-\t\t\tdie(_(\"this format specifier can't be used with this command\"));\n+\t\t\tdie(_(\"%s is not supported by this command\"), \"%(count)\");\n \t\tstrbuf_addf(sb, \"%0*d\", decimal_width(c->pretty_ctx->rev->total),\n \t\t\t    c->pretty_ctx->rev->nr);\n \t\treturn 7;\n@@ -1559,7 +1559,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \n \tif (starts_with(placeholder, \"(total)\")) {\n \t\tif (!c->pretty_ctx->rev)\n-\t\t\tdie(_(\"this format specifier can't be used with this command\"));\n+\t\t\tdie(_(\"%s is not supported by this command\"), \"%(total)\");\n \t\tstrbuf_addf(sb, \"%d\", c->pretty_ctx->rev->total);\n \t\treturn 7;\n \t}\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539763","messageId":"883dd358b6d69ab8430a4fcd95318150a6fca870.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 2/8] format-patch: refactor generate_commit_list_cover","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:29Z","receivedAt":"2026-03-23T16:57:58Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Refactor for readability and remove unnecessary initialization.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c | 7 +++----\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 716ebc2701..997bdd608e 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1376,12 +1376,11 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \tstruct pretty_print_context ctx = {0};\n \tstruct rev_info rev = REV_INFO_INIT;\n \n-\tstrbuf_init(&commit_line, 0);\n \trev.total = n;\n \tctx.rev = &rev;\n-\tfor (int i = n - 1; i >= 0; i--) {\n-\t\trev.nr = n - i;\n-\t\trepo_format_commit_message(the_repository, list[i], format,\n+\tfor (int i = 1; i <= n; i++) {\n+\t\trev.nr = i;\n+\t\trepo_format_commit_message(the_repository, list[n - i], format,\n \t\t\t\t&commit_line, &ctx);\n \t\tfprintf(cover_file, \"%s\\n\", commit_line.buf);\n \t\tstrbuf_reset(&commit_line);\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539765","messageId":"cover.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1773959395.git.mroik@delayed.space","subject":"[PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:27Z","receivedAt":"2026-03-23T16:57:58Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Not much has changed, just applied the suggestions Kristoffer made.\nThank you again for the review\n\n[1/8] pretty.c: better die message %(count) and %(total) (Mirko Faina)\n[2/8] format-patch: refactor generate_commit_list_cover (Mirko Faina)\n[3/8] format-patch: rename --cover-letter-format option (Mirko Faina)\n[4/8] docs/pretty-formats: add %(count) and %(total) (Mirko Faina)\n[5/8] format.commitListFormat: strip meaning from empty (Mirko Faina)\n[6/8] format-patch: wrap generate_commit_list_cover() (Mirko Faina)\n[7/8] format-patch: add preset for --commit-list-format (Mirko Faina)\n[8/8] format-patch: --commit-list-format without prefix (Mirko Faina)\n\n Documentation/config/format.adoc    |  2 +-\n Documentation/git-format-patch.adoc | 19 ++++----\n Documentation/pretty-formats.adoc   |  4 ++\n builtin/log.c                       | 35 +++++++-------\n pretty.c                            |  4 +-\n t/t4014-format-patch.sh             | 72 +++++++++++++++++++----------\n t/t9902-completion.sh               |  1 -\n 7 files changed, 84 insertions(+), 53 deletions(-)\n\nRange-diff against v2:\n1:  a0d26c5999 = 1:  a0d26c5999 pretty.c: better die message %(count) and %(total)\n2:  883dd358b6 = 2:  883dd358b6 format-patch: refactor generate_commit_list_cover\n3:  5d061d6398 = 3:  5d061d6398 format-patch: rename --cover-letter-format option\n4:  7b1e5cbb24 ! 4:  ce7d1bd1fe docs/pretty-formats: add %(count) and %(total)\n    @@ Metadata\n      ## Commit message ##\n         docs/pretty-formats: add %(count) and %(total)\n     \n    -    When --commit-list-format has been introduced to format-patch, two new\n    -    placeholders have been added to the PRETTY FORMATS code without being\n    +    When --commit-list-format was introduced to format-patch, two new\n    +    placeholders were added to the PRETTY FORMATS code without being\n         documented. Do so now.\n     \n         Signed-off-by: Mirko Faina <mroik@delayed.space>\n    @@ Documentation/pretty-formats.adoc: The placeholders are:\n      +%D+:: ref names without the \" (\", \")\" wrapping.\n     ++%(count)+:: the number of a patch within a patch series. Used only in\n     +\t`--commit-list-format` in `format-patch`\n    -++%(total)+:: the number of tatal patches in a patch series. Used only in\n    +++%(total)+:: the total number of patches in a patch series. Used only in\n     +\t`--commit-list-format` in `format-patch`\n      ++%(decorate++`[:<option>,...]`++)++::\n      ref names with custom decorations. The `decorate` string may be followed by a\n5:  3cb0a0a088 ! 5:  66d30249bb format.commitListFormat: strip meaning from empty\n    @@ Commit message\n     \n         The configuration variable format.commitListFormat allows for an empty\n         value. This is unusual and can create issues when interacting with this\n    -    configuration variable through the cli interface.\n    +    configuration variable through the CLI.\n     \n         Strip meaning to format.commitListFormat with an empty value.\n     \n6:  3f547451a2 = 6:  c722fc9d0f format-patch: wrap generate_commit_list_cover()\n7:  fdcb68e650 = 7:  bdd8f1fb57 format-patch: add preset for --commit-list-format\n8:  ef0d3ed876 = 8:  d125458e33 format-patch: --commit-list-format without prefix\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539762","messageId":"ce7d1bd1fefc63bf625eb88a1b9d73d77af4c4ae.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 4/8] docs/pretty-formats: add %(count) and %(total)","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:31Z","receivedAt":"2026-03-23T16:57:59Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"When --commit-list-format was introduced to format-patch, two new\nplaceholders were added to the PRETTY FORMATS code without being\ndocumented. Do so now.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/pretty-formats.adoc | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/Documentation/pretty-formats.adoc b/Documentation/pretty-formats.adoc\nindex 5405e57a60..2ae0eb11a9 100644\n--- a/Documentation/pretty-formats.adoc\n+++ b/Documentation/pretty-formats.adoc\n@@ -253,6 +253,10 @@ The placeholders are:\n \tlinkgit:git-rev-list[1])\n +%d+:: ref names, like the --decorate option of linkgit:git-log[1]\n +%D+:: ref names without the \" (\", \")\" wrapping.\n++%(count)+:: the number of a patch within a patch series. Used only in\n+\t`--commit-list-format` in `format-patch`\n++%(total)+:: the total number of patches in a patch series. Used only in\n+\t`--commit-list-format` in `format-patch`\n ++%(decorate++`[:<option>,...]`++)++::\n ref names with custom decorations. The `decorate` string may be followed by a\n colon and zero or more comma-separated options. Option values may contain\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539764","messageId":"5d061d6398bae368a7cc95700b5df44854d1d8e8.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 3/8] format-patch: rename --cover-letter-format option","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:30Z","receivedAt":"2026-03-23T16:57:59Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"To align the name of the configuration variable and the name of the\ncommand line option, either one should change name. By changing the name\nof the option we get the added benefit of having --cover-<TAB> expand to\n--cover-letter without ambiguity.\n\nIf the user gives the --cover-letter-format option it would be\nreasonable to expect that the user wants to generate the cover letter\ndespite not giving --cover-letter.\n\nRename --cover-letter-format to --commit-list-format and make it imply\n--cover-letter unless --no-cover-letter is given.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/git-format-patch.adoc | 17 ++++++------\n builtin/log.c                       |  4 ++-\n t/t4014-format-patch.sh             | 41 +++++++++++++++--------------\n t/t9902-completion.sh               |  1 -\n 4 files changed, 32 insertions(+), 31 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 31fa492335..45ca72e670 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -24,7 +24,7 @@ SYNOPSIS\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n-\t\t   [--cover-letter-format=<format-spec>]\n+\t\t   [--commit-list-format=<format-spec>]\n \t\t   [--[no-]encode-email-headers]\n \t\t   [--no-notes | --notes[=<ref>]]\n \t\t   [--interdiff=<previous>]\n@@ -323,16 +323,15 @@ feeding the result to `git send-email`.\n \tcontaining the branch description, shortlog and the overall diffstat.  You can\n \tfill in a description in the file before sending it out.\n \n---cover-letter-format=<format-spec>::\n-\tSpecify the format in which to generate the commit list of the\n-\tpatch series. This option is available if the user wants to use\n-\tan alternative to the default `shortlog` format. The accepted\n-\tvalues for format-spec are \"shortlog\" or a format string\n-\tprefixed with `log:`.\n+--commit-list-format=<format-spec>::\n+\tSpecify the format in which to generate the commit list of the patch\n+\tseries. The accepted values for format-spec are \"shortlog\" or a format\n+\tstring prefixed with `log:`.\n \te.g. `log: %s (%an)`\n-\tIf defined, defaults to the `format.commitListFormat` configuration\n+\tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\n-\tThis option is relevant only if a cover letter is generated.\n+\tThis option implies the use of `--cover-letter` unless\n+\t`--no-cover-letter` is given.\n \n --encode-email-headers::\n --no-encode-email-headers::\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 997bdd608e..a7f129d583 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2014,7 +2014,7 @@ int cmd_format_patch(int argc,\n \t\t\t    N_(\"print patches to standard out\")),\n \t\tOPT_BOOL(0, \"cover-letter\", &cover_letter,\n \t\t\t    N_(\"generate a cover letter\")),\n-\t\tOPT_STRING(0, \"cover-letter-format\", &cover_letter_fmt, N_(\"format-spec\"),\n+\t\tOPT_STRING(0, \"commit-list-format\", &cover_letter_fmt, N_(\"format-spec\"),\n \t\t\t    N_(\"format spec used for the commit list in the cover letter\")),\n \t\tOPT_BOOL(0, \"numbered-files\", &just_numbers,\n \t\t\t    N_(\"use simple number sequence for output file names\")),\n@@ -2358,6 +2358,8 @@ int cmd_format_patch(int argc,\n \t\tcover_letter_fmt = cfg.fmt_cover_letter_commit_list;\n \t\tif (!cover_letter_fmt)\n \t\t\tcover_letter_fmt = \"shortlog\";\n+\t} else if (cover_letter == -1) {\n+\t\tcover_letter = 1;\n \t}\n \n \tif (cover_letter == -1) {\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7c67bdf922..d2a775f78d 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -383,49 +383,50 @@ test_expect_success 'filename limit applies only to basename' '\n test_expect_success 'cover letter with subject, author and count' '\n \trm -rf patches &&\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter \\\n-\t--cover-letter-format=\"log:[%(count)/%(total)] %s (%an)\" -o patches HEAD~1 &&\n-\tgrep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %s (%an)\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n-test_expected_success 'cover letter with author and count' '\n+test_expect_success 'cover letter with author and count' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter \\\n-\t--cover-letter-format=\"log:[%(count)/%(total)] %an\" -o patches HEAD~1 &&\n-\tgrep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %an\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch\n '\n \n test_expect_success 'cover letter shortlog' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n-\ttest_when_finished \"rm -rf patches result test_file\" &&\n+\ttest_when_finished \"rm -rf expect patches result test_file\" &&\n+\tcat >expect <<-\"EOF\" &&\n+\tA U Thor (1):\n+\t  This is a subject\n+\tEOF\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter --cover-letter-format=shortlog \\\n-\t-o patches HEAD~1 &&\n-\tsed -n -e \"/^A U Thor/p;\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --commit-list-format=shortlog -o patches HEAD~1 &&\n+\tgrep -E -A 1 \"^A U Thor \\([[:digit:]]+\\):$\" patches/0000-cover-letter.patch >result &&\n+\tcat result &&\n+\ttest_cmp expect result\n '\n \n-test_expect_success 'cover letter no format' '\n+test_expect_success 'no cover letter but with format specified' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches result test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --cover-letter -o patches HEAD~1 &&\n-\tsed -n -e \"/^A U Thor/p;\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 1 result\n+\tgit format-patch --no-cover-letter --commit-list-format=\"[%(count)] %s\" -o patches HEAD~1 &&\n+\ttest_path_is_missing patches/0000-cover-letter.patch\n '\n \n test_expect_success 'cover letter config with count, subject and author' '\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 35e20b5351..2f9a597ec7 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -2775,7 +2775,6 @@ test_expect_success PERL 'send-email' '\n \ttest_completion \"git send-email --cov\" <<-\\EOF &&\n \t--cover-from-description=Z\n \t--cover-letter Z\n-\t--cover-letter-format=Z\n \tEOF\n \ttest_completion \"git send-email --val\" <<-\\EOF &&\n \t--validate Z\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539766","messageId":"66d30249bb933aead0c6b1743167b4b30e522f70.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 5/8] format.commitListFormat: strip meaning from empty","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:32Z","receivedAt":"2026-03-23T16:58:01Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"The configuration variable format.commitListFormat allows for an empty\nvalue. This is unusual and can create issues when interacting with this\nconfiguration variable through the CLI.\n\nStrip meaning to format.commitListFormat with an empty value.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c           | 11 +----------\n t/t4014-format-patch.sh | 11 -----------\n 2 files changed, 1 insertion(+), 21 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex a7f129d583..47126f9064 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1055,17 +1055,8 @@ static int git_format_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \tif (!strcmp(var, \"format.commitlistformat\")) {\n-\t\tstruct strbuf tmp = STRBUF_INIT;\n-\t\tstrbuf_init(&tmp, 0);\n-\t\tif (value)\n-\t\t\tstrbuf_addstr(&tmp, value);\n-\t\telse\n-\t\t\tstrbuf_addstr(&tmp, \"log:[%(count)/%(total)] %s\");\n-\n \t\tFREE_AND_NULL(cfg->fmt_cover_letter_commit_list);\n-\t\tgit_config_string(&cfg->fmt_cover_letter_commit_list, var, tmp.buf);\n-\t\tstrbuf_release(&tmp);\n-\t\treturn 0;\n+\t\treturn git_config_string(&cfg->fmt_cover_letter_commit_list, var, value);\n \t}\n \tif (!strcmp(var, \"format.outputdirectory\")) {\n \t\tFREE_AND_NULL(cfg->config_output_directory);\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex d2a775f78d..ca37f40a6a 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -451,17 +451,6 @@ test_expect_success 'cover letter config with count and author' '\n \ttest_line_count = 2 result\n '\n \n-test_expect_success 'cover letter config commitlistformat set but no format' '\n-\ttest_when_finished \"rm -rf patches result\" &&\n-\ttest_when_finished \"git config unset format.coverletter\" &&\n-\ttest_when_finished \"git config unset format.commitlistformat\" &&\n-\tgit config set format.coverletter true &&\n-\tprintf \"\\tcommitlistformat\" >> .git/config &&\n-\tgit format-patch -o patches HEAD~2 &&\n-\tgrep -E \"^[[[:digit:]]+/[[:digit:]]+] .*\" patches/0000-cover-letter.patch >result &&\n-\ttest_line_count = 2 result\n-'\n-\n test_expect_success 'cover letter config commitlistformat set to shortlog' '\n \ttest_when_finished \"rm -rf patches result\" &&\n \ttest_when_finished \"git config unset format.coverletter\" &&\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539767","messageId":"c722fc9d0fd9af25d7c151079a778299f8ea7054.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 6/8] format-patch: wrap generate_commit_list_cover()","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:33Z","receivedAt":"2026-03-23T16:58:01Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"While most conventions should not allow for the text lines in commit\nmessages to get too long, when they do it could make emails harder to\nread.\n\nTeach generate_commit_list_cover() to wrap its commit lines if they are\ntoo long.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n builtin/log.c | 8 +++++++-\n 1 file changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 47126f9064..d1765ce4ad 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -40,6 +40,7 @@\n #include \"progress.h\"\n #include \"commit-slab.h\"\n #include \"advice.h\"\n+#include \"utf8.h\"\n \n #include \"commit-reach.h\"\n #include \"range-diff.h\"\n@@ -1364,6 +1365,7 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \t\t\t\t       struct commit **list, int n)\n {\n \tstruct strbuf commit_line = STRBUF_INIT;\n+\tstruct strbuf wrapped_line = STRBUF_INIT;\n \tstruct pretty_print_context ctx = {0};\n \tstruct rev_info rev = REV_INFO_INIT;\n \n@@ -1373,12 +1375,16 @@ static void generate_commit_list_cover(FILE *cover_file, const char *format,\n \t\trev.nr = i;\n \t\trepo_format_commit_message(the_repository, list[n - i], format,\n \t\t\t\t&commit_line, &ctx);\n-\t\tfprintf(cover_file, \"%s\\n\", commit_line.buf);\n+\t\tstrbuf_add_wrapped_text(&wrapped_line, commit_line.buf, 0, 0,\n+\t\t\t\t\tMAIL_DEFAULT_WRAP);\n+\t\tfprintf(cover_file, \"%s\\n\", wrapped_line.buf);\n \t\tstrbuf_reset(&commit_line);\n+\t\tstrbuf_reset(&wrapped_line);\n \t}\n \tfprintf(cover_file, \"\\n\");\n \n \tstrbuf_release(&commit_line);\n+\tstrbuf_release(&wrapped_line);\n }\n \n static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539768","messageId":"d125458e3351e6007831dcf84c70e91924b8883d.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 8/8] format-patch: --commit-list-format without prefix","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:35Z","receivedAt":"2026-03-23T16:58:02Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"Having to prefix a custom format-string with \"log:\" when passed from the\nCLI can be annoying. It would be great if this prefix wasn't required.\n\nTeach make_cover_letter() to accept custom format-strings without the\n\"log:\" prefix if a placeholder is detected.\n\nNote that both here and in \"git log --format\" the check is done naively\nby just checking for the presence of a '%'.\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/git-format-patch.adoc |  4 +++-\n builtin/log.c                       |  2 ++\n t/t4014-format-patch.sh             | 24 ++++++++++++++++++++++++\n 3 files changed, 29 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 55cc680685..c52dbcc170 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -326,8 +326,10 @@ feeding the result to `git send-email`.\n --commit-list-format=<format-spec>::\n \tSpecify the format in which to generate the commit list of the patch\n \tseries. The accepted values for format-spec are `shortlog`, `modern` or a\n-\tformat string prefixed with `log:`.\n+\tformat-string prefixed with `log:`.\n \te.g. `log: %s (%an)`\n+\tThe user is allowed to drop the prefix if the format-string contains a\n+\t`%<placeholder>`.\n \tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\n \tThis option implies the use of `--cover-letter` unless\ndiff --git a/builtin/log.c b/builtin/log.c\nindex c6cf04350a..ad7b7215fe 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1448,6 +1448,8 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n \telse if (!strcmp(format, \"modern\"))\n \t\tgenerate_commit_list_cover(rev->diffopt.file, \"[%(count)/%(total)] %s\",\n \t\t\t\t\t   list, nr);\n+\telse if (strchr(format, '%'))\n+\t\tgenerate_commit_list_cover(rev->diffopt.file, format, list, nr);\n \telse\n \t\tdie(_(\"'%s' is not a valid format string\"), format);\n \ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7571cc582b..7517094bd6 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -392,6 +392,30 @@ test_expect_success 'cover letter with subject, author and count' '\n \ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n+test_expect_success 'cover letter with custom format no prefix' '\n+\trm -rf patches &&\n+\ttest_when_finished \"git reset --hard HEAD~1\" &&\n+\ttest_when_finished \"rm -rf patches test_file\" &&\n+\ttouch test_file &&\n+\tgit add test_file &&\n+\tgit commit -m \"This is a subject\" &&\n+\tgit format-patch --commit-list-format=\"[%(count)/%(total)] %s (%an)\" \\\n+\t-o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n+'\n+\n+test_expect_success 'cover letter fail when no prefix and no placeholder' '\n+\trm -rf patches &&\n+\ttest_when_finished \"git reset --hard HEAD~1\" &&\n+\ttest_when_finished \"rm -rf patches test_file err\" &&\n+\ttouch test_file &&\n+\tgit add test_file &&\n+\tgit commit -m \"This is a subject\" &&\n+\ttest_must_fail git format-patch --commit-list-format=\"this should fail\" \\\n+\t-o patches HEAD~1 2>err &&\n+\ttest_grep \"is not a valid format string\" err\n+'\n+\n test_expect_success 'cover letter modern format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches test_file\" &&\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539769","messageId":"bdd8f1fb579af60b2c018f463e91c90859bb2daf.1774284699.git.mroik@delayed.space","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"[PATCH v3 7/8] format-patch: add preset for --commit-list-format","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-23T16:57:34Z","receivedAt":"2026-03-23T16:58:02Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"\"git format-patch --commit-list-format\" enables the user to make their\nown format for the commit list in the cover letter. It would be nice to\nhave a ready to use format to replace shortlog.\n\nTeach make_cover_letter() the \"modern\" format preset.\nThis new format is the same as: \"log:[%(count)/%(total)] %s\".\n\nSigned-off-by: Mirko Faina <mroik@delayed.space>\n---\n Documentation/config/format.adoc    |  2 +-\n Documentation/git-format-patch.adoc |  4 ++--\n builtin/log.c                       |  3 +++\n t/t4014-format-patch.sh             | 20 +++++++++++++++-----\n 4 files changed, 21 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/config/format.adoc b/Documentation/config/format.adoc\nindex ea5ec5df7a..ef1ed1d250 100644\n--- a/Documentation/config/format.adoc\n+++ b/Documentation/config/format.adoc\n@@ -104,7 +104,7 @@ format.coverLetter::\n format.commitListFormat::\n \tWhen the `--cover-letter-format` option is not given, `format-patch`\n \tuses the value of this variable to decide how to format the title of\n-\teach commit. Default to `shortlog`.\n+\teach commit. Defaults to `shortlog`.\n \n format.outputDirectory::\n \tSet a custom directory to store the resulting files instead of the\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 45ca72e670..55cc680685 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -325,8 +325,8 @@ feeding the result to `git send-email`.\n \n --commit-list-format=<format-spec>::\n \tSpecify the format in which to generate the commit list of the patch\n-\tseries. The accepted values for format-spec are \"shortlog\" or a format\n-\tstring prefixed with `log:`.\n+\tseries. The accepted values for format-spec are `shortlog`, `modern` or a\n+\tformat string prefixed with `log:`.\n \te.g. `log: %s (%an)`\n \tIf not given, defaults to the `format.commitListFormat` configuration\n \tvariable.\ndiff --git a/builtin/log.c b/builtin/log.c\nindex d1765ce4ad..c6cf04350a 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1445,6 +1445,9 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,\n \t\tgenerate_commit_list_cover(rev->diffopt.file, format, list, nr);\n \telse if (!strcmp(format, \"shortlog\"))\n \t\tgenerate_shortlog_cover_letter(&log, rev, list, nr);\n+\telse if (!strcmp(format, \"modern\"))\n+\t\tgenerate_commit_list_cover(rev->diffopt.file, \"[%(count)/%(total)] %s\",\n+\t\t\t\t\t   list, nr);\n \telse\n \t\tdie(_(\"'%s' is not a valid format string\"), format);\n \ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca37f40a6a..7571cc582b 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -392,18 +392,17 @@ test_expect_success 'cover letter with subject, author and count' '\n \ttest_grep \"^\\[1/1\\] This is a subject (A U Thor)$\" patches/0000-cover-letter.patch\n '\n \n-test_expect_success 'cover letter with author and count' '\n+test_expect_success 'cover letter modern format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf patches test_file\" &&\n \ttouch test_file &&\n \tgit add test_file &&\n \tgit commit -m \"This is a subject\" &&\n-\tgit format-patch --commit-list-format=\"log:[%(count)/%(total)] %an\" \\\n-\t-o patches HEAD~1 &&\n-\ttest_grep \"^\\[1/1\\] A U Thor$\" patches/0000-cover-letter.patch\n+\tgit format-patch --commit-list-format=\"modern\" -o patches HEAD~1 &&\n+\ttest_grep \"^\\[1/1\\] This is a subject$\" patches/0000-cover-letter.patch\n '\n \n-test_expect_success 'cover letter shortlog' '\n+test_expect_success 'cover letter shortlog format' '\n \ttest_when_finished \"git reset --hard HEAD~1\" &&\n \ttest_when_finished \"rm -rf expect patches result test_file\" &&\n \tcat >expect <<-\"EOF\" &&\n@@ -451,6 +450,17 @@ test_expect_success 'cover letter config with count and author' '\n \ttest_line_count = 2 result\n '\n \n+test_expect_success 'cover letter config commitlistformat set to modern' '\n+\ttest_when_finished \"rm -rf patches result\" &&\n+\ttest_when_finished \"git config unset format.coverletter\" &&\n+\ttest_when_finished \"git config unset format.commitlistformat\" &&\n+\tgit config set format.coverletter true &&\n+\tgit config set format.commitlistformat modern &&\n+\tgit format-patch -o patches HEAD~2 &&\n+\tgrep -E \"^[[[:digit:]]+/[[:digit:]]+] .*$\" patches/0000-cover-letter.patch >result &&\n+\ttest_line_count = 2 result\n+'\n+\n test_expect_success 'cover letter config commitlistformat set to shortlog' '\n \ttest_when_finished \"rm -rf patches result\" &&\n \ttest_when_finished \"git config unset format.coverletter\" &&\n-- \n2.53.0.1118.gaef5881109\n\n"},{"id":"539778","messageId":"xmqqqzpa489h.fsf@gitster.g","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-23T20:10:18Z","receivedAt":"2026-03-23T20:10:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":null},"body":"Mirko Faina <mroik@delayed.space> writes:\n\n> Not much has changed, just applied the suggestions Kristoffer made.\n> Thank you again for the review\n>\n> [1/8] pretty.c: better die message %(count) and %(total) (Mirko Faina)\n> [2/8] format-patch: refactor generate_commit_list_cover (Mirko Faina)\n> [3/8] format-patch: rename --cover-letter-format option (Mirko Faina)\n> [4/8] docs/pretty-formats: add %(count) and %(total) (Mirko Faina)\n> [5/8] format.commitListFormat: strip meaning from empty (Mirko Faina)\n> [6/8] format-patch: wrap generate_commit_list_cover() (Mirko Faina)\n> [7/8] format-patch: add preset for --commit-list-format (Mirko Faina)\n> [8/8] format-patch: --commit-list-format without prefix (Mirko Faina)\n>\n>  Documentation/config/format.adoc    |  2 +-\n>  Documentation/git-format-patch.adoc | 19 ++++----\n>  Documentation/pretty-formats.adoc   |  4 ++\n>  builtin/log.c                       | 35 +++++++-------\n>  pretty.c                            |  4 +-\n>  t/t4014-format-patch.sh             | 72 +++++++++++++++++++----------\n>  t/t9902-completion.sh               |  1 -\n>  7 files changed, 84 insertions(+), 53 deletions(-)\n\nAll incremental changes look reasonable to me, and it seems we have\nalready reached the point of diminishing returns?\n\nIt is possible that people are only commenting on low-hanging\nobvious typoes and mistakes without seeing a bigger picture,\nbut I think I've read through an earlier iteration of the series,\nand found it more-or-less solid, and I do not think there was a\ndrastic change of course since then, so I am happy to mark the topic\nfor 'next' now.\n\nUnless other people find bigger issues remaining in the series, that\nis, of course ;-)\n\nThanks.\n"},{"id":"539856","messageId":"95c249dc-6946-425a-bc44-2a943b4bf551@app.fastmail.com","threadId":"65248","inReplyTo":"xmqqqzpa489h.fsf@gitster.g","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-03-24T16:19:07Z","receivedAt":"2026-03-24T16:19:29Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Mon, Mar 23, 2026, at 21:10, Junio C Hamano wrote:\n>>[snip]\n>>  7 files changed, 84 insertions(+), 53 deletions(-)\n>\n> All incremental changes look reasonable to me, and it seems we have\n> already reached the point of diminishing returns?\n>\n> It is possible that people are only commenting on low-hanging\n> obvious typoes and mistakes without seeing a bigger picture,\n\nAll my comments here are from spotting things accidentally and are not\nin any way holistic assessments. ;)\n\n> but I think I've read through an earlier iteration of the series,\n> and found it more-or-less solid, and I do not think there was a\n> drastic change of course since then, so I am happy to mark the topic\n> for 'next' now.\n>\n> Unless other people find bigger issues remaining in the series, that\n> is, of course ;-)\n"},{"id":"540084","messageId":"ad6a32f9-1b48-4bb5-97c5-96d1dfea3074@gmail.com","threadId":"65248","inReplyTo":"xmqqqzpa489h.fsf@gitster.g","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-03-26T14:29:38Z","receivedAt":"2026-03-26T14:29:53Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 23/03/2026 20:10, Junio C Hamano wrote:\n> Mirko Faina <mroik@delayed.space> writes:\n> \n>> Not much has changed, just applied the suggestions Kristoffer made.\n>> Thank you again for the review\n>>\n>> [1/8] pretty.c: better die message %(count) and %(total) (Mirko Faina)\n>> [2/8] format-patch: refactor generate_commit_list_cover (Mirko Faina)\n>> [3/8] format-patch: rename --cover-letter-format option (Mirko Faina)\n>> [4/8] docs/pretty-formats: add %(count) and %(total) (Mirko Faina)\n>> [5/8] format.commitListFormat: strip meaning from empty (Mirko Faina)\n>> [6/8] format-patch: wrap generate_commit_list_cover() (Mirko Faina)\n>> [7/8] format-patch: add preset for --commit-list-format (Mirko Faina)\n>> [8/8] format-patch: --commit-list-format without prefix (Mirko Faina)\n>>\n>>   Documentation/config/format.adoc    |  2 +-\n>>   Documentation/git-format-patch.adoc | 19 ++++----\n>>   Documentation/pretty-formats.adoc   |  4 ++\n>>   builtin/log.c                       | 35 +++++++-------\n>>   pretty.c                            |  4 +-\n>>   t/t4014-format-patch.sh             | 72 +++++++++++++++++++----------\n>>   t/t9902-completion.sh               |  1 -\n>>   7 files changed, 84 insertions(+), 53 deletions(-)\n> \n> All incremental changes look reasonable to me, and it seems we have\n> already reached the point of diminishing returns?\n> \n> It is possible that people are only commenting on low-hanging\n> obvious typoes and mistakes without seeing a bigger picture,\n> but I think I've read through an earlier iteration of the series,\n> and found it more-or-less solid, and I do not think there was a\n> drastic change of course since then, so I am happy to mark the topic\n> for 'next' now.\n> \n> Unless other people find bigger issues remaining in the series, that\n> is, of course ;-)\n\nI've just had a look at what you merged to next and it looks sound to \nme. The tweaks to the new feature in this series are very welcome \nimprovements.\n\nThanks\n\nPhillip\n\n> Thanks.\n> \n\n"},{"id":"540104","messageId":"CALnO6CAmXrYxYUCg6KRKNYmw7xTW6W5ZZ85BAYL5pOt0pvMR2w@mail.gmail.com","threadId":"65248","inReplyTo":"cover.1774284699.git.mroik@delayed.space","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-03-26T16:34:00Z","receivedAt":"2026-03-26T16:34:12Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":null},"body":"On Mon, Mar 23, 2026 at 1:32 PM Mirko Faina <mroik@delayed.space> wrote:\n>\n> Not much has changed, just applied the suggestions Kristoffer made.\n> Thank you again for the review\n>\n> [1/8] pretty.c: better die message %(count) and %(total) (Mirko Faina)\n> [2/8] format-patch: refactor generate_commit_list_cover (Mirko Faina)\n> [3/8] format-patch: rename --cover-letter-format option (Mirko Faina)\n> [4/8] docs/pretty-formats: add %(count) and %(total) (Mirko Faina)\n> [5/8] format.commitListFormat: strip meaning from empty (Mirko Faina)\n> [6/8] format-patch: wrap generate_commit_list_cover() (Mirko Faina)\n> [7/8] format-patch: add preset for --commit-list-format (Mirko Faina)\n> [8/8] format-patch: --commit-list-format without prefix (Mirko Faina)\n\nI've just noticed:\n- we don't specify the default value in git-format-patch(1), so I have\nto jump from there to git-config(1) to look it up\n- we don't specify what the \"modern\" format means\n\nMaybe that was all hashed out already, in which case links appreciated :)\n\n\n-- \nD. Ben Knoble\n"},{"id":"540105","messageId":"xmqqpl4qr1he.fsf@gitster.g","threadId":"65248","inReplyTo":"ad6a32f9-1b48-4bb5-97c5-96d1dfea3074@gmail.com","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-26T16:37:17Z","receivedAt":"2026-03-26T16:37:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":null},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> On 23/03/2026 20:10, Junio C Hamano wrote:\n>> Mirko Faina <mroik@delayed.space> writes:\n>> \n>>> Not much has changed, just applied the suggestions Kristoffer made.\n>>> Thank you again for the review\n>>> ...\n>>> [7/8] format-patch: add preset for --commit-list-format (Mirko Faina)\n>>> [8/8] format-patch: --commit-list-format without prefix (Mirko Faina)\n>>> ...\n>>>   Documentation/config/format.adoc    |  2 +-\n>>>   Documentation/git-format-patch.adoc | 19 ++++----\n> I've just had a look at what you merged to next and it looks sound to \n> me. The tweaks to the new feature in this series are very welcome \n> improvements.\n\nYup, I tried \"modern\" and generally liked it very much.\n\nThe appearance of the list looked a bit odd that each element in a\nlist of things with heading was shown without any indentation before\nthe heading, though.  I'd probably use\n\n    --commit-list-format=\" %(count): %<(72,trunc)%s\"\n\nor something like that myself.\n\nI seem to be getting spurious blank lines between the lines with the\nabove, when I lengthen and shorten 72 in the format string above,\nthough.  I haven't figured out what is broken, though.\n\n"},{"id":"540107","messageId":"acVpNdlKESgogXe3@exploit","threadId":"65248","inReplyTo":"CALnO6CAmXrYxYUCg6KRKNYmw7xTW6W5ZZ85BAYL5pOt0pvMR2w@mail.gmail.com","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-26T17:15:42Z","receivedAt":"2026-03-26T17:15:52Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"On Thu, Mar 26, 2026 at 12:34:00PM -0400, D. Ben Knoble wrote:\n> On Mon, Mar 23, 2026 at 1:32 PM Mirko Faina <mroik@delayed.space> wrote:\n> >\n> > Not much has changed, just applied the suggestions Kristoffer made.\n> > Thank you again for the review\n> >\n> > [1/8] pretty.c: better die message %(count) and %(total) (Mirko Faina)\n> > [2/8] format-patch: refactor generate_commit_list_cover (Mirko Faina)\n> > [3/8] format-patch: rename --cover-letter-format option (Mirko Faina)\n> > [4/8] docs/pretty-formats: add %(count) and %(total) (Mirko Faina)\n> > [5/8] format.commitListFormat: strip meaning from empty (Mirko Faina)\n> > [6/8] format-patch: wrap generate_commit_list_cover() (Mirko Faina)\n> > [7/8] format-patch: add preset for --commit-list-format (Mirko Faina)\n> > [8/8] format-patch: --commit-list-format without prefix (Mirko Faina)\n> \n> I've just noticed:\n> - we don't specify the default value in git-format-patch(1), so I have\n> to jump from there to git-config(1) to look it up\n> - we don't specify what the \"modern\" format means\n> \n> Maybe that was all hashed out already, in which case links appreciated :)\n\nNo, you're right. It doesn't say what the default is in\n--commit-list-format, it just says that it defaults to\nformat.commitListFormat if not given.\n\nI will send a patch to fix the docs. I guess I should also change the\ntext for --cover-letter as the commit list can now be something other\nthan a shortlog.\n\nThank you for pointing out.\n"},{"id":"540161","messageId":"acXYSm1JoX6YRuoL@exploit","threadId":"65248","inReplyTo":"xmqqpl4qr1he.fsf@gitster.g","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-27T01:13:05Z","receivedAt":"2026-03-27T01:13:10Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"On Thu, Mar 26, 2026 at 09:37:17AM -0700, Junio C Hamano wrote:\n> Yup, I tried \"modern\" and generally liked it very much.\n> \n> The appearance of the list looked a bit odd that each element in a\n> list of things with heading was shown without any indentation before\n> the heading, though.  I'd probably use\n> \n>     --commit-list-format=\" %(count): %<(72,trunc)%s\"\n> \n> or something like that myself.\n> \n> I seem to be getting spurious blank lines between the lines with the\n> above, when I lengthen and shorten 72 in the format string above,\n> though.  I haven't figured out what is broken, though.\n\nCould this be because of strbuf_add_wrapped_text()? In a previous review\nsomeone pointed out that there was no wrapping, so now each entry goes\nthrough a pass of strbuf_add_wrapped_text() which should wrap when the\nline gets longer than MAIL_DEFAULT_WRAP (72 characters). Since you\nguarantee at most 72 chars for %s, if it ever gets to that the line\nwould be at least 76 chars long due to \" n: \".\n"},{"id":"540187","messageId":"xmqqldfdmf6r.fsf@gitster.g","threadId":"65248","inReplyTo":"acXYSm1JoX6YRuoL@exploit","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-27T16:04:44Z","receivedAt":"2026-03-27T16:04:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":null},"body":"Mirko Faina <mroik@delayed.space> writes:\n\n> On Thu, Mar 26, 2026 at 09:37:17AM -0700, Junio C Hamano wrote:\n>> Yup, I tried \"modern\" and generally liked it very much.\n>> \n>> The appearance of the list looked a bit odd that each element in a\n>> list of things with heading was shown without any indentation before\n>> the heading, though.  I'd probably use\n>> \n>>     --commit-list-format=\" %(count): %<(72,trunc)%s\"\n>> \n>> or something like that myself.\n>> \n>> I seem to be getting spurious blank lines between the lines with the\n>> above, when I lengthen and shorten 72 in the format string above,\n>> though.  I haven't figured out what is broken, though.\n>\n> Could this be because of strbuf_add_wrapped_text()?\n\nAhh, I think that would explain it.  In general, I think it is a\nmistake to use strbuf_addwrapped_text() for any end-user\nconfigurable output.  After all, wouldn't %w(w,i1,i2) work in the\nformat string?\n\n> In a previous review\n> someone pointed out that there was no wrapping,\n\nWhen the payload _can_ be specified to wrap (i.e., end-user\nconfigurable output format), the wrapping should not be forced by\nthe mechanism.  A project that is not ours may want to keep a single\nlong line for their commit list entries.\n\nI do not mind if the default \"modern\" were defined to include %w()\nto force wrapping to those who follow the default, of course.  But\ndo not unconditionally wrap what the end-user formatted to their\nliking.\n\n"},{"id":"540194","messageId":"acaq3Rg63ZjEV8rH@exploit","threadId":"65248","inReplyTo":"xmqqldfdmf6r.fsf@gitster.g","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Mirko Faina","fromEmail":"mroik@delayed.space","sentAt":"2026-03-27T16:18:10Z","receivedAt":"2026-03-27T16:18:15Z","isPatch":true,"sender":{"key":"mroik@delayed.space","avatar":null},"body":"On Fri, Mar 27, 2026 at 09:04:44AM -0700, Junio C Hamano wrote:\n> When the payload _can_ be specified to wrap (i.e., end-user\n> configurable output format), the wrapping should not be forced by\n> the mechanism.  A project that is not ours may want to keep a single\n> long line for their commit list entries.\n> \n> I do not mind if the default \"modern\" were defined to include %w()\n> to force wrapping to those who follow the default, of course.  But\n> do not unconditionally wrap what the end-user formatted to their\n> liking.\n\nI see, since there's not much to edit, I'll send the changes regarding\nthe docs and the wrapping in a single series (I saw that you already\nmade mf/format-patch-commit-list-format-doc but I hope it is not a\nproblem), instead of submitting a new one.\n"},{"id":"540201","messageId":"xmqqbjg9kyn5.fsf@gitster.g","threadId":"65248","inReplyTo":"acaq3Rg63ZjEV8rH@exploit","subject":"Re: [PATCH v3 0/8] improve \"git format-patch --commit-list-format\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-27T16:47:26Z","receivedAt":"2026-03-27T16:47:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":null},"body":"Mirko Faina <mroik@delayed.space> writes:\n\n> On Fri, Mar 27, 2026 at 09:04:44AM -0700, Junio C Hamano wrote:\n>> When the payload _can_ be specified to wrap (i.e., end-user\n>> configurable output format), the wrapping should not be forced by\n>> the mechanism.  A project that is not ours may want to keep a single\n>> long line for their commit list entries.\n>> \n>> I do not mind if the default \"modern\" were defined to include %w()\n>> to force wrapping to those who follow the default, of course.  But\n>> do not unconditionally wrap what the end-user formatted to their\n>> liking.\n>\n> I see, since there's not much to edit, I'll send the changes regarding\n> the docs and the wrapping in a single series (I saw that you already\n> made mf/format-patch-commit-list-format-doc but I hope it is not a\n> problem), instead of submitting a new one.\n\nI do not quite know what you are planning to do with the above four\nlines, but you do not have to answer me here, as we'll know soon\nenough once you post them.  I'll just have to remember *not* to merge\nthe new -doc topic to 'next' until that happens ;-).\n"}]}