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

Finding file revisions

From
CMChris Mason <mason@suse.com>
Date
Apr 27, 2005, 16:50 UTC
Message-ID
<200504271251.00635.mason@suse.com>
Hello everyone,

I haven't seen a tool yet to find which changeset modified a given file, so I whipped up something. The basic idea is to:

for each changeset in rev-list
	for each file in diff-tree -r parent changeset
		match against desired files

Is there a faster way? This will scale pretty badly as the tree grows, but I usually only want to search back a few months in the history. So, it might make sense to limit the results by date or commit/tag.

Usage: file-changes [-c commit id] file1 ...

The file names can be perl regular expressions, and it will match any file starting with the expression listed. So "file-changes fs/ext" will show everything in ext2 and ext3.

Example output:
diff-tree -r 56022b4d00cae3ff816d3ff05d9f8a80e1517c60 9bd104d712d710d53c35166e40bd5fe24caf893e
8a796b48e757e56b50802c28abf28e0199c45ad9->2db368df614de4799be2d1baffb6563dbe1b8926 fs/ext2/inode.c
dbc8fd9bab639b84b8cc94fdbbf850b1e4bf1b2b->a4cd819734ba2eea9d5d21039deca62057f72d44 fs/ext3/inode.c
cat-file commit 9bd104d712d710d53c35166e40bd5fe24caf893e
    tree cd4e40eae003e29c0d3be2aa769c3b572ab1b488
    parent 56022b4d00cae3ff816d3ff05d9f8a80e1517c60
    author mason <mason@coffee> 1114617717 -0400
    committer mason <mason@coffee> 1114617717 -0400
    comments go here

This is meant for cut n' paste. If you find a changeset comment you like, run the diff-tree -r command on the first line to see a diff of the changeset (maybe I should add | diff-tree-helper here?)

-chris
#!/usr/bin/perl
use strict;

my $last; my $ret; my $i; my @wanted = (); my $matched; my $argc = scalar(@ARGV); my $commit;

sub print_usage() {
    print STDERR "usage: file-changes [-c commit] file_list\n";
    exit(1);
}
if ($argc < 1) {
    print_usage();
}
for ($i = 0 ; $i < $argc ; $i++)  {
    if ($ARGV[$i] eq "-c") {
    	if ($i == $argc - 1) {
	    print_usage();
	}
	$commit = $ARGV[++$i];
    } else {
	push @wanted, $ARGV[$i];
    }
}
if (!defined($commit)) {
    $commit = `commit-id`;
    if ($?) {
    	print STDERR "commit-id failed, try using -c to specify a commit\n";
	exit(1);
    }
    chomp $commit;
}
$last = $commit;
open(RL, "rev-list $commit|") || die "rev-list failed";
while(<RL>) {
    chomp;
    my $cur = $_;
    $matched = 0;
    if ($cur eq $last) {
        next;
    }
    # rev-list gives us the commits from newest to oldest
    open(DT, "diff-tree -r $cur $last|") || die "diff-tree failed";
    while(<DT>) {
        chomp;
	my @words = split;
	my $file = $words[3];
	# if the filename has whitespace, suck it in
	if (scalar(@words) > 4) {
	    if (m/$file(.*)/) {
	        $file .= $1;
	    }
	}
	foreach my $m (@wanted) {
	    if ($file =~ m/^$m/) {
		if (!$matched) {
		    print "diff-tree -r $cur $last\n";
		}
		print "$words[2] $file\n";
		$matched = 1;
	    }
	}
    }
    close(DT);
    if ($?) {
	$ret = $? >> 8;
	die "diff-tree failed with $ret";
    }
    if ($matched) {
	print "cat-file commit $last\n";
	open(COMMIT, "cat-file commit $last|") || die "cat-file $last failed";
	while(<COMMIT>) {
	    print "    $_";
	}
	close(COMMIT);
	if ($?) {
	    $ret = $? >> 8;
	    die "cat-file failed with $ret";
	}
	print "\n";
    }
    $last = $cur;
}
close(RL);
if ($?) {
    $ret = $? >> 8;
    die "rev-list failed with $ret";
}
Next: Linus Torvalds
Message 1 of 25 in “Finding file revisions”
  1. Chris MasonApr 27, 2005
  2. Linus TorvaldsApr 27, 2005
  3. Chris MasonApr 27, 2005
  4. Linus TorvaldsApr 27, 2005
  5. Chris MasonApr 27, 2005
  6. Simon FowlerApr 28, 2005
  7. Chris MasonApr 28, 2005
  8. Simon FowlerApr 28, 2005
  9. Chris MasonApr 28, 2005
  10. Kay SieversApr 28, 2005
  11. Tony LuckApr 28, 2005
  12. Thomas GlanzmannApr 28, 2005
  13. Kay SieversApr 28, 2005
  14. Chris MasonApr 28, 2005
  15. Linus TorvaldsApr 28, 2005
  16. Kay SieversApr 28, 2005
  17. Linus TorvaldsApr 28, 2005
  18. Chris MasonApr 28, 2005
  19. David WoodhouseApr 28, 2005
  20. David WoodhouseApr 28, 2005
  21. Thomas GleixnerApr 27, 2005
  22. Linus TorvaldsApr 28, 2005
  23. Thomas GleixnerApr 28, 2005
  24. Daniel BarkalowApr 28, 2005
  25. Chris MasonApr 28, 2005

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.