From 51ed9f7e724468b8e44a7c33946dda38a335acca Mon Sep 17 00:00:00 2001 From: Mirko Faina Date: Sat, 7 Mar 2026 00:34:44 +0100 Subject: docs: add usage for the cover-letter fmt feature Document the new "--cover-letter-format" option in format-patch and its related configuration variable "format.commitListFormat". Signed-off-by: Mirko Faina Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.adoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'Documentation/git-format-patch.adoc') diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc index 9a7807ca71..668330a015 100644 --- a/Documentation/git-format-patch.adoc +++ b/Documentation/git-format-patch.adoc @@ -24,6 +24,7 @@ SYNOPSIS [(--reroll-count|-v) ] [--to=] [--cc=] [--[no-]cover-letter] [--quiet] + [--cover-letter-format=] [--[no-]encode-email-headers] [--no-notes | --notes[=]] [--interdiff=] @@ -321,6 +322,17 @@ feeding the result to `git send-email`. containing the branch description, shortlog and the overall diffstat. You can fill in a description in the file before sending it out. +--cover-letter-format=:: + Specify the format in which to generate the commit list of the + patch series. This option is available if the user wants to use + an alternative to the default `shortlog` format. The accepted + values for format-spec are "shortlog" or a format string + prefixed with `log:`. + e.g. `log: %s (%an)` + If defined, defaults to the `format.commitListFormat` configuration + variable. + This option is relevant only if a cover letter is generated. + --encode-email-headers:: --no-encode-email-headers:: Encode email headers that have non-ASCII characters with @@ -452,6 +464,7 @@ with configuration variables. signOff = true outputDirectory = coverLetter = auto + commitListFormat = shortlog coverFromDescription = auto ------------ -- cgit v1.3 From 67ea2ad7d1b006194762cbfcc0b7801ffe652ca4 Mon Sep 17 00:00:00 2001 From: Mirko Faina Date: Mon, 23 Mar 2026 17:57:30 +0100 Subject: format-patch: rename --cover-letter-format option To align the name of the configuration variable and the name of the command line option, either one should change name. By changing the name of the option we get the added benefit of having --cover- expand to --cover-letter without ambiguity. If the user gives the --cover-letter-format option it would be reasonable to expect that the user wants to generate the cover letter despite not giving --cover-letter. Rename --cover-letter-format to --commit-list-format and make it imply --cover-letter unless --no-cover-letter is given. Signed-off-by: Mirko Faina Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.adoc | 17 ++++++++------- builtin/log.c | 4 +++- t/t4014-format-patch.sh | 41 +++++++++++++++++++------------------ t/t9902-completion.sh | 1 - 4 files changed, 32 insertions(+), 31 deletions(-) (limited to 'Documentation/git-format-patch.adoc') diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc index 31fa492335..45ca72e670 100644 --- a/Documentation/git-format-patch.adoc +++ b/Documentation/git-format-patch.adoc @@ -24,7 +24,7 @@ SYNOPSIS [(--reroll-count|-v) ] [--to=] [--cc=] [--[no-]cover-letter] [--quiet] - [--cover-letter-format=] + [--commit-list-format=] [--[no-]encode-email-headers] [--no-notes | --notes[=]] [--interdiff=] @@ -323,16 +323,15 @@ feeding the result to `git send-email`. containing the branch description, shortlog and the overall diffstat. You can fill in a description in the file before sending it out. ---cover-letter-format=:: - Specify the format in which to generate the commit list of the - patch series. This option is available if the user wants to use - an alternative to the default `shortlog` format. The accepted - values for format-spec are "shortlog" or a format string - prefixed with `log:`. +--commit-list-format=:: + Specify the format in which to generate the commit list of the patch + series. The accepted values for format-spec are "shortlog" or a format + string prefixed with `log:`. e.g. `log: %s (%an)` - If defined, defaults to the `format.commitListFormat` configuration + If not given, defaults to the `format.commitListFormat` configuration variable. - This option is relevant only if a cover letter is generated. + This option implies the use of `--cover-letter` unless + `--no-cover-letter` is given. --encode-email-headers:: --no-encode-email-headers:: diff --git a/builtin/log.c b/builtin/log.c index 997bdd608e..a7f129d583 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -2014,7 +2014,7 @@ int cmd_format_patch(int argc, N_("print patches to standard out")), OPT_BOOL(0, "cover-letter", &cover_letter, N_("generate a cover letter")), - OPT_STRING(0, "cover-letter-format", &cover_letter_fmt, N_("format-spec"), + OPT_STRING(0, "commit-list-format", &cover_letter_fmt, N_("format-spec"), N_("format spec used for the commit list in the cover letter")), OPT_BOOL(0, "numbered-files", &just_numbers, N_("use simple number sequence for output file names")), @@ -2358,6 +2358,8 @@ int cmd_format_patch(int argc, cover_letter_fmt = cfg.fmt_cover_letter_commit_list; if (!cover_letter_fmt) cover_letter_fmt = "shortlog"; + } else if (cover_letter == -1) { + cover_letter = 1; } if (cover_letter == -1) { diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 7c67bdf922..d2a775f78d 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -383,49 +383,50 @@ test_expect_success 'filename limit applies only to basename' ' test_expect_success 'cover letter with subject, author and count' ' rm -rf patches && test_when_finished "git reset --hard HEAD~1" && - test_when_finished "rm -rf patches result test_file" && + test_when_finished "rm -rf patches test_file" && touch test_file && git add test_file && git commit -m "This is a subject" && - git format-patch --cover-letter \ - --cover-letter-format="log:[%(count)/%(total)] %s (%an)" -o patches HEAD~1 && - grep "^\[1/1\] This is a subject (A U Thor)$" patches/0000-cover-letter.patch >result && - test_line_count = 1 result + git format-patch --commit-list-format="log:[%(count)/%(total)] %s (%an)" \ + -o patches HEAD~1 && + test_grep "^\[1/1\] This is a subject (A U Thor)$" patches/0000-cover-letter.patch ' -test_expected_success 'cover letter with author and count' ' +test_expect_success 'cover letter with author and count' ' test_when_finished "git reset --hard HEAD~1" && - test_when_finished "rm -rf patches result test_file" && + test_when_finished "rm -rf patches test_file" && touch test_file && git add test_file && git commit -m "This is a subject" && - git format-patch --cover-letter \ - --cover-letter-format="log:[%(count)/%(total)] %an" -o patches HEAD~1 && - grep "^\[1/1\] A U Thor$" patches/0000-cover-letter.patch >result && - test_line_count = 1 result + git format-patch --commit-list-format="log:[%(count)/%(total)] %an" \ + -o patches HEAD~1 && + test_grep "^\[1/1\] A U Thor$" patches/0000-cover-letter.patch ' test_expect_success 'cover letter shortlog' ' test_when_finished "git reset --hard HEAD~1" && - test_when_finished "rm -rf patches result test_file" && + test_when_finished "rm -rf expect patches result test_file" && + cat >expect <<-"EOF" && + A U Thor (1): + This is a subject + EOF touch test_file && git add test_file && git commit -m "This is a subject" && - git format-patch --cover-letter --cover-letter-format=shortlog \ - -o patches HEAD~1 && - sed -n -e "/^A U Thor/p;" patches/0000-cover-letter.patch >result && - test_line_count = 1 result + git format-patch --commit-list-format=shortlog -o patches HEAD~1 && + grep -E -A 1 "^A U Thor \([[:digit:]]+\):$" patches/0000-cover-letter.patch >result && + cat result && + test_cmp expect result ' -test_expect_success 'cover letter no format' ' +test_expect_success 'no cover letter but with format specified' ' test_when_finished "git reset --hard HEAD~1" && test_when_finished "rm -rf patches result test_file" && touch test_file && git add test_file && git commit -m "This is a subject" && - git format-patch --cover-letter -o patches HEAD~1 && - sed -n -e "/^A U Thor/p;" patches/0000-cover-letter.patch >result && - test_line_count = 1 result + git format-patch --no-cover-letter --commit-list-format="[%(count)] %s" -o patches HEAD~1 && + test_path_is_missing patches/0000-cover-letter.patch ' test_expect_success 'cover letter config with count, subject and author' ' diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 35e20b5351..2f9a597ec7 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -2775,7 +2775,6 @@ test_expect_success PERL 'send-email' ' test_completion "git send-email --cov" <<-\EOF && --cover-from-description=Z --cover-letter Z - --cover-letter-format=Z EOF test_completion "git send-email --val" <<-\EOF && --validate Z -- cgit v1.3 From d022dc77ab81fcc005b9965e91f524d4a43e74b5 Mon Sep 17 00:00:00 2001 From: Mirko Faina Date: Mon, 23 Mar 2026 17:57:34 +0100 Subject: format-patch: add preset for --commit-list-format "git format-patch --commit-list-format" enables the user to make their own format for the commit list in the cover letter. It would be nice to have a ready to use format to replace shortlog. Teach make_cover_letter() the "modern" format preset. This new format is the same as: "log:[%(count)/%(total)] %s". Signed-off-by: Mirko Faina Signed-off-by: Junio C Hamano --- Documentation/config/format.adoc | 2 +- Documentation/git-format-patch.adoc | 4 ++-- builtin/log.c | 3 +++ t/t4014-format-patch.sh | 20 +++++++++++++++----- 4 files changed, 21 insertions(+), 8 deletions(-) (limited to 'Documentation/git-format-patch.adoc') diff --git a/Documentation/config/format.adoc b/Documentation/config/format.adoc index ea5ec5df7a..ef1ed1d250 100644 --- a/Documentation/config/format.adoc +++ b/Documentation/config/format.adoc @@ -104,7 +104,7 @@ format.coverLetter:: format.commitListFormat:: When the `--cover-letter-format` option is not given, `format-patch` uses the value of this variable to decide how to format the title of - each commit. Default to `shortlog`. + each commit. Defaults to `shortlog`. format.outputDirectory:: Set a custom directory to store the resulting files instead of the diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc index 45ca72e670..55cc680685 100644 --- a/Documentation/git-format-patch.adoc +++ b/Documentation/git-format-patch.adoc @@ -325,8 +325,8 @@ feeding the result to `git send-email`. --commit-list-format=:: Specify the format in which to generate the commit list of the patch - series. The accepted values for format-spec are "shortlog" or a format - string prefixed with `log:`. + series. The accepted values for format-spec are `shortlog`, `modern` or a + format string prefixed with `log:`. e.g. `log: %s (%an)` If not given, defaults to the `format.commitListFormat` configuration variable. diff --git a/builtin/log.c b/builtin/log.c index d1765ce4ad..c6cf04350a 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1445,6 +1445,9 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, generate_commit_list_cover(rev->diffopt.file, format, list, nr); else if (!strcmp(format, "shortlog")) generate_shortlog_cover_letter(&log, rev, list, nr); + else if (!strcmp(format, "modern")) + generate_commit_list_cover(rev->diffopt.file, "[%(count)/%(total)] %s", + list, nr); else die(_("'%s' is not a valid format string"), format); diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index ca37f40a6a..7571cc582b 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -392,18 +392,17 @@ test_expect_success 'cover letter with subject, author and count' ' test_grep "^\[1/1\] This is a subject (A U Thor)$" patches/0000-cover-letter.patch ' -test_expect_success 'cover letter with author and count' ' +test_expect_success 'cover letter modern format' ' test_when_finished "git reset --hard HEAD~1" && test_when_finished "rm -rf patches test_file" && touch test_file && git add test_file && git commit -m "This is a subject" && - git format-patch --commit-list-format="log:[%(count)/%(total)] %an" \ - -o patches HEAD~1 && - test_grep "^\[1/1\] A U Thor$" patches/0000-cover-letter.patch + git format-patch --commit-list-format="modern" -o patches HEAD~1 && + test_grep "^\[1/1\] This is a subject$" patches/0000-cover-letter.patch ' -test_expect_success 'cover letter shortlog' ' +test_expect_success 'cover letter shortlog format' ' test_when_finished "git reset --hard HEAD~1" && test_when_finished "rm -rf expect patches result test_file" && cat >expect <<-"EOF" && @@ -451,6 +450,17 @@ test_expect_success 'cover letter config with count and author' ' test_line_count = 2 result ' +test_expect_success 'cover letter config commitlistformat set to modern' ' + 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 modern && + 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" && -- cgit v1.3 From 36c16a5b7fff7806b475b5fa07eca3a5179d7fa6 Mon Sep 17 00:00:00 2001 From: Mirko Faina Date: Mon, 23 Mar 2026 17:57:35 +0100 Subject: format-patch: --commit-list-format without prefix Having to prefix a custom format-string with "log:" when passed from the CLI can be annoying. It would be great if this prefix wasn't required. Teach make_cover_letter() to accept custom format-strings without the "log:" prefix if a placeholder is detected. Note that both here and in "git log --format" the check is done naively by just checking for the presence of a '%'. Signed-off-by: Mirko Faina Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.adoc | 4 +++- builtin/log.c | 2 ++ t/t4014-format-patch.sh | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'Documentation/git-format-patch.adoc') diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc index 55cc680685..c52dbcc170 100644 --- a/Documentation/git-format-patch.adoc +++ b/Documentation/git-format-patch.adoc @@ -326,8 +326,10 @@ feeding the result to `git send-email`. --commit-list-format=:: Specify the format in which to generate the commit list of the patch series. The accepted values for format-spec are `shortlog`, `modern` or a - format string prefixed with `log:`. + format-string prefixed with `log:`. e.g. `log: %s (%an)` + The user is allowed to drop the prefix if the format-string contains a + `%`. If not given, defaults to the `format.commitListFormat` configuration variable. This option implies the use of `--cover-letter` unless diff --git a/builtin/log.c b/builtin/log.c index c6cf04350a..ad7b7215fe 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1448,6 +1448,8 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, else if (!strcmp(format, "modern")) generate_commit_list_cover(rev->diffopt.file, "[%(count)/%(total)] %s", list, nr); + else if (strchr(format, '%')) + generate_commit_list_cover(rev->diffopt.file, format, list, nr); else die(_("'%s' is not a valid format string"), format); diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 7571cc582b..7517094bd6 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -392,6 +392,30 @@ test_expect_success 'cover letter with subject, author and count' ' test_grep "^\[1/1\] This is a subject (A U Thor)$" patches/0000-cover-letter.patch ' +test_expect_success 'cover letter with custom format no prefix' ' + rm -rf patches && + test_when_finished "git reset --hard HEAD~1" && + test_when_finished "rm -rf patches test_file" && + touch test_file && + git add test_file && + git commit -m "This is a subject" && + git format-patch --commit-list-format="[%(count)/%(total)] %s (%an)" \ + -o patches HEAD~1 && + test_grep "^\[1/1\] This is a subject (A U Thor)$" patches/0000-cover-letter.patch +' + +test_expect_success 'cover letter fail when no prefix and no placeholder' ' + rm -rf patches && + test_when_finished "git reset --hard HEAD~1" && + test_when_finished "rm -rf patches test_file err" && + touch test_file && + git add test_file && + git commit -m "This is a subject" && + test_must_fail git format-patch --commit-list-format="this should fail" \ + -o patches HEAD~1 2>err && + test_grep "is not a valid format string" err +' + test_expect_success 'cover letter modern format' ' test_when_finished "git reset --hard HEAD~1" && test_when_finished "rm -rf patches test_file" && -- cgit v1.3