4

Is git broken or what are we doing wrong ? ;-)

We found out, that a file was changed in a recent version of the git repository and I tried to figure out when that was using whatchanged.

How can this be:

$ git checkout 27773b72432e86d308d25d666663f237e50aa3fd Tools/foo.php $ md5sum Tools/foo.php 85552061cae9832c11eb6607ac88e3d8 Tools/foo.php $ git checkout master Tools/foo.php $ md5sum Tools/foo.php f38f51232785a432af2d1bd8db4429ed Tools/foo.php 

BUT:

$ git whatchanged 27773b72432e86d308d25d666663f237e50aa3fd..master | grep foo.php # empty result 

How can this be?

3
  • 2
    You can configure git to ignore line endings for one thing. I don't think you can make md5sum ignore them :) Commented Jun 29, 2018 at 15:37
  • It's not line endings. It's a real code change. I just used md5sum to illustrate the problem Commented Jun 29, 2018 at 15:42
  • 1
    @Alex what happened when you apply a diff instead of whatchanged in final command? Commented Jun 29, 2018 at 16:12

2 Answers 2

3

The short answer is, you might want to try using

git whatchanged master..27773b72432e86d308d25d666663f237e50aa3fd 

(It's true that you really should probably use git log instead, but that isn't related to why it isn't doing what you expect.)

Here's some info that will help understand why:

That notation 27773b72432e86d308d25d666663f237e50aa3fd..master does not, as other users have suggested, mean "a range of commits starting at (but excluding) 27773b7 and ending at (and including) master". It sometimes reduces to that, but that isn't what it means. (And you'll see in a minute why the distinction is important.)

What it means is, "all commits that are reachable from master, but that are not reachable from 27773b7". (Where "reachable" means via parent pointers.)

Now if we assume that your commit graph looks like

 .... 27773b7 -- A -- B -- C <--(master) 

then this would reduce to the type of "range" others have identified. But in that case, you wouldn't be experiencing the problem. That's because you've shown that the file at 27773b7 is different from the file at C (master), which means either A or B or C must have changed it. If your commit graph looked like that.

So we can conclude that your commit graph doesn't look like that.

Another way it could look is

--- o -- A -- 27773b7 -- x ... \ B -- C <--(master) 

In this graph, 27773b7...master means just B and C, because A is not reachable by master, and while o is reachable by master, it's also reachable by 27773b7.

Now it's possible that the reason the file is different at 27773b7 is that it was changed either by A or by 27773b7 itself. In either case, using 27773b7^ (as other answer suggests) would not help.

Which brings me back to my point: if you really want to think of the A..B notation as defining a range, the start of the range can not be assumed to be A; if anything, you'd expect it to be the merge base between A and B (if there is one; sometimes it could just be the root of Bs commit hierarchy) - and that's equal to A only if A is reachable from B. And at any rate, you can't assume its a linear range of commits.

But understanding the subset of the commit graph it really indicates makes it more clear, that if A..B shows nothing you might need to try B..A.

Sign up to request clarification or add additional context in comments.

Comments

1

A range specified as A..B means from A to B but excluding A. See https://git-scm.com/docs/gitrevisions#gitrevisions-Theememtwo-dotRangeNotation

If revision 27773b7 is the only revision in which the file Tools/foo.php has been changed, then the range 27773b7..master excludes exactly that only change.

Update:

What you want is to include A but exclude all its parents. The shortcut for that is A^!. See https://git-scm.com/docs/gitrevisions#_other_rev_parent_shorthand_notations.

So, your command would be

$ git whatchanged 27773b7^! master | grep foo.php 

One last note: https://git-scm.com/docs/git-whatchanged suggests to use git log instead of git whatchanged.

To get a list of the file names only, you would say:

$ git log --name-only --format="" (other arguments here) 

That would make sure that when you grep that output you would not accidentally match a comment.

4 Comments

You might also add a suggestion about how to get the desired results.
No, this analysis is wrong. If the file at 27773b7 differs from the file at master, the issue isn't that the range is excluding a change that 27773b7 made.
@MarkAdelsberger git log (or git whatchanged) prints what has been changed in each revision in the range. It does not make a diff. So, when none of the selected revisions includes a change of the selected file, you won't see it.
@AdrianW - Yes, but that's beside the point. If, as you assume in your answer, 27773b7 were an ancestor of master, AND the file differs between 27773b7 and master, that would mean that some commit AFTER 27773b7 had changed the file. A change made by 27773b7 - the change that you keep pointing out would be excluded - would already be accounted for in the version of the file AT 27773b7, so it would not be a difference between that and the master version. This is not hard to test if you remain confused (it took me about 5 minutes to set up and verify).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.