{"thread":{"id":"55515","subject":"git checkout behaviour when only ctime of file changes","startedAt":"2021-04-19T09:11:26Z","lastAt":"2021-04-20T06:10:16Z","messageCount":6,"participants":["Cristian Morales Vega","Bagas Sanjaya","Junio C Hamano","brian m. carlson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"422237","messageId":"CAOWQn3Qesh0+CkaD95q78Rq_vN5tjWKDe7HTk0Ynk-NY8XUKzg@mail.gmail.com","threadId":"55515","inReplyTo":null,"subject":"git checkout behaviour when only ctime of file changes","fromName":"Cristian Morales Vega","fromEmail":"christian.morales.vega@gmail.com","sentAt":"2021-04-19T09:11:12Z","receivedAt":"2021-04-19T09:11:26Z","isPatch":false,"sender":{"key":"christian.morales.vega@gmail.com","avatar":null},"body":"I thought you may want to take a look at\nhttps://issues.jenkins.io/browse/JENKINS-65395.\n\nBasically after something updates the ctime of a file, a\n\"git checkout\" can behave differently depending on whether a\n\"git update-index --refresh\" has been run before or not.\n_Maybe_ it could make sense for \"git checkout\" to always behave as if\n\"git update-index --refresh\" had been run before? No idea really.\n\nI have seen this with git version 2.30.2.\n"},{"id":"422262","messageId":"a6a5bb81-9a86-8901-31dd-dc9c09da0a23@gmail.com","threadId":"55515","inReplyTo":"CAOWQn3Qesh0+CkaD95q78Rq_vN5tjWKDe7HTk0Ynk-NY8XUKzg@mail.gmail.com","subject":"Re: git checkout behaviour when only ctime of file changes","fromName":"Bagas Sanjaya","fromEmail":"bagasdotme@gmail.com","sentAt":"2021-04-19T11:10:23Z","receivedAt":"2021-04-19T11:10:43Z","isPatch":false,"sender":{"key":"bagasdotme@gmail.com","avatar":"https://avatars.githubusercontent.com/u/40219486?v=4"},"body":"On 19/04/21 16.11, Cristian Morales Vega wrote:\n> Basically after something updates the ctime of a file, a\n> \"git checkout\" can behave differently depending on whether a\n> \"git update-index --refresh\" has been run before or not.\n> _Maybe_ it could make sense for \"git checkout\" to always behave as if\n> \"git update-index --refresh\" had been run before? No idea really.\nI know that setting SELinux label can alter file ctime, but when\nI need to write the test that simulate file ctime update, do you\nknow which Unix command can trigger that, beside SELinux tools?\n\n-- \nAn old man doll... just what I always wanted! - Clara\n"},{"id":"422263","messageId":"CAOWQn3Qa68aWH8ztGAej=ctJDw4dkzuPQkkqo6Ydvn=13hV1vw@mail.gmail.com","threadId":"55515","inReplyTo":"a6a5bb81-9a86-8901-31dd-dc9c09da0a23@gmail.com","subject":"Re: git checkout behaviour when only ctime of file changes","fromName":"Cristian Morales Vega","fromEmail":"christian.morales.vega@gmail.com","sentAt":"2021-04-19T11:23:14Z","receivedAt":"2021-04-19T11:24:28Z","isPatch":false,"sender":{"key":"christian.morales.vega@gmail.com","avatar":null},"body":"On Mon, 19 Apr 2021 at 12:10, Bagas Sanjaya <bagasdotme@gmail.com> wrote:\n>\n> On 19/04/21 16.11, Cristian Morales Vega wrote:\n> > Basically after something updates the ctime of a file, a\n> > \"git checkout\" can behave differently depending on whether a\n> > \"git update-index --refresh\" has been run before or not.\n> > _Maybe_ it could make sense for \"git checkout\" to always behave as if\n> > \"git update-index --refresh\" had been run before? No idea really.\n> I know that setting SELinux label can alter file ctime, but when\n> I need to write the test that simulate file ctime update, do you\n> know which Unix command can trigger that, beside SELinux tools?\n\nI am no expert on SELinux and I'm not sure I understand the question.\nI know \"chcon\", from coreutils, can do the SELinux labeling/ctime\nupdate. You could use that when writing a test. There is an example on\nthe fifth comment of JENKINS-65395.\nI know \"docker run --volume <host-dir>:<container-dir>:rw,z\" will do\nthe same, at least if SELinux is enabled. Which is what triggers\nJENKINS-65395.\nDon't really know a lot more.\n"},{"id":"422337","messageId":"xmqqh7k29f35.fsf@gitster.g","threadId":"55515","inReplyTo":"CAOWQn3Qesh0+CkaD95q78Rq_vN5tjWKDe7HTk0Ynk-NY8XUKzg@mail.gmail.com","subject":"Re: git checkout behaviour when only ctime of file changes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-04-19T20:47:26Z","receivedAt":"2021-04-19T20:49:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Cristian Morales Vega <christian.morales.vega@gmail.com> writes:\n\n> I thought you may want to take a look at\n> https://issues.jenkins.io/browse/JENKINS-65395.\n>\n> Basically after something updates the ctime of a file, a\n> \"git checkout\" can behave differently depending on whether a\n> \"git update-index --refresh\" has been run before or not.\n\nChanges to ctime, not just to mtime, participate in \"the path may\nhave been changed so need to go back to the contents to see if it\ntruly has\" logic, and \"update-index --refresh\" is a mechanism to\nclear that \"the path may have been changed\" bit.  \n\nSo if your \"behave differently ... with or without refresh\" happens\nequally if you replace 'ctime' in your statement with 'mtime', then\neverything is working as designed.  But it was unclear from your\ndescription.\n\nAssuming that the difference with and without refresh after mtime\nchange is the same as the difference with and without refresh after\nctime change, the \"core.trustctime\" configuration variable is for\nthose whose files have untrustworthy ctime (due to background\nscanners and other funnies).\n\n"},{"id":"422364","messageId":"YH42xGwjTX4Axcpp@camp.crustytoothpaste.net","threadId":"55515","inReplyTo":"CAOWQn3Qesh0+CkaD95q78Rq_vN5tjWKDe7HTk0Ynk-NY8XUKzg@mail.gmail.com","subject":"Re: git checkout behaviour when only ctime of file changes","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2021-04-20T02:04:52Z","receivedAt":"2021-04-20T02:05:31Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2021-04-19 at 09:11:12, Cristian Morales Vega wrote:\n> I thought you may want to take a look at\n> https://issues.jenkins.io/browse/JENKINS-65395.\n> \n> Basically after something updates the ctime of a file, a\n> \"git checkout\" can behave differently depending on whether a\n> \"git update-index --refresh\" has been run before or not.\n> _Maybe_ it could make sense for \"git checkout\" to always behave as if\n> \"git update-index --refresh\" had been run before? No idea really.\n\nI believe the situation you're seeing is that git checkout usually\ndoesn't rewrite files in the working tree that are already up to date.\nThis makes checkout much faster in large working trees.\n\nBy default, Git does include the ctime in its computation of whether a\nfile is up to date.  If the ctime changes, then the file is considered\nto be stale.  git checkout, without an intervening command, will\noverwrite it, since it's dirty and just overwriting it is cheaper than\ndetermining whether it is in fact up to date.\n\ngit update-index --refresh does the check about whether the file is in\nfact up to date.  This isn't free; if you've modified 1000 files, or if\nyou've modified large files, there's going to be a cost to this, and it\ncan be very substantial.  As mentioned, git checkout doesn't want to\nperform that cost needlessly, so it overwrites the file unconditionally.\n\nAs far as I'm aware, Git doesn't document which files it does and does\nnot rewrite in the working tree as part of a checkout, except as part of\ncertain specified options (e.g., the --overlay option).  It is therefore\nfree to choose any algorithm it chooses, and in this case, we've\noptimized for checkout performance, not minimal modifications.\n\nThere is a config option, core.trustctime, which can be set to false if\nyou don't want to consider the ctime as part of whether a file is up to\ndate.  But Git is behaving correctly and as desired here.\n-- \nbrian m. carlson (he/him or they/them)\nHouston, Texas, US\n"},{"id":"422368","messageId":"CAOWQn3Rr7qsTTjY1CYj1SAXk6_fhEc8mFn1o4Dep5N0c9yeK1A@mail.gmail.com","threadId":"55515","inReplyTo":"YH42xGwjTX4Axcpp@camp.crustytoothpaste.net","subject":"Re: git checkout behaviour when only ctime of file changes","fromName":"Cristian Morales Vega","fromEmail":"christian.morales.vega@gmail.com","sentAt":"2021-04-20T06:10:01Z","receivedAt":"2021-04-20T06:10:16Z","isPatch":false,"sender":{"key":"christian.morales.vega@gmail.com","avatar":null},"body":"On Tue, 20 Apr 2021 at 03:05, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n>\n> On 2021-04-19 at 09:11:12, Cristian Morales Vega wrote:\n> > I thought you may want to take a look at\n> > https://issues.jenkins.io/browse/JENKINS-65395.\n> >\n> > Basically after something updates the ctime of a file, a\n> > \"git checkout\" can behave differently depending on whether a\n> > \"git update-index --refresh\" has been run before or not.\n> > _Maybe_ it could make sense for \"git checkout\" to always behave as if\n> > \"git update-index --refresh\" had been run before? No idea really.\n>\n> I believe the situation you're seeing is that git checkout usually\n> doesn't rewrite files in the working tree that are already up to date.\n> This makes checkout much faster in large working trees.\n>\n> By default, Git does include the ctime in its computation of whether a\n> file is up to date.  If the ctime changes, then the file is considered\n> to be stale.  git checkout, without an intervening command, will\n> overwrite it, since it's dirty and just overwriting it is cheaper than\n> determining whether it is in fact up to date.\n\nYes, this is basically it. The \"just overwriting it is cheaper than\ndetermining whether it is in fact up to date\" is the main thing. I was\nthinking that maybe, if ctime has changed but mtime hasn't, it could\nbe faster to not overwrite the files since I _think_ it means the file\ncontents don't need to be checked, only the basic file permissions (I\ndon't think git stores any extended attributes, does it?). But I could\nbe completely wrong here. Otherwise \"core.trustctime\" seems like the\nperfect option for the problem.\n"}]}