From: Phillip Wood Date: Tue, 10 Mar 2026 14:34:01 GMT Subject: Re: [PATCH v7 4/5] format-patch: add commitListFormat config Message-ID: <6b160915-1cdf-48b5-abe4-3efd0771598e@gmail.com> In-Reply-To: On 06/03/2026 23:34, Mirko Faina wrote: > Using "--cover-letter" we can tell format-patch to generate a cover > letter, in this cover letter there's a list of commits included in the > patch series and the format is specified by the "--cover-letter-format" > option. Would be useful if this format could be configured from the > config file instead of always needing to pass it from the command line. > > Teach format-patch how to read the format spec for the cover letter from > the config files. The variable it should look for is called > format.commitListFormat. > > Possible values: > - commitListFormat is set but no string is passed: it will default to > "[%(count)/%(total)] %s" It is unusual for an empty config value to mean something different from it not being set. The reason for this is that it allows git -c config.key some-command to act as though config.key was not set. Perhaps we should use the value "default" to generate a default format. It would be nice to support a default format on the commandline as well. > - if a string is passed: will use it as a format spec. Note that this > is either "shortlog" or a format spec prefixed by "log:" > e.g."log:%s (%an)" Having the config value behave like --cover-letter-format= is sensible > - if commitListFormat is not set: it will default to the shortlog > format. makes sense Thanks Phillip > Signed-off-by: Mirko Faina > --- > builtin/log.c | 21 ++++++++++++++++ > t/t4014-format-patch.sh | 53 +++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 74 insertions(+) > > diff --git a/builtin/log.c b/builtin/log.c > index 95e5d9755f..5fec0ddaf9 100644 > --- a/builtin/log.c > +++ b/builtin/log.c > @@ -886,6 +886,7 @@ struct format_config { > char *signature; > char *signature_file; > enum cover_setting config_cover_letter; > + char *fmt_cover_letter_commit_list; > char *config_output_directory; > enum cover_from_description cover_from_description_mode; > int show_notes; > @@ -930,6 +931,7 @@ static void format_config_release(struct format_config *cfg) > string_list_clear(&cfg->extra_cc, 0); > strbuf_release(&cfg->sprefix); > free(cfg->fmt_patch_suffix); > + free(cfg->fmt_cover_letter_commit_list); > } > > static enum cover_from_description parse_cover_from_description(const char *arg) > @@ -1052,6 +1054,19 @@ static int git_format_config(const char *var, const char *value, > cfg->config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF; > return 0; > } > + if (!strcmp(var, "format.commitlistformat")) { > + struct strbuf tmp = STRBUF_INIT; > + strbuf_init(&tmp, 0); > + if (value) > + strbuf_addstr(&tmp, value); > + else > + strbuf_addstr(&tmp, "log:[%(count)/%(total)] %s"); > + > + FREE_AND_NULL(cfg->fmt_cover_letter_commit_list); > + git_config_string(&cfg->fmt_cover_letter_commit_list, var, tmp.buf); > + strbuf_release(&tmp); > + return 0; > + } > if (!strcmp(var, "format.outputdirectory")) { > FREE_AND_NULL(cfg->config_output_directory); > return git_config_string(&cfg->config_output_directory, var, value); > @@ -2329,6 +2344,12 @@ int cmd_format_patch(int argc, > goto done; > total = list.nr; > > + if (!cover_letter_fmt) { > + cover_letter_fmt = cfg.fmt_cover_letter_commit_list; > + if (!cover_letter_fmt) > + cover_letter_fmt = "shortlog"; > + } > + > if (cover_letter == -1) { > if (cfg.config_cover_letter == COVER_AUTO) > cover_letter = (total > 1); > diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh > index 458da80721..4891389a53 100755 > --- a/t/t4014-format-patch.sh > +++ b/t/t4014-format-patch.sh > @@ -428,6 +428,59 @@ test_expect_success 'cover letter no format' ' > test_line_count = 1 result > ' > > +test_expect_success 'cover letter config with count, subject and author' ' > + test_when_finished "rm -rf patches result" && > + test_when_finished "git config unset format.coverletter" && > + test_when_finished "git config unset format.commitlistformat" && > + git config set format.coverletter true && > + git config set format.commitlistformat "log:[%(count)/%(total)] %s (%an)" && > + git format-patch -o patches HEAD~2 && > + grep -E "^[[[:digit:]]+/[[:digit:]]+] .* \(A U Thor\)" patches/0000-cover-letter.patch >result && > + test_line_count = 2 result > +' > + > +test_expect_success 'cover letter config with count and author' ' > + test_when_finished "rm -rf patches result" && > + test_when_finished "git config unset format.coverletter" && > + test_when_finished "git config unset format.commitlistformat" && > + git config set format.coverletter true && > + git config set format.commitlistformat "log:[%(count)/%(total)] (%an)" && > + git format-patch -o patches HEAD~2 && > + grep -E "^[[[:digit:]]+/[[:digit:]]+] \(A U Thor\)" patches/0000-cover-letter.patch >result && > + test_line_count = 2 result > +' > + > +test_expect_success 'cover letter config commitlistformat set but no format' ' > + test_when_finished "rm -rf patches result" && > + test_when_finished "git config unset format.coverletter" && > + test_when_finished "git config unset format.commitlistformat" && > + git config set format.coverletter true && > + printf "\tcommitlistformat" >> .git/config && > + git format-patch -o patches HEAD~2 && > + grep -E "^[[[:digit:]]+/[[:digit:]]+] .*" patches/0000-cover-letter.patch >result && > + test_line_count = 2 result > +' > + > +test_expect_success 'cover letter config commitlistformat set to shortlog' ' > + test_when_finished "rm -rf patches result" && > + test_when_finished "git config unset format.coverletter" && > + test_when_finished "git config unset format.commitlistformat" && > + git config set format.coverletter true && > + git config set format.commitlistformat shortlog && > + git format-patch -o patches HEAD~2 && > + grep -E "^A U Thor \([[:digit:]]+\)" patches/0000-cover-letter.patch >result && > + test_line_count = 1 result > +' > + > +test_expect_success 'cover letter config commitlistformat not set' ' > + test_when_finished "rm -rf patches result" && > + test_when_finished "git config unset format.coverletter" && > + git config set format.coverletter true && > + git format-patch -o patches HEAD~2 && > + grep -E "^A U Thor \([[:digit:]]+\)" patches/0000-cover-letter.patch >result && > + test_line_count = 1 result > +' > + > test_expect_success 'reroll count' ' > rm -fr patches && > git format-patch -o patches --cover-letter --reroll-count 4 main..side >list &&