* git-diff-tree(1) can already do the important parts of git-format-rev(1)
@ 2026-10-15 10:35 Kristoffer Haugsbakk
2026-10-15 18:42 ` Kristoffer Haugsbakk
0 siblings, 1 reply; 3+ messages in thread
From: Kristoffer Haugsbakk @ 2026-10-15 10:35 UTC (permalink / raw)
To: git
git-format-rev(1) is an experimental command from Git 2.55.0. It was
introduced because no command was found for the use case of pretty
formatting one revision at a time from standard in (stdin). See
[Discussion] on the doc.
🔗 Discussion: https://git-scm.com/docs/git-format-rev#_discussion
But yesterday someone was reading through all of git-rev-list(1). And
this is one of the examples:
git rev-list HEAD |
git diff-tree --stdin --format=medium -p
And if one turns on merge display and off patch display.
git rev-list HEAD |
git diff-tree --stdin --format=medium --no-patch -m
You have “on-demand pretty formatting”
And it’s even *better*. Because it supports `--notes` like git-log(1)
does. And probably everything else that the rev-list machinery
supports. git-format-rev(1) does not. The `--notes` display is not part
of pretty formatting itself.
(There are also some minor extra things you get from the pretty formats
(the built-in ones) used with git-log(1) and co. that you don’t get with
git-format-rev(1). Because git-format-rev(1) just uses `pretty.h` while
I think git-log(1) and co. use `log-tree.h`.)
But you do have the issue that you have to pass object names. With
git-format-rev(1) you can pass revision expressions. But you can just
stick a revs-to-OID pipe in front of it:
... | git cat-file --batch-command='%(objectname)' | ...
And then that’s taken care of.[2]
That’s for `git format-rev --stdin-mode=revs`. But there is a
concillation price in that `git format-rev --stdin-mode=text` can format
object names (full hex) in running text (by just tweaking the function
that `git name-rev --annotate-stdin` calls). But that was a nice bonus
and not why the command was made.
† 1: git-format-rev(1) also supports NUL-terminated input in order to
deal with multiline revision expressions.[3] And `-Z` for
git-cat-file(1) does that too (both input and output), so the pair
git-cat-file(1)/git-diff-tree(1) is equally expressive.
🔗 3: https://lore.kernel.org/git/e8bb57a2-8eff-4f72-96ca-72d8880901e0@gmail.com/
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: git-diff-tree(1) can already do the important parts of git-format-rev(1)
2026-10-15 10:35 git-diff-tree(1) can already do the important parts of git-format-rev(1) Kristoffer Haugsbakk
@ 2026-10-15 18:42 ` Kristoffer Haugsbakk
2026-10-17 16:34 ` Kristoffer Haugsbakk
0 siblings, 1 reply; 3+ messages in thread
From: Kristoffer Haugsbakk @ 2026-10-15 18:42 UTC (permalink / raw)
To: git
On Thu, Oct 15, 2026, at 12:35, Kristoffer Haugsbakk wrote:
> git-format-rev(1) is an experimental command from Git 2.55.0. It was
> introduced because no command was found for the use case of pretty
> formatting one revision at a time from standard in (stdin). See
> [Discussion] on the doc.
>
> 🔗 Discussion: https://git-scm.com/docs/git-format-rev#_discussion
>
> But yesterday someone was reading through all of git-rev-list(1). And
> this is one of the examples:
>
> git rev-list HEAD |
> git diff-tree --stdin --format=medium -p
>
> And if one turns on merge display and off patch display.
>
> git rev-list HEAD |
> git diff-tree --stdin --format=medium --no-patch -m
>
> You have “on-demand pretty formatting”
But for multiline pretties you need NUL termination. And this is what
`-z` says:
When --raw, --numstat, --name-only or --name-status has been given,
do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted
as explained for the configuration variable core.quotePath (see
git-config(1)).
So `-z` only applies to some primitive and name-centric diff
formats. And that’s why my later footnote is wrong:
>[snip]
>
> † 1: git-format-rev(1) also supports NUL-terminated input in order to
> deal with multiline revision expressions.[3] And `-Z` for
> git-cat-file(1) does that too (both input and output), so the pair
> git-cat-file(1)/git-diff-tree(1) is equally expressive.
>
> 🔗 3: https://lore.kernel.org/git/e8bb57a2-8eff-4f72-96ca-72d8880901e0@gmail.com/
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: git-diff-tree(1) can already do the important parts of git-format-rev(1)
2026-10-15 18:42 ` Kristoffer Haugsbakk
@ 2026-10-17 16:34 ` Kristoffer Haugsbakk
0 siblings, 0 replies; 3+ messages in thread
From: Kristoffer Haugsbakk @ 2026-10-17 16:34 UTC (permalink / raw)
To: git
On Thu, Oct 15, 2026, at 20:42, Kristoffer Haugsbakk wrote:
> On Thu, Oct 15, 2026, at 12:35, Kristoffer Haugsbakk wrote:
>>[snip]
>>
>> git rev-list HEAD |
>> git diff-tree --stdin --format=medium --no-patch -m
>>
>> You have “on-demand pretty formatting”
>
> But for multiline pretties you need NUL termination. And this is what
> `-z` says:
>
> When --raw, --numstat, --name-only or --name-status has been given,
> do not munge pathnames and use NULs as output field terminators.
>
> Without this option, pathnames with "unusual" characters are quoted
> as explained for the configuration variable core.quotePath (see
> git-config(1)).
>
> So `-z` only applies to some primitive and name-centric diff
> formats. And that’s why my later footnote is wrong:
>
>>[snip]
>>
>> † 1: git-format-rev(1) also supports NUL-terminated input in order to
>> deal with multiline revision expressions.[3] And `-Z` for
>> git-cat-file(1) does that too (both input and output), so the pair
>> git-cat-file(1)/git-diff-tree(1) is equally expressive.
>>
>> 🔗 3: https://lore.kernel.org/git/e8bb57a2-8eff-4f72-96ca-72d8880901e0@gmail.com/
But I was wrong again. git-diff-tree(1) supports NUL for pretty printing
(`-v`). I was only looking at one single output. But with “separator”
delimiters (either newline or NUL) there is no delimiter for one single
record (output). That’s why it didn’t show up for me. (thanks `cat -A`)
But the separator behavior is a problem. Because when consuming input
piecemeal (like reading from a shell coproc) you need a terminator. But
the `log-tree.c` functionality very diligently keeps itself to using
separators:
1. You feed one commit: you get the output with no delimiter
2. You feed another one: now there are two output records so a delimiter
is needed. *Then* a separator is printed right before the record
3. Repeat
4. Of course the final record will not have a delimiter at the end
I experimented with forcing terminator behavior but it seems that
git-diff-tree(1) is just unwilling.
But it seems that one can just add a `--use-terminator` option
commands that use `tree-log.c` (I think by adding it to `revision.c:
handle_revision_opt`). Then I can use a git-diff-tree(1) that acts like
git-format-rev(1) with `--stdin-mode=revs`... and in fact a bit better
(see previous).
All of this for pretty-printing (`-z`). For `--patch` (cf. raw diff)
there is no NUL delimiter support.
THE CONTEXT
I am working on a shell script that needs to construct a git-log(1)/
git-format-patch(1)-like output. Each commit message describes a range
of commits. And the optional patch/diff output is the interdiff between
each range if they happen to share the same base. This is like
git-format-patch(1) with `--interdiff`. So what I need for each
record/entry in the log:
1. A commit message
2. An interdiff if wanted and if it can be produced
What I have done, respectively:
1. A coproc for `git format-rev --stdin-mode=revs`
2. Individual calls to git-diff-tree(1) (not `--stdin`)
Somewhat incidental to this, I figured out that git-diff-tree(1) can
almost replace `git format-rev --stdin`.
But when I turned to git-diff-tree(1) and tried to transform (2) into a
coproc. But that seems to not be feasible, since it seems that
NUL-termination is not supported for diffs that a person would want
to look at.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-17 16:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 10:35 git-diff-tree(1) can already do the important parts of git-format-rev(1) Kristoffer Haugsbakk
2026-10-15 18:42 ` Kristoffer Haugsbakk
2026-10-17 16:34 ` Kristoffer Haugsbakk
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox