From 67ea2ad7d1b006194762cbfcc0b7801ffe652ca4 Mon Sep 17 00:00:00 2001
From: Mirko Faina <mroik@delayed.space>
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-<TAB> 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 <mroik@delayed.space>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-format-patch.adoc | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 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) <n>]
 		   [--to=<email>] [--cc=<email>]
 		   [--[no-]cover-letter] [--quiet]
-		   [--cover-letter-format=<format-spec>]
+		   [--commit-list-format=<format-spec>]
 		   [--[no-]encode-email-headers]
 		   [--no-notes | --notes[=<ref>]]
 		   [--interdiff=<previous>]
@@ -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=<format-spec>::
-	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=<format-spec>::
+	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::
-- 
cgit v1.3-5-g9baa


From d022dc77ab81fcc005b9965e91f524d4a43e74b5 Mon Sep 17 00:00:00 2001
From: Mirko Faina <mroik@delayed.space>
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 <mroik@delayed.space>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 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=<format-spec>::
 	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-5-g9baa


From 36c16a5b7fff7806b475b5fa07eca3a5179d7fa6 Mon Sep 17 00:00:00 2001
From: Mirko Faina <mroik@delayed.space>
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 <mroik@delayed.space>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 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=<format-spec>::
 	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
+	`%<placeholder>`.
 	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-5-g9baa

