Combine color with conditional newlines in git log output

The final solution (without any known quirks) is at the bottom of this answer.

A workaround is to put a custom placeholder for the newlines in the format string (without using the %-b magic) and then postprocess the output with sed. In the example below the placeholder is the CHOMPABLENEWLINES string (of course you can replace it with any text of your choice, just make sure that it can't appear in your commit messages):

git log --format=format:"%C(yellow)%h %C(blue)%s %C(green)%ad %C(reset)%an%C(dim)CHOMPABLENEWLINES%b"|sed -e 's/CHOMPABLENEWLINES$//; s/CHOMPABLENEWLINES/\n\n/; $ s/$/\n/'

Colored output of git log with sed postprocessing

Note that this approach also fixes the problem that the effect of the %C directive extends only till the end of the current line (at least in git 2.7.4). As a result, in case of a multi-line body the color is applied only to its first line. Compare:

# Only the first line of a multiline message body is colored
git log --format=format:"%C(yellow)%h %C(blue)%s %C(green)%ad %C(reset)%an%n%n%Cred%b"

Colored output of git log without sed postprocessing

# Entire multiline message body is colored (though a byproduct of this
# is that the color setting persists beyond the current
# command - note the red prompt following the output)
git log --format=format:"%C(yellow)%h %C(blue)%s %C(green)%ad %C(reset)%an%CredCHOMPABLENEWLINES%b"|sed -e 's/CHOMPABLENEWLINES$//; s/CHOMPABLENEWLINES/\n\n/; $ s/$/\n/'

Colored output of git log with sed postprocessing

The undesirable side effect of persisted color setting can be counteracted by ending the format string with a %C(reset) directive. Then we also need a custom marker for the end of the %b placeholder, since the visual end of line is no longer an actual end of line from sed's point of view. In the example below the string ENDOFBODY is used as such a marker (and of course you must select it so that it doesn't appear in your expected output).

# This version works with GNU sed. For a portable version (including BSD
# and MacOS X systems) scroll down a little more
git log --format=tformat:"%C(yellow)%h %C(blue)%s %C(green)%ad %C(reset)%an%CredCHOMPABLENEWLINES%bENDOFBODY%C(reset)"|sed -e 's/CHOMPABLENEWLINESENDOFBODY//; s/CHOMPABLENEWLINES/\n\n/; s/ENDOFBODY//'

Output of the final version

Some versions or setups of git disable colored output when it doesn't directly go to terminal. In such cases you must also provide the --color=always option to git log.


The final solution, using only portable features of sed, is as follows:

git log --color=always --format=tformat:"%C(yellow)%h %C(blue)%s %C(green)%ad %C(reset)%an%C(red)CHOMPABLENEWLINES%bENDOFBODY%C(reset)"|sed -e 's/CHOMPABLENEWLINESENDOFBODY//; s/CHOMPABLENEWLINES/\'$'\n''\'$'\n/; s/ENDOFBODY//'

Tags:

Git

Git Log