threads / discuss / 22215

touching a file causes it to be listed using git diff-files

Subject: touching a file causes it to be listed using git diff-files

## tl;dr

6 messages between Jan 13, 2010 and Jan 14, 2010.

replies: 5people: 2as markdown or json

Stephen Bannasch· Jan 13, 2010, 23:57 UTC · lore
If I touch a file in the working directory (only changing it's last-modified) attribute it shows up when running git diff-files.
If I then run git status followed by git diff-files again it doesn't show up either time.
Is this an error?
Simple example:

[dev]$ git --version git version 1.6.5.3

[dev]$ git init t Initialized empty shared Git repository in /Users/stephen/dev/t/.git/

[dev]$ cd t
[t (master)]$ echo 'hi' > hello; git add hello; git commit -am 'initial commit'
[master (root-commit) f39d21a] initial commit
  1 files changed, 1 insertions(+), 0 deletions(-)
  create mode 100644 hello
[t (master)]$ git diff-files

[t (master)]$ git status # On branch master nothing to commit (working directory clean)

[t (master)]$ touch hello

[t (master)]$ git diff-files :100644 100644 45b983be36b73c0788dc9cbcb76cbb80fc7bb057 0000000000000000000000000000000000000000 M hello

[t (master)]$ git status # On branch master nothing to commit (working directory clean)

[t (master)]$ git diff-files
Jeff King· Jan 14, 2010, 03:02 UTC · re: Stephen Bannasch · lore

Re: touching a file causes it to be listed using git diff-files

On Wed, Jan 13, 2010 at 06:57:28PM -0500, Stephen Bannasch wrote:
Show 5 quoted lines
> If I touch a file in the working directory (only changing it's last-modified) attribute it shows up when running git diff-files.
> 
> If I then run git status followed by git diff-files again it doesn't show up either time.
> 
> Is this an error?

No. For performance reasons[1], plumbing commands like diff-files do not update the index. You must run "git update-index --refresh" manually.

User-facing porcelain commands like "git diff" and "git status" will refresh the index automatically. So "git status" will, as a side effect, refresh the index and impact further calls to diff-files.

-Peff

[1] Refreshing the index needs to stat all of the files. If you are writing a script using plumbing commands, you probably want to do the possibly-expensive refresh once at the start of your script, and then issue many diff commands. This makes a lot of sense for "diff-index", which otherwise does not need to touch the working tree at all. I'm not sure how much it helps with diff-files, though, which clearly ends up stat'ing the working tree file anyway.

Stephen Bannasch· Jan 14, 2010, 05:01 UTC · re: Jeff King · lore

Re: touching a file causes it to be listed using git diff-files

At 10:02 PM -0500 1/13/10, Jeff King wrote:
Show 24 quoted lines
>On Wed, Jan 13, 2010 at 06:57:28PM -0500, Stephen Bannasch wrote:
>
>> If I touch a file in the working directory (only changing it's last-modified) attribute it shows up when running git diff-files.
>>
>> If I then run git status followed by git diff-files again it doesn't show up either time.
>>
>> Is this an error?
>
>No. For performance reasons[1], plumbing commands like diff-files do not
>update the index. You must run "git update-index --refresh" manually.
>
>User-facing porcelain commands like "git diff" and "git status" will
>refresh the index automatically. So "git status" will, as a side effect,
>refresh the index and impact further calls to diff-files.
>
>-Peff
>
>[1] Refreshing the index needs to stat all of the files. If you are
>writing a script using plumbing commands, you probably want to do the
>possibly-expensive refresh once at the start of your script, and then
>issue many diff commands. This makes a lot of sense for "diff-index",
>which otherwise does not need to touch the working tree at all. I'm not
>sure how much it helps with diff-files, though, which clearly ends up
>stat'ing the working tree file anyway.
Jeff,
Thanks for that explanation.
Do you know if there is a plumbing command that will stat all of the files without listing the files that actually do need updating?
In the case where file1 has been only touched but file2 has been changed (and both are tracked) I'd like to stat both filesand then run diff-files as plumbing to see that only file2 has been changed in the working directory.
'git diff' also stats the files but strangely 'git diff --quiet' doesn't ???
In this example .snarfit.yml has real changes.
  $ touch nowebdb.cs
  $ git diff-files
  :100644 100644 22dab3b1c864d808da4d2be40196250ba879f68f 0000000000000000000000000000000000000000 M      .snarfit.yml
  :100644 100644 57982f13c69a91e3341d5b06021d31944633b5a3 0000000000000000000000000000000000000000 M      nowebdb.css
  $ git diff --quiet
  $ git diff-files
  :100644 100644 22dab3b1c864d808da4d2be40196250ba879f68f 0000000000000000000000000000000000000000 M      .snarfit.yml
  :100644 100644 57982f13c69a91e3341d5b06021d31944633b5a3 0000000000000000000000000000000000000000 M      nowebdb.css
  $ git diff --shortstat
   1 files changed, 2 insertions(+), 2 deletions(-)
  $ git diff-files
  :100644 100644 22dab3b1c864d808da4d2be40196250ba879f68f 0000000000000000000000000000000000000000 M      .snarfit.yml
I thought adding '-q' to update-index would cause it to run quietly but that is not the case:
  $ git diff-files
  :100644 100644 22dab3b1c864d808da4d2be40196250ba879f68f 0000000000000000000000000000000000000000 M      .snarfit.yml
  :100644 100644 57982f13c69a91e3341d5b06021d31944633b5a3 0000000000000000000000000000000000000000 M      nowebdb.css
  $ git update-index --refresh -q
  .snarfit.yml: needs update
  $ git diff-files
  :100644 100644 22dab3b1c864d808da4d2be40196250ba879f68f 0000000000000000000000000000000000000000 M      .snarfit.yml
Jeff King· Jan 14, 2010, 05:26 UTC · re: Stephen Bannasch · lore

Re: touching a file causes it to be listed using git diff-files

On Thu, Jan 14, 2010 at 12:01:46AM -0500, Stephen Bannasch wrote:
Show 7 quoted lines
> Do you know if there is a plumbing command that will stat all of the
> files without listing the files that actually do need updating?
> 
> In the case where file1 has been only touched but file2 has been
> changed (and both are tracked) I'd like to stat both filesand then run
> diff-files as plumbing to see that only file2 has been changed in the
> working directory.

Judging from the scripts in git itself, I think the recommended practice is to simply "git update-index --refresh -q >/dev/null".

> 'git diff' also stats the files but strangely 'git diff --quiet' doesn't ???

I can't reproduce that behavior here on the current "master". Old versions of git used to not do the index refresh for "diff". What version of git are you using?

-Peff
Stephen Bannasch· Jan 14, 2010, 05:57 UTC · re: Jeff King · lore

Re: touching a file causes it to be listed using git diff-files

At 12:26 AM -0500 1/14/10, Jeff King wrote:
Show 18 quoted lines
>On Thu, Jan 14, 2010 at 12:01:46AM -0500, Stephen Bannasch wrote:
>
>> Do you know if there is a plumbing command that will stat all of the
>> files without listing the files that actually do need updating?
>>
>> In the case where file1 has been only touched but file2 has been
>> changed (and both are tracked) I'd like to stat both filesand then run
>> diff-files as plumbing to see that only file2 has been changed in the
>> working directory.
>
>Judging from the scripts in git itself, I think the recommended practice
>is to simply "git update-index --refresh -q >/dev/null".
>
>> 'git diff' also stats the files but strangely 'git diff --quiet' doesn't ???
>
>I can't reproduce that behavior here on the current "master". Old
>versions of git used to not do the index refresh for "diff". What
>version of git are you using?
The most recent test was on:

$ git --version git version 1.6.6

Jeff King· Jan 14, 2010, 06:39 UTC · re: Stephen Bannasch · lore

Re: touching a file causes it to be listed using git diff-files

On Thu, Jan 14, 2010 at 12:57:05AM -0500, Stephen Bannasch wrote:
Show 10 quoted lines
> >> 'git diff' also stats the files but strangely 'git diff --quiet' doesn't ???
> >
> >I can't reproduce that behavior here on the current "master". Old
> >versions of git used to not do the index refresh for "diff". What
> >version of git are you using?
> 
> The most recent test was on:
> 
> $ git --version
> git version 1.6.6

Ah, OK, I figured it out. It is due to the early return of "--quiet". Since we know we are simply returning a status of "all the same" or "at least one difference", we can quit after finding the first difference.

So if you have two files, "a" and "b", you can try:
  $ touch a
  $ echo changes >b
  $ git diff --quiet
  $ git diff-files

and you will see that 'a' has been updated, because we traverse the files in sorted order and quit only after seeing 'b'.

But if you do instead:
  $ touch b
  $ echo change >a
  $ git diff --quiet
  $ git diff-files
we quit after 'a' and never refresh 'b'.

I don't think it should be considered a bug, though. "git diff" produces the correct result, and it is under no obligation to produce its side effect. If a caller really wants the index refreshed, he should use update-index instead.

-Peff

← back to recent threads