aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMirko Faina <mroik@delayed.space>2026-03-07 00:34:43 +0100
committerJunio C Hamano <gitster@pobox.com>2026-03-06 17:16:44 -0800
commitbe0ef6fcd2379ea3dc1569d6d8c360d6d59d031f (patch)
treed527d18c3bf1195b74ac85f0cb6ae7ac0c23a909
parent6005932d95ff05541f9dbe8c49a45b7abaf7432e (diff)
downloadgit-be0ef6fcd2379ea3dc1569d6d8c360d6d59d031f.tar.xz
format-patch: add commitListFormat config
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" - 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)" - if commitListFormat is not set: it will default to the shortlog format. Signed-off-by: Mirko Faina <mroik@delayed.space> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/log.c21
-rwxr-xr-xt/t4014-format-patch.sh53
2 files changed, 74 insertions, 0 deletions
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 &&