]> git.ipfire.org Git - thirdparty/git.git/commitdiff
format-patch: add commitListFormat config
authorMirko Faina <mroik@delayed.space>
Fri, 6 Mar 2026 23:34:43 +0000 (00:34 +0100)
committerJunio C Hamano <gitster@pobox.com>
Sat, 7 Mar 2026 01:16:44 +0000 (17:16 -0800)
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>
builtin/log.c
t/t4014-format-patch.sh

index 95e5d9755fac6d42864c72a6553b1713828dc685..5fec0ddaf91b0a52c4dac9a1a334019eeff3e1d2 100644 (file)
@@ -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);
index 458da80721a1e97d5ff80a64e29c5588cf4d4ab7..4891389a53aed40be5568a3bc4623c9e61c17fb7 100755 (executable)
@@ -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 &&