Alex
Alex

Reputation: 35138

Git does not show change even the file changed

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?

Upvotes: 4

Views: 124

Answers (2)

Mark Adelsberger
Mark Adelsberger

Reputation: 45819

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.

Upvotes: 3

Adrian W
Adrian W

Reputation: 5036

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.

Upvotes: 1

Related Questions