Is there a way to customize the output of git blame?

GitBlame

Git Problem Overview


git log has a nice --format option to specify how the output should be formatted.

But git blame doesn't seem to have an equivalent, although default output of blame is not quite human-friendly. I would like to see much less.

For example, instead of:

5600cab7 js/sidebar/VehicleGrid.js        (Rene Saarsoo    2009-10-08 18:55:24 +0000 127)    if (x > y) {
b5f1040c js/map/monitoring/VehicleGrid.js (Mihkel Muhkel   2010-05-31 07:20:13 +0000 128)        return x;

I would like to have:

5600cab7 Rene Saarsoo (1 year ago)     127:    if (x > y) {
b5f1040c Mihkel Muhkel (5 months ago)  128:        return x;

I figure that I could write a script to parse the output of git blame --porcelain but given the horrendous default output of blame I feel that somebody out there must have already done something about it.

Any ideas? Or any tips for implementing such a script?

Git Solutions


Solution 1 - Git

You can use alternate output format: git annotate or git blame -c.

You can change formatting of dates with --date=<format> option (or blame.date config variable), where <format> is one of relative, local, default, iso, rfc, short. See git-blame and git-log manpages for details.

Solution 2 - Git

Update Git 2.18 (Q2 2018): "git blame" learns to unhighlight uninteresting metadata from the originating commit on lines that are the same as the previous one, and also paint lines in different colors depending on the age of the commit.

See commit 0dc95a4, commit 25d5f52, commit cdc2d5f (24 Apr 2018) by Stefan Beller (stefanbeller).
(Merged by Junio C Hamano -- gitster -- in commit 3d24129, 30 May 2018)

> ## builtin/blame: add new coloring scheme config

> Add a config option that allows selecting the default color scheme for blame. The command line still takes precedence over the configuration.

git config now reports:

> blame.coloring::

> This determines the coloring scheme to be applied to blame output.
It can be 'repeatedLines', 'highlightRecent', or 'none' which is the default.


> ## builtin/blame: highlight recently changed lines

> Choose a different color for dates and imitate a 'temperature cool down' depending upon age. > > Similarly to the previous patch, this offers the command line option '--color-by-age' to enable this mode and the config option 'color.blame.highlightrecent' to select colors.

The documentation now adds:

> color.blame.highlightRecent

> This can be used to color the metadata of a blame line depending on age of the line. > > This setting should be set to a comma-separated list of color and date settings, starting and ending with a color, the dates should be set from oldest to newest.
The metadata will be colored given the colors if the the line was introduced before the given timestamp, overwriting older timestamped colors. > > Instead of an absolute timestamp relative timestamps work as well, e.g. > 2.weeks.ago is valid to address anything older than 2 weeks. > > It defaults to 'blue,12 month ago,white,1 month ago,red', which colors everything older than one year blue, recent changes between one month and one year old are kept white, and lines introduced within the last month are colored red.


> ## builtin/blame: dim uninteresting metadata lines

> When using git-blame, lots of lines contain redundant information, for example in hunks that consist of multiple lines, the metadata (commit name, author, date) are repeated.
A reader may not be interested in those, so offer an option to color the information that is repeated from the previous line differently.
Traditionally, we use CYAN for lines that are less interesting than others (e.g. hunk header), so go with that.

> The command line option '--color-lines' will trigger the coloring of repeated lines, and the config option 'color.blame.colorLines' is provided to select the color.
Setting the config option doesn't imply that repeated lines are colored.


Note: The "--color-lines" and "--color-by-age" options of "git blame"(man) have been missing, which are now documented with Git 2.34 (Q4 2021).

See commit 8c32856 (08 Oct 2021), and commit 38c356a (01 Oct 2021) by Bagas Sanjaya (bagasme).
(Merged by Junio C Hamano -- gitster -- in commit 871e42e, 18 Oct 2021)

> ## blame: document --color-* options
> Co-authored-by: Dr. Matthias St. Pierre
> Signed-off-by: Dr. Matthias St. Pierre
> Signed-off-by: Bagas Sanjaya

> Commit cdc2d5f ("builtin/blame: dim uninteresting metadata lines", 2018-04-23, Git v2.18.0-rc0 -- merge listed in batch #7) and 25d5f52 ("builtin/blame: highlight recently changed lines", 2018-04-23, Git v2.18.0-rc0 -- merge listed in batch #7) introduce --color-lines and --color-by-age options to git blame(man), respectively.
> While both options are mentioned in usage help, they aren't documented in git-blame(1).
> Document them.

git blame now includes in its man page: > [--color-lines] [--color-by-age] [--progress] [--abbrev=] > [ | --contents | --reverse ..] [--]

blame-options now includes in its man page: > ## --color-lines > > Color line annotations in the default format differently if they come from > the same commit as the preceding line. This makes it easier to distinguish > code blocks introduced by different commits. The color defaults to cyan and > can be adjusted using the color.blame.repeatedLines config option. > > ## --color-by-age > > Color line annotations depending on the age of the line in the default format. > The color.blame.highlightRecent config option controls what color is used for > each range of age.

git config now includes in its man page: > This setting should be set to a comma-separated list of color and > date settings, starting and ending with a color, the dates should be > set from oldest to newest. The metadata will be colored with the > specified colors if the line was introduced before the given > timestamp, overwriting older timestamped colors.

git config now includes in its man page: > It defaults to blue,12 month ago,white,1 month ago,red, which > colors everything older than one year blue, recent changes between > one month and one year old are kept white, and lines introduced > within the last month are colored red.

git config now includes in its man page: > Use the specified color to colorize line annotations for > git blame --color-lines, if they come from the same commit as the > preceding line. Defaults to cyan.


Original answer 2010

Considering web interface like Trac or Redmine integrate git blame results, I suppose such a parsing has already been done.

You can see in this Redmine Defect 3832 an example with this ruby script:

Solution 3 - Git

Going further with VonC's great answer, I made a more complete scale for the color.blame.highlightRecent config:

[color "blame"]
	highlightRecent = 237, 20 month ago, 238, 19 month ago, 239, 18 month ago, 240, 17 month ago, 241, 16 month ago, 242, 15 month ago, 243, 14 month ago, 244, 13 month ago, 245, 12 month ago, 246, 11 month ago, 247, 10 month ago, 248, 9 month ago, 249, 8 month ago, 250, 7 month ago, 251, 6 month ago, 252, 5 month ago, 253, 4 month ago, 254, 3 month ago, 231, 2 month ago, 230, 1 month ago, 229, 3 weeks ago, 228, 2 weeks ago, 227, 1 week ago, 226

Which has a scale from 20 month ago to now (last 4 weeks with different colors):

If you improved it, comment the gist! And star if you liked it ❤️

Solution 4 - Git

For me, the -s flag works, because all I need is the SHA1 ID, after which I look up the commit for details. A script definitely seems like overkill. Is it possible the -s flag was unavailable a year ago?

Solution 5 - Git

Since git log provides way more customization options for output, you can combine git blame, awk, xargs and git log to achieve what you want. E.g.

git --no-pager blame <filepath> -L1,+1 --porcelain | awk 'NR==1 {print $1}' | xargs git --no-pager log -1 --pretty=format:"%h - (%cd) %s - %an" --date=relative

This outputs something like this:

f8a66e80c - (5 months ago) Add gem: devise - elquimista

Basically what git blame and awk does above is get a full commit SHA, and xargs passes it to git log as an argument.

Solution 6 - Git

You can add this to your .gitconfig to get relative time (n days ago etc)

[blame]
    date = human

Solution 7 - Git

git blame --porcelain gives the information you need in a form that should be easy for a script to read, but is hard for a human. This would be a good place to start writing a script.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRene SaarsooView Question on Stackoverflow
Solution 1 - GitJakub NarębskiView Answer on Stackoverflow
Solution 2 - GitVonCView Answer on Stackoverflow
Solution 3 - GitUlysse BNView Answer on Stackoverflow
Solution 4 - GitGdalyaView Answer on Stackoverflow
Solution 5 - GitelquimistaView Answer on Stackoverflow
Solution 6 - GitimaliazharView Answer on Stackoverflow
Solution 7 - GitrjmunroView Answer on Stackoverflow