Subject: [PATCH v5 0/5] format-rev: introduce builtin for on-demand pretty formatting

From: [email-masked]
Date: Mon, 11 May 2026 17:45:44 +0200

From: Kristoffer Haugsbakk <[email-masked]>

(Subject from v2: name-rev: learn --format=<pretty>)

Topic name (applied): kh/name-rev-custom-format

Topic summary: Introduce a new builtin for pretty formatting either (1) one
revision expression per line or (2) commit object names found in running
text.

See the last patch for the motivation. In short there isn’t anything that I
have found that lets you format however many commits you want through one
process (so looping over `git show` is excepted).

The other patches prepare for this change.

§ Changes in v5

Notes from patch 5/5, all doc changes:

    • Fix definition list mistake
      • No blank line between the two modes
      • Also replace `::` delimiters with `;;`. This is not strictly
        needed since the definition list is inside an open block. But
        it is consistent with all other definition list in definition
        lists I’ve seen. (The command option section is a long
        definition list.)
    • Rewrite part that I was unhappy about regarding
      `--stdin-mode=text` and `-z`:

        https://lore.kernel.org/git/[email-masked]/
    • Replace `abcdef012...` with just “some object name”. The object
      name is arbitrary and my AsciiDoc output seems to do some weird
      things for `...` inside backticks for HTML.
    • Replace “this problem is just another” with “this problem
      *is solved* with...”

§ Link to v4

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

[1/5] name-rev: wrap both blocks in braces
[2/5] name-rev: run clang-format before factoring code
[3/5] name-rev: factor code for sharing with a new command
[4/5] name-rev: make dedicated --annotate-stdin --name-only test
[5/5] format-rev: introduce builtin for on-demand pretty formatting

 .gitignore                        |   1 +
 Documentation/git-format-rev.adoc | 215 +++++++++++++++++++++
 Documentation/meson.build         |   1 +
 Makefile                          |   1 +
 builtin.h                         |   1 +
 builtin/name-rev.c                | 300 +++++++++++++++++++++++++++---
 command-list.txt                  |   1 +
 git.c                             |   1 +
 t/t1517-outside-repo.sh           |   3 +-
 t/t6120-describe.sh               | 208 +++++++++++++++++++++
 10 files changed, 706 insertions(+), 26 deletions(-)
 create mode 100644 Documentation/git-format-rev.adoc

Interdiff against v4:
diff --git a/Documentation/git-format-rev.adoc b/Documentation/git-format-rev.adoc
index 436980012bc..c40d52e9f6d 100644
--- a/Documentation/git-format-rev.adoc
+++ b/Documentation/git-format-rev.adoc
@@ -25,13 +25,14 @@ OPTIONS
 	How to interpret standard input data:
 +
 --
-`revs`:: Each line or record (see the <<io,INPUT AND OUTPUT FORMATS>>
+`revs`;; Each line or record (see the <<io,INPUT AND OUTPUT FORMATS>>
 	section) is interpreted as a commit. Any kind of revision
 	expression can be used (see linkgit:gitrevisions[7]). Annotated
 	tags are peeled (see linkgit:gitglossary[7]).
 +
 The argument `rev` is also accepted.
-`text`:: Formats all commit object names found in freeform text. These
+
+`text`;; Formats all commit object names found in freeform text. These
 	must the full object names, i.e. abbreviated hexidecimal object
 	names will not be interpreted.
 +
@@ -53,8 +54,12 @@ commit object name is left alone (echoed).
 	of newline. This option cannot be negated.
 +
 This is useful if both the input and output could contain newlines or if
-the input could contain _NUL_ characters; see the <<io,INPUT AND OUTPUT
-FORMATS>> section.
+the input to this command also uses _NUL_ character termination; see the
+<<io,INPUT AND OUTPUT FORMATS>> section below.
++
+The mode `--stdin-mode=text` can have use for this option when it needs
+to process input like for example `git last-modified -z`; see the
+<<examples,EXAMPLES>> section below.
 
 `--null-output`::
 `--no-null-output`::
@@ -70,8 +75,6 @@ This is useful if the output could contain newlines, for example if the
 	default is `--no-null-input`.
 +
 This is useful if the input revision expressions could contain newlines.
-It is also useful if the input could contain _NUL_ characters; see the
-<<io,INPUT AND OUTPUT FORMATS>> section.
 
 [[io]]
 INPUT AND OUTPUT FORMAT
@@ -90,16 +93,13 @@ acts as a _terminator_, not a _separator_. In other words, the final
 line or record is also terminated by the terminator character.
 
 The mode `--stdin-mode=text` replaces each object name with the
-formatted commit, i.e. the format `%s` would transform the object name
-`abcdef012...` to `<subject>` without any termination. Like this:
+formatted commit, i.e. the format `%s` would transform some commit
+object name to `<subject>` without any termination. Like this:
 
 ----
 Did we not fix this in "<subject>"?
 ----
 
-Regarding input in this mode: using `-z` or `--null-input` makes sure
-that _NUL_ characters in the input are passed through correctly.
-
 It is safe to interactively read and write from this command since each
 record is immediately flushed.
 
@@ -202,8 +202,8 @@ not a good fit for the above use case.
 
 In short, it is straightforward to use these two commands if you use one
 process per line. It is much more work if you just want to use one
-process, but still doable. In contrast, this problem is just another
-shell pipeline with this command.
+process, but still doable. In contrast, this problem is solved with just
+another shell pipeline with this command.
 
 SEE ALSO
 --------
Range-diff against v4:
1:  9cb5cfd1ec3 = 1:  9cb5cfd1ec3 name-rev: wrap both blocks in braces
2:  14900271321 = 2:  14900271321 name-rev: run clang-format before factoring code
3:  724ec022894 = 3:  724ec022894 name-rev: factor code for sharing with a new command
4:  382efc3ddb8 = 4:  382efc3ddb8 name-rev: make dedicated --annotate-stdin --name-only test
5:  049a45e32bc ! 5:  425eb16728c format-rev: introduce builtin for on-demand pretty formatting
    @@ Documentation/git-format-rev.adoc (new)
     +	How to interpret standard input data:
     ++
     +--
    -+`revs`:: Each line or record (see the <<io,INPUT AND OUTPUT FORMATS>>
    ++`revs`;; Each line or record (see the <<io,INPUT AND OUTPUT FORMATS>>
     +	section) is interpreted as a commit. Any kind of revision
     +	expression can be used (see linkgit:gitrevisions[7]). Annotated
     +	tags are peeled (see linkgit:gitglossary[7]).
     ++
     +The argument `rev` is also accepted.
    -+`text`:: Formats all commit object names found in freeform text. These
    ++
    ++`text`;; Formats all commit object names found in freeform text. These
     +	must the full object names, i.e. abbreviated hexidecimal object
     +	names will not be interpreted.
     ++
    @@ Documentation/git-format-rev.adoc (new)
     +	of newline. This option cannot be negated.
     ++
     +This is useful if both the input and output could contain newlines or if
    -+the input could contain _NUL_ characters; see the <<io,INPUT AND OUTPUT
    -+FORMATS>> section.
    ++the input to this command also uses _NUL_ character termination; see the
    ++<<io,INPUT AND OUTPUT FORMATS>> section below.
    +++
    ++The mode `--stdin-mode=text` can have use for this option when it needs
    ++to process input like for example `git last-modified -z`; see the
    ++<<examples,EXAMPLES>> section below.
     +
     +`--null-output`::
     +`--no-null-output`::
    @@ Documentation/git-format-rev.adoc (new)
     +	default is `--no-null-input`.
     ++
     +This is useful if the input revision expressions could contain newlines.
    -+It is also useful if the input could contain _NUL_ characters; see the
    -+<<io,INPUT AND OUTPUT FORMATS>> section.
     +
     +[[io]]
     +INPUT AND OUTPUT FORMAT
    @@ Documentation/git-format-rev.adoc (new)
     +line or record is also terminated by the terminator character.
     +
     +The mode `--stdin-mode=text` replaces each object name with the
    -+formatted commit, i.e. the format `%s` would transform the object name
    -+`abcdef012...` to `<subject>` without any termination. Like this:
    ++formatted commit, i.e. the format `%s` would transform some commit
    ++object name to `<subject>` without any termination. Like this:
     +
     +----
     +Did we not fix this in "<subject>"?
     +----
     +
    -+Regarding input in this mode: using `-z` or `--null-input` makes sure
    -+that _NUL_ characters in the input are passed through correctly.
    -+
     +It is safe to interactively read and write from this command since each
     +record is immediately flushed.
     +
    @@ Documentation/git-format-rev.adoc (new)
     +
     +In short, it is straightforward to use these two commands if you use one
     +process per line. It is much more work if you just want to use one
    -+process, but still doable. In contrast, this problem is just another
    -+shell pipeline with this command.
    ++process, but still doable. In contrast, this problem is solved with just
    ++another shell pipeline with this command.
     +
     +SEE ALSO
     +--------

base-commit: 67006b9db8b772423ad0706029286096307d2567
-- 
2.54.0.13.g9c7419e39f8