GIT-COMMENT(1) General Commands Manual GIT-COMMENT(1)

git-commentadd comments from commit messages

git comment [--all] [--comment-start string] [--comment-lead string] [--comment-end string] [--min-group lines] [--min-repeat lines] [--no-repeat] [--pretty format] [options ...] [--] file

The git-comment command adds comments to a file showing the commit messages which last modified each group of lines. By default only commit messages with bodies and which modified groups of at least 2 lines are added. Each comment contains the abbreviated commit hash and the commit summary, followed by the commit body.

git-comment accepts all the options of git-blame(1) in addition to the following:

Include all commit messages. The default is to include only commit messages with bodies (lines after the summary).
string
Start comments with string. The default is the value of comment.start or ‘/*’.
string
Continue comments with the leading string. The default is the value of comment.lead or ‘ *’.
string
End comments with string. The default is the value of comment.end or ‘ */’.
lines
Add comments only for groups of at least lines. The default is 2 lines.
lines
Avoid repeating a comment if it occurred in the last lines. The default is 30 lines.
Avoid repeating comments entirely.
format
Set the pretty-print format to use for commit messages. The default is the value of comment.pretty or ‘format:%h %s%n%n%-b’. See git-show(1).

For files with ‘#’ comments:

git config comment.start '#'
git config comment.lead '#'
git config comment.end ''

Add as many comments as possible:

git comment --all --min-group 1 --min-repeat 1

git-blame(1)

September 10, 2021 OpenBSD 7.4

git-comment.pl in git

#!/usr/bin/env perl
# Copyright (C) 2021  June McEnroe <june@causal.agency>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

use lib (split(/:/, $ENV{GITPERLLIB} || '/usr/local/share/perl5'));

use strict;
use warnings;
use Getopt::Long qw(:config pass_through);
use Git;

my $repo = Git->repository();

my ($all, $minGroup, $minRepeat, $noRepeat) = (0, 2, 30, 0);
my $commentStart = $repo->config('comment.start') // "/*";
my $commentLead = $repo->config('comment.lead') // " *";
my $commentEnd = $repo->config('comment.end') // " */";
my $pretty = $repo->config('comment.pretty') // 'format:%h %s%n%n%-b';
GetOptions(
	'all' => \$all,
	'comment-start=s' => \$commentStart,
	'comment-lead=s' => \$commentLead,
	'comment-end:s' => \$commentEnd,
	'min-group=i' => \$minGroup,
	'min-repeat=i' => \$minRepeat,
	'no-repeat' => \$noRepeat,
	'pretty=s' => \$pretty,
) or die;

sub printComment {
	my ($indent, $summary, @body) = @_;
	print "$indent$commentStart $summary";
	if (@body) {
		print "\n";
		foreach (@body) {
			print "$indent$commentLead";
			print " $_" if $_;
			print "\n";
		}
		print "$indent$commentEnd\n" if $commentEnd;
	} else {
		print "$commentEnd\n";
	}
}

my ($pipe, $ctx) = $repo->command_output_pipe('blame', '--porcelain', @ARGV);

my ($commit, $nr, $group, $printed, %message, %nrs);
while (<$pipe>) {
	chomp;
	if (/^([[:xdigit:]]+) \d+ (\d+) (\d+)/) {
		($commit, $nr, $group, $printed) = ($1, $2, $3, 0);
		next if $message{$commit};
		if ($commit =~ /^0+$/) {
			$message{$commit} = ['Not committed yet'];
			next;
		}
		my @message = $repo->command(
			'show', '--no-patch', "--pretty=$pretty", $commit
		);
		$message{$commit} = \@message;
	} elsif (/^\t(\s*)(.*)/) {
		my ($indent, $line) = ($1, $2);
		unless ($printed || $line =~ /^[})]?;?$/) {
			$printed = 1;
			if (
				$group >= $minGroup &&
				!($noRepeat && $nrs{$commit}) &&
				!($nrs{$commit} && $nr < $nrs{$commit} + $minRepeat) &&
				($all || @{$message{$commit}} > 1)
			) {
				$nrs{$commit} = $nr;
				printComment($indent, @{$message{$commit}});
			}
		}
		print "$indent$line\n";
	}
}

$repo->command_close_pipe($pipe, $ctx);