threads / discuss / 9878

Blaming diffs

Subject: Blaming diffs

## tl;dr

7 messages between Sep 16, 2007 and Sep 17, 2007.

replies: 6people: 5as markdown or json

Mike Hommey· Sep 16, 2007, 16:38 UTC · lore
Hi,

It seems to me there is no tool to "blame diffs", i.e. something to know what commit(s) is(are) responsible for a set of changes.

For example, the following script tries to get the set of commits involved in the changes between $A and $B. Note it only works for text additions.

git diff --unified=0 $A $B | awk 'BEGIN { FS="(^(--- a/|+++ b/)|^@@ -[0-9,]+ \\+| @@)" } /^---/ || ( /^+++ b\/(.*)/ && file=="" ) { file = $2 } /^@@/ {split($2, a, /,/); a[2] = a[2] ? a[2] + a[1] - 1 : a[1]; print "git blame -l -L " a[1] "," a[2], "'$A..$B'", file }' | sh | cut -f 1 -d " " | sort -u
Has anyone tried to work on something similar yet ?

If not, as git users, what kind of output would you expect from such a tool, and where do you think this should lie (extension to git diff, or separate tool) ?

Cheers,
Mike
Frank Lichtenheld· Sep 16, 2007, 17:05 UTC · re: Mike Hommey · lore

Re: Blaming diffs

On Sun, Sep 16, 2007 at 06:38:29PM +0200, Mike Hommey wrote:
Show 14 quoted lines
> It seems to me there is no tool to "blame diffs", i.e. something to know
> what commit(s) is(are) responsible for a set of changes.
> 
> For example, the following script tries to get the set of commits
> involved in the changes between $A and $B. Note it only works for text
> additions. 
> 
> git diff --unified=0 $A $B | awk 'BEGIN { FS="(^(--- a/|+++ b/)|^@@ -[0-9,]+ \\+| @@)" } /^---/ || ( /^+++ b\/(.*)/ && file=="" ) { file = $2 } /^@@/ {split($2, a, /,/); a[2] = a[2] ? a[2] + a[1] - 1 : a[1]; print "git blame -l -L " a[1] "," a[2], "'$A..$B'", file }' | sh | cut -f 1 -d " " | sort -u
> 
> Has anyone tried to work on something similar yet ?
> 
> If not, as git users, what kind of output would you expect from such a
> tool, and where do you think this should lie (extension to git diff, or
> separate tool) ?

What do you use for $A and $B? commits? What is the difference between your script and "git log --pretty=format:%H $A..$B" then?

Gruesse,
-- 
Frank Lichtenheld <frank@lichtenheld.de>
www: http://www.djpig.de/
Mike Hommey· Sep 16, 2007, 17:16 UTC · re: Frank Lichtenheld · lore

Re: Blaming diffs

On Sun, Sep 16, 2007 at 07:05:35PM +0200, Frank Lichtenheld <frank@lichtenheld.de> wrote:
Show 19 quoted lines
> On Sun, Sep 16, 2007 at 06:38:29PM +0200, Mike Hommey wrote:
> > It seems to me there is no tool to "blame diffs", i.e. something to know
> > what commit(s) is(are) responsible for a set of changes.
> > 
> > For example, the following script tries to get the set of commits
> > involved in the changes between $A and $B. Note it only works for text
> > additions. 
> > 
> > git diff --unified=0 $A $B | awk 'BEGIN { FS="(^(--- a/|+++ b/)|^@@ -[0-9,]+ \\+| @@)" } /^---/ || ( /^+++ b\/(.*)/ && file=="" ) { file = $2 } /^@@/ {split($2, a, /,/); a[2] = a[2] ? a[2] + a[1] - 1 : a[1]; print "git blame -l -L " a[1] "," a[2], "'$A..$B'", file }' | sh | cut -f 1 -d " " | sort -u
> > 
> > Has anyone tried to work on something similar yet ?
> > 
> > If not, as git users, what kind of output would you expect from such a
> > tool, and where do you think this should lie (extension to git diff, or
> > separate tool) ?
> 
> What do you use for $A and $B? commits? What is the difference between
> your script and "git log --pretty=format:%H $A..$B"
> then?

In my typical usecase, $A is upstream and $B is HEAD. What happens is that my work branch includes some changes that have been merged upstream and some others that are not yet, or won't because it's not appropriate. I obviously occasionally merge the upstream branch back, in which case my changes that were committed upstream don't appear in a git diff $A $B anymore.

git log --pretty=format:%H $A..$B would give me the list of all commits that occurred on my branch, while my script only gives the commits containing changes that are still not applied upstream.

Mike
Christian Couder· Sep 17, 2007, 04:59 UTC · re: Mike Hommey · lore

Re: Blaming diffs

Le dimanche 16 septembre 2007, Mike Hommey a écrit :
> Hi,
>
> It seems to me there is no tool to "blame diffs", i.e. something to know
> what commit(s) is(are) responsible for a set of changes.

I don't know if that's what you are looking for but perhaps you could use "git bisect run". You just need to pass it a script that returns 1 when it finds the changes and 0 otherwise. (See git-bisect man page.)

Sometimes ago I sent a patch that would allow "!" after "git bisect run", but it seems to have been forgotten. This patch makes it possible to use:

git bisect run ! grep some_stuff file1 file2...

This would give you the commit where some_stuff was introduced in file1 or file2...

Regards, Christian.

Shawn O. Pearce· Sep 17, 2007, 04:57 UTC · re: Christian Couder · lore

Re: Blaming diffs

Christian Couder <chriscool@tuxfamily.org> wrote:
Show 8 quoted lines
> Le dimanche 16 septembre 2007, Mike Hommey a écrit :
> >
> > It seems to me there is no tool to "blame diffs", i.e. something to know
> > what commit(s) is(are) responsible for a set of changes.
> 
> I don't know if that's what you are looking for but perhaps you could 
> use "git bisect run". You just need to pass it a script that returns 1 when 
> it finds the changes and 0 otherwise. (See git-bisect man page.)
That's very inefficient to search for something...
 
Show 7 quoted lines
> Sometimes ago I sent a patch that would allow "!" after "git bisect run", 
> but it seems to have been forgotten. This patch makes it possible to use:
> 
> git bisect run ! grep some_stuff file1 file2...
> 
> This would give you the commit where some_stuff was introduced in file1 or 
> file2...
Is `git log -Ssome_stuff -- file1 file2` somehow not working for you?
-- 
Shawn.
Christian Couder· Sep 17, 2007, 05:40 UTC · re: Shawn O. Pearce · lore

Re: Blaming diffs

Le lundi 17 septembre 2007, Shawn O. Pearce a écrit :
Show 6 quoted lines
> Christian Couder <chriscool@tuxfamily.org> wrote:
> > I don't know if that's what you are looking for but perhaps you could
> > use "git bisect run". You just need to pass it a script that returns 1
> > when it finds the changes and 0 otherwise. (See git-bisect man page.)
>
> That's very inefficient to search for something...

Perhaps but you can search using whatever script or command you want/know. You are not limited by those implemented in git.

You can also make it more efficient with "git bisect {start,good,bad}".

Regards, Christian.

Junio C Hamano· Sep 17, 2007, 05:41 UTC · re: Christian Couder · lore

Re: Blaming diffs

Christian Couder <chriscool@tuxfamily.org> writes:
Show 12 quoted lines
> Le lundi 17 septembre 2007, Shawn O. Pearce a écrit :
>> Christian Couder <chriscool@tuxfamily.org> wrote:
>> > I don't know if that's what you are looking for but perhaps you could
>> > use "git bisect run". You just need to pass it a script that returns 1
>> > when it finds the changes and 0 otherwise. (See git-bisect man page.)
>>
>> That's very inefficient to search for something...
>
> Perhaps but you can search using whatever script or command you want/know. 
> You are not limited by those implemented in git.
>
> You can also make it more efficient with "git bisect {start,good,bad}".

I _think_ the inefficiency Shawn refers to is that "git bisect" wrapper inherently is based on checking out the revision. It is similar to "filter-branch --tree-filter" being much more inefficient than "filter-branch --index-filter" (the latter only works with index while the former does a full checkout).

The underlying "git rev-list --bisect" can be used to ask for sequence of commits to check if your check does not require a full checkout, but there is no wrapper like "git bisect" that uses that mode of operation.

← back to recent threads