git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / mirror / code / Atom feed
* Reset sometimes updates mtime
@ 2015-07-09 14:02 Dennis Kaarsemaker
  2015-07-09 17:56 ` Junio C Hamano
  0 siblings, 1 reply; 3+ messages in thread
From: Dennis Kaarsemaker @ 2015-07-09 14:02 UTC (permalink / raw)
  To: git

I'm seeing some behaviour with git reset that I find odd. Basically if I
do

git fetch && \
git reset --hard simple-tag-that-points-to-the-current-commit

sometimes the reset will update the mtime of all files and directories
in the repo and sometimes it will leave them alone. Changing it to

git fetch && \
git status && \
git reset --hard simple-tag-that-points-to-the-current-commit

Cause the mtime update to reliably not happen.

Bad thing is that I am relying on the mtime updates not to happen if the
files don't actually change. Is this an assumption I can safely make? If
it is, then I'll debug further (e.g. I don't even know yet if the file
gets rewritten or just touched, why the index gets updated as well
etc.).

-- 
Dennis Kaarsemaker
http://www.kaarsemaker.net

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Reset sometimes updates mtime
  2015-07-09 14:02 Reset sometimes updates mtime Dennis Kaarsemaker
@ 2015-07-09 17:56 ` Junio C Hamano
  2015-07-10  7:30   ` Dennis Kaarsemaker
  0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2015-07-09 17:56 UTC (permalink / raw)
  To: Dennis Kaarsemaker; +Cc: git

Dennis Kaarsemaker <dennis@kaarsemaker.net> writes:

> I'm seeing some behaviour with git reset that I find odd. Basically if I
> do
>
> git fetch && \
> git reset --hard simple-tag-that-points-to-the-current-commit
>
> sometimes the reset will update the mtime of all files and directories
> in the repo and sometimes it will leave them alone. Changing it to
>
> git fetch && \
> git status && \
> git reset --hard simple-tag-that-points-to-the-current-commit
>
> Cause the mtime update to reliably not happen.

If my theory on what is happening is correct, I do not think there
is any bug in what "reset --hard" is doing.

My theory is that something is causing the stat info that is cached
in your index and the lstat(2) return you get from your working tree
files go out of sync.  Even though you are not actively touching any
working tree files (otherwise, you wouldn't be complaining about
mtime changing in the first place), perhaps your build of Git
records timestamps in NS but your filesystem and the operating
system does not preserve nanosecond resolution of timestamps when it
evicts inode data from the core, or something like that?  If that is
what is happening, I think that "fetch" is a red herring, but any
operation that takes some time and/or hits filesystem reasonably
hard would trigger it.

And the reason why I say there is no bug in what "reset --hard" is
doing here, if the above theory is correct, is because:

 - The user asked "reset --hard" to "make sure that my working tree
   files are identical to those of HEAD";

 - "reset --hard" looks at lstat(2) return and the cached stat info
   in the index and find them not to match.  It can do one of two
   things:

   (1) see if the user did something stupid, like "touch file", that
       modifies only lstat(2) info without actually changing its
       contents, by reading from the working tree, reading HEAD:file
       from the object database, and comparing them, and overwrite
       the working tree file only when they do not match.

       or

   (2) the contents might happen to be the same, but the end result
       user desires to have is that the contents of the working tree
       file is the same as that from the HEAD, so overwrite it
       without wasting time reading two and compare before doing so.

   and it is perfectly reasonable to do the latter.  After all, the
   whole point of having its cached lstat(2) data in the index is to
   so that we do not have to always compare the contents before
   deciding something has changed in the working tree.

Running "git update-index --refresh" immediately before "reset" may
alleviate the issue.  "git status" has the same effect, only because
it does "update-index --refresh" at the beginning of its processing,
but it wastes a lot more time and resource doing other things.

But unless/until you know _why_ the cached stat info in your index
goes stale relative to what lstat(2) tells you, it would not "solve"
it, because that magical thing (and my theory is cached data in your
operating system that keeps a file timestamp with more precision
than your underlying filesystem can represent is being flushed, and
reading the file timestamp back from the disk has to truncate the
nanoseconds part) can happen at any time between the "--refresh" and
your "reset".

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Reset sometimes updates mtime
  2015-07-09 17:56 ` Junio C Hamano
@ 2015-07-10  7:30   ` Dennis Kaarsemaker
  0 siblings, 0 replies; 3+ messages in thread
From: Dennis Kaarsemaker @ 2015-07-10  7:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On do, 2015-07-09 at 10:56 -0700, Junio C Hamano wrote:
> Dennis Kaarsemaker <dennis@kaarsemaker.net> writes:
> 
> > I'm seeing some behaviour with git reset that I find odd. Basically if I
> > do
> >
> > git fetch && \
> > git reset --hard simple-tag-that-points-to-the-current-commit
> >
> > sometimes the reset will update the mtime of all files and directories
> > in the repo and sometimes it will leave them alone. Changing it to
> >
> > git fetch && \
> > git status && \
> > git reset --hard simple-tag-that-points-to-the-current-commit
> >
> > Cause the mtime update to reliably not happen.
> 
> If my theory on what is happening is correct, I do not think there
> is any bug in what "reset --hard" is doing.
> 
> My theory is that something is causing the stat info that is cached
> in your index and the lstat(2) return you get from your working tree
> files go out of sync.  Even though you are not actively touching any
> working tree files (otherwise, you wouldn't be complaining about
> mtime changing in the first place), perhaps your build of Git
> records timestamps in NS but your filesystem and the operating
> system does not preserve nanosecond resolution of timestamps when it
> evicts inode data from the core, or something like that?  If that is
> what is happening, I think that "fetch" is a red herring, but any
> operation that takes some time and/or hits filesystem reasonably
> hard would trigger it.
> 
> And the reason why I say there is no bug in what "reset --hard" is
> doing here, if the above theory is correct, is because:
> 
>  - The user asked "reset --hard" to "make sure that my working tree
>    files are identical to those of HEAD";
> 
>  - "reset --hard" looks at lstat(2) return and the cached stat info
>    in the index and find them not to match.  It can do one of two
>    things:
> 
>    (1) see if the user did something stupid, like "touch file", that
>        modifies only lstat(2) info without actually changing its
>        contents, by reading from the working tree, reading HEAD:file
>        from the object database, and comparing them, and overwrite
>        the working tree file only when they do not match.
> 
>        or
> 
>    (2) the contents might happen to be the same, but the end result
>        user desires to have is that the contents of the working tree
>        file is the same as that from the HEAD, so overwrite it
>        without wasting time reading two and compare before doing so.
> 
>    and it is perfectly reasonable to do the latter.  After all, the
>    whole point of having its cached lstat(2) data in the index is to
>    so that we do not have to always compare the contents before
>    deciding something has changed in the working tree.
> 
> Running "git update-index --refresh" immediately before "reset" may
> alleviate the issue.  "git status" has the same effect, only because
> it does "update-index --refresh" at the beginning of its processing,
> but it wastes a lot more time and resource doing other things.
> 
> But unless/until you know _why_ the cached stat info in your index
> goes stale relative to what lstat(2) tells you, it would not "solve"
> it, because that magical thing (and my theory is cached data in your
> operating system that keeps a file timestamp with more precision
> than your underlying filesystem can represent is being flushed, and
> reading the file timestamp back from the disk has to truncate the
> nanoseconds part) can happen at any time between the "--refresh" and
> your "reset".

Thanks Junio!

If I understand you correctly, reset should not touch files if it thinks
they are up-to-date, so at least that assumption is safe to make. I'll
test your theory about why reset thinks all the files are outdated.

I did notice 'fetch' updates the index (well, mtime of .git/index
changes, I didn't look at index content yet), so maybe fetch isn't quite
a red herring. I'll try to eliminate this variable as well.
 
-- 
Dennis Kaarsemaker
www.kaarsemaker.net

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-07-10  7:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-09 14:02 Reset sometimes updates mtime Dennis Kaarsemaker
2015-07-09 17:56 ` Junio C Hamano
2015-07-10  7:30   ` Dennis Kaarsemaker

Code repositories for project(s) associated with this inbox:

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).