I am trying to develop a format string to pass to git log --pretty
so that each log entry ends in a full commit message, yet each log entry is separated by exactly one empty line. The problem is that some full commit messages end in a newline, and some do not.
For example, let's say I have two commits, abc1234
and def5678
, but only abc1234
contains a newline at the end of the full commit message. Outputting the raw commit contents on the command line would look something like this:
[prompt]$ git cat-file commit abc1234
(...)
Title FOO
Full commit message FOO
[prompt]$ git cat-file commit def5678
(...)
Title BAR
Full commit message BAR[prompt]$
Note how the new shell prompt appears at the end of the last line of output, demonstrating that commit def5678
does not contain a newline at the end of the full commit message.
Let's say that def5678
is the parent of abc1234
and I want to output a simple log where each entry contains only the short commit hash, title line, and full commit message. I might try something like this:
[prompt]$ git log --graph --pretty='commit %h%n%B' abc1234
* commit abc1234
| Title FOO
|
| Full commit message FOO
|
* commit def5678
| Title BAR
|
| Full commit message BAR
* commit <parent of def5678>
(...)
Note the spacing between the log entries. The entries for abc1234
and def5678
are separated by a blank line (save for the graph character), yet the entries for def5678
and its parent are not.
How can I construct a format string so that the spacing is consistent, even with inconsistent termination of full commit messages? The builtin pretty formats of medium
, full
, fuller
, and email
already do that, but I want to be able to construct arbitrary format strings to do the same thing.
I've experimented with the %+B
, %-B
and % B
sequences (and their %b
and %n
equivalents), but I just can't seem to get consistent spacing.
I'm using Git 2.17.0 if that makes a difference.
As @jthill alluded to in the comments, and expressed in git-log(1)
:
If you add a
-
(minus sign) after%
of a placeholder, all consecutive line-feeds immediately preceding the expansion are deleted if and only if the placeholder expands to an empty string.
Therefore, if we can find a format sequence %<token>
that will always expand to the empty string, we can use %-<token>%n
to replace zero or more consecutive newlines with a single newline. As it turns out, there is such a format sequence: %C()
, the empty color selector. (Normally the parentheses enclose a non-empty string that specifies coloration to be used in the log output. See git-log(1)
and git-config(1)
for more details.)
The fact that %C()
evaluates to the empty string instead of causing an error seems like a happy accident instead of something to lay one's hat upon, but at least for Git 2.17, it does the trick. At this point, I have enough information to answer my own question.
To maintain consistent separation between log entries output by git log --pretty=<tformat>
, where <tformat>
may or may not evaluate to a string ending in a newline, append %-C()%n
to <tformat>
. For example:
[prompt]$ git log --graph --pretty='commit %h%n%B%-C()%n' abc1234
* commit abc1234
| Title FOO
|
| Full commit message FOO
|
* commit def5678
| Title BAR
|
| Full commit message BAR
|
* commit <parent of def5678>
(...)