git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Blamming a diff between two commits?

From
Thomas Rast <trast@student.ethz.ch>
Date
Feb 17, 2009, 14:09 UTC
Message-ID
<200902171509.21434.trast@student.ethz.ch>
In-Reply-To
<499AB8A1.7090909@datacom.ind.br>
Samuel Lucas Vaz de Mello wrote:
> Is there any way to git blame (or annotate) a diff between two
> commits?

Piecing it together from existing tools isn't really hard, and made for a nice distraction.

Call it as './git-blame-diff.perl HEAD^ HEAD' or so.

This lacks proper argument checking and a chdir to the repository top level. Maybe you could fill in the gaps and shape it as a contrib patch? For bonus points, change it so that the workdir version can be used as the new side of the diff, by omitting the second argument.

--- 8< --- #!/usr/bin/perl -w

sub parse_hunk_header {
	my ($line) = @_;
	my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) =
	    $line =~ /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
	$o_cnt = 1 unless defined $o_cnt;
	$n_cnt = 1 unless defined $n_cnt;
	return ($o_ofs, $o_cnt, $n_ofs, $n_cnt);
}
sub get_blame_prefix {
	my ($line) = @_;
	$line =~ /^([0-9a-f]+\s+\([^\)]+\))/ or die "bad blame output: $line";
	return $1;
}

my ($oldrev, $newrev) = @ARGV; open($diff, '-|', 'git', '--no-pager', 'diff', $oldrev, $newrev) or die;

my ($pre, $post);
my $filename;
while (<$diff>) {
	if (m{^diff --git ./(.*) ./\1$}) {
		$filename = $1;
	} elsif (m{^(\+\+\+|---) ./$filename$}) {
		# ignore
	} elsif (m{^@@ }) {
		my ($o_ofs, $o_cnt, $n_ofs, $n_cnt)
			= parse_hunk_header($_);
		my $o_end = $o_ofs + $o_cnt;
		my $n_end = $n_ofs + $n_cnt;
		open($pre, '-|', 'git', 'blame', "-L$o_ofs,$o_end",
		     $oldrev, '--', $filename) or die;
		open($post, '-|', 'git', 'blame', "-L$n_ofs,$n_end",
		     $newrev, '--', $filename) or die;
	} elsif (m{^ }) {
		print get_blame_prefix(scalar <$pre>), "\t", $_;
		scalar <$post>; # discard
	} elsif (m{^\-}) {
		print get_blame_prefix(scalar <$pre>), "\t", $_;
	} elsif (m{^\+}) {
		print get_blame_prefix(scalar <$post>), "\t", $_;
	} 
}
-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Previous: Matthieu MoyNext: Thomas Rast
Message 6 of 10 in “Blamming a diff between two commits?”
  1. Samuel Lucas Vaz de MelloFeb 17, 2009
  2. Johannes SchindelinFeb 17, 2009
  3. Samuel Lucas Vaz de MelloFeb 17, 2009
  4. Johannes SchindelinFeb 17, 2009
  5. Matthieu MoyFeb 17, 2009
  6. Thomas RastFeb 17, 2009
  7. Thomas RastFeb 20, 2009
  8. Jan HudecFeb 22, 2009
  9. Matthieu MoyFeb 22, 2009
  10. Jan HudecFeb 22, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.