Subject: [RFC PATCH v2] format-patch: better commit list for cover letter

From: Mirko Faina <[email-masked]>
Date: Sat, 21 Feb 2026 00:55:01 +0100

Often when sending patch series there's a need to clarify to the
reviewer what's the purpose of said series, since it might be difficult
to understand it from reading the commits messages one by one.

"git format-patch" provides the useful "--cover-letter" flag to declare
if we want it to generate a template for us to use. By default it will
generate a "git shortlog" of the changes, which developers find less
useful than they'd like, mainly because the shortlog groups commits by
author, and gives no obvious chronological order.

Teach the make_cover_letter() a better cover letter format to replace
the current. The format can be seen from the following example:

    [1/3] abcc234s: this is a summary
    [2/3] 73s84ns2: this is another summary

Signed-off-by: Mirko Faina <[email-masked]>
---
This patch comes after a small off-topic[1] that discussed the
usefulness (or the lack thereof) of the current cover letter template.
This patch hopes to make a better format so that developers won't have
to make their own custom script to generate better info.

P.s. I'm sorry, the first version was a bit wrong. This one is correct.

[1] https://lore.kernel.org/git/[email-masked]/

 builtin/log.c | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index c1cd3999a7..7d446b09b4 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -30,7 +30,6 @@
 #include "reflog-walk.h"
 #include "patch-ids.h"
 #include "path.h"
-#include "shortlog.h"
 #include "remote.h"
 #include "string-list.h"
 #include "parse-options.h"
@@ -40,6 +39,8 @@
 #include "mailmap.h"
 #include "progress.h"
 #include "commit-slab.h"
+#include "pretty.h"
+#include "strbuf.h"
 
 #include "commit-reach.h"
 #include "range-diff.h"
@@ -1324,6 +1325,29 @@ static void get_notes_args(struct strvec *arg, struct rev_info *rev)
 	}
 }
 
+static void generate_cover_commit_list(FILE *cover_file, struct commit** list, int nr)
+{
+	char* commit_hash_buf = malloc(GIT_MAX_HEXSZ + 1);
+	struct strbuf *sb_loglines = malloc(sizeof(struct strbuf));
+	int temp;
+
+	for (int i = 0; i < nr; i++) {
+		strbuf_init(sb_loglines, 0);
+		strbuf_addf(sb_loglines, "[%0*d/%d] ", decimal_width(nr), i + 1, nr);
+		temp = sb_loglines->len;
+		strbuf_addstr(sb_loglines, oid_to_hex_r(commit_hash_buf, &list[i]->object.oid));
+		strbuf_remove(sb_loglines, temp + 8, sb_loglines->len - (temp + 8));
+		strbuf_addch(sb_loglines, ':');
+		strbuf_addch(sb_loglines, ' ');
+		pp_commit_easy(CMIT_FMT_ONELINE, list[i], sb_loglines);
+		fprintf(cover_file, "%s\n", sb_loglines->buf);
+	}
+
+	fprintf(cover_file, "\n");
+	strbuf_release(sb_loglines);
+	free(commit_hash_buf);
+}
+
 static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 			      struct commit *origin,
 			      int nr, struct commit **list,
@@ -1333,7 +1357,6 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 			      const struct format_config *cfg)
 {
 	const char *from;
-	struct shortlog log;
 	struct strbuf sb = STRBUF_INIT;
 	int i;
 	const char *encoding = "UTF-8";
@@ -1377,18 +1400,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 	free(pp.after_subject);
 	strbuf_release(&sb);
 
-	shortlog_init(&log);
-	log.wrap_lines = 1;
-	log.wrap = MAIL_DEFAULT_WRAP;
-	log.in1 = 2;
-	log.in2 = 4;
-	log.file = rev->diffopt.file;
-	log.groups = SHORTLOG_GROUP_AUTHOR;
-	shortlog_finish_setup(&log);
-	for (i = 0; i < nr; i++)
-		shortlog_add_commit(&log, list[i]);
-
-	shortlog_output(&log);
+	generate_cover_commit_list(rev->diffopt.file, list, nr);
 
 	/* We can only do diffstat with a unique reference point */
 	if (origin)

base-commit: a8e89346a7731cb3104010f322c65e2a0c922618
-- 
2.53.0