From: Linus Torvalds Date: Wed, 27 Apr 2005 22:19:23 GMT Subject: Re: Finding file revisions Message-ID: In-Reply-To: <200504271423.37433.mason@suse.com> On Wed, 27 Apr 2005, Chris Mason wrote: > > So, new prog attached. New usage: > > file-changes [-c commit_id] [-s commit_id] file ... > > -c is the commit where you want to start searching > -s is the commit where you want to stop searching Your script will do some funky stuff, because you incorrectly think that the rev-list is sorted linearly. It's not. It's sorted in a rough chronological order, but you really can't do the "last" vs "cur" thing that you do, because two commits after each other in the rev-list listing may well be from two totally different branches, so when you compare one tree against the other, you're really doing something pretty nonsensical. diff-tree will happily compare trees that aren't related, so it will "work" in a sense, but it doesn't actually do what you think it does ;) So what you should do is basically something like open(RL, "rev-list $commit|") || die "rev-list failed"; while() { chomp; my $cur = $_; (so far so good) but then you should look at the _parents_ of that commit, ie do (NOTE NOTE NOTE! I'm a total perl idiot, so I'm not going to do this right): open(PARENT, "cat-file commit $cur") || die "cat-file failed"); while() { chomp; my @words = split; if ($words[1] == "tree") continue; if ($words[1] != "parent") break; test_diff($cur, $words[2]); } close(PARENT); } close(RL); and now your "test_diff()" thing can do the tree diff. That way you actually do "tree-diff" on the thing you should do, and it will show you _which_ way it changed in a merge (ie if you hit a merge-point, it will do a tree-diff against both parents, and show you which one had the difference - then you'll obviously usually see that same difference later on when you dig down to the actual changeset that did it too). Remember: time is not a nice linear stream. Linus