{"thread":{"id":"23649","subject":"[PATCH 2/2] Documentation: git-add does not update files marked \"assume unchanged\"","startedAt":"2010-05-01T09:25:12Z","lastAt":"2010-05-05T15:44:59Z","messageCount":7,"participants":["Clemens Buchacher","Avery Pennarun","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"140676","messageId":"20100501092512.GA15941@localhost","threadId":"23649","inReplyTo":null,"subject":"[PATCH 1/2] do not overwrite files marked \"assume unchanged\"","fromName":"Clemens Buchacher","fromEmail":"drizzd@aon.at","sentAt":"2010-05-01T09:25:12Z","receivedAt":"2010-05-01T09:25:12Z","isPatch":true,"sender":{"key":"drizzd@gmx.net","avatar":"https://avatars.githubusercontent.com/u/59082?v=4"},"body":"A merge will fail gracefully if it needs to update files marked\n\"assume unchanged\", but other similar commands will not. In\nparticular, checkout and rebase will silently overwrite changes to\nsuch files.\n\nThis is a regression introduced in commit 1dcafcc0 (verify_uptodate():\nadd ce_uptodate(ce) test), which avoids lstat's during a merge, if the\nindex entry is up-to-date. If the CE_VALID flag is set, however, we\ncannot trust CE_UPTODATE.\n\nSigned-off-by: Clemens Buchacher <drizzd@aon.at>\n---\n t/t2106-update-index-assume-unchanged.sh |   24 ++++++++++++++++++++++++\n unpack-trees.c                           |    2 +-\n 2 files changed, 25 insertions(+), 1 deletions(-)\n create mode 100755 t/t2106-update-index-assume-unchanged.sh\n\ndiff --git a/t/t2106-update-index-assume-unchanged.sh b/t/t2106-update-index-assume-unchanged.sh\nnew file mode 100755\nindex 0000000..99d858c\n--- /dev/null\n+++ b/t/t2106-update-index-assume-unchanged.sh\n@@ -0,0 +1,24 @@\n+#!/bin/sh\n+\n+test_description='git update-index --assume-unchanged test.\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' \\\n+\t': >file &&\n+\t git add file &&\n+\t git commit -m initial &&\n+\t git branch other &&\n+\t echo upstream >file &&\n+\t git add file &&\n+\t git commit -m upstream'\n+\n+test_expect_success 'do not switch branches with dirty file' \\\n+\t'git reset --hard &&\n+\t git checkout other &&\n+\t echo dirt >file &&\n+\t git update-index --assume-unchanged file &&\n+\t test_must_fail git checkout master'\n+\n+test_done\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 75f54ca..1a8030c 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -862,7 +862,7 @@ static int verify_uptodate_1(struct cache_entry *ce,\n {\n \tstruct stat st;\n \n-\tif (o->index_only || (!ce_skip_worktree(ce) && (o->reset || ce_uptodate(ce))))\n+\tif (o->index_only || (!((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) && (o->reset || ce_uptodate(ce))))\n \t\treturn 0;\n \n \tif (!lstat(ce->name, &st)) {\n-- \n1.7.0.5.3.ga76e\n"},{"id":"140675","messageId":"20100501092720.GB15941@localhost","threadId":"23649","inReplyTo":"20100501092512.GA15941@localhost","subject":"[PATCH 2/2] Documentation: git-add does not update files marked \"assume unchanged\"","fromName":"Clemens Buchacher","fromEmail":"drizzd@aon.at","sentAt":"2010-05-01T09:27:20Z","receivedAt":"2010-05-01T09:27:20Z","isPatch":true,"sender":{"key":"drizzd@gmx.net","avatar":"https://avatars.githubusercontent.com/u/59082?v=4"},"body":"\nSigned-off-by: Clemens Buchacher <drizzd@aon.at>\n---\n\nBehavior of git-add also changed since commit 1dcafcc0, but I actually\nprefer it this way.\n\n Documentation/git-update-index.txt |    5 ++---\n 1 files changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt\nindex 68dc187..2d45774 100644\n--- a/Documentation/git-update-index.txt\n+++ b/Documentation/git-update-index.txt\n@@ -93,8 +93,6 @@ OPTIONS\n This option can be also used as a coarse file-level mechanism\n to ignore uncommitted changes in tracked files (akin to what\n `.gitignore` does for untracked files).\n-You should remember that an explicit 'git add' operation will\n-still cause the file to be refreshed from the working tree.\n Git will fail (gracefully) in case it needs to modify this file\n in the index e.g. when merging in a commit;\n thus, in case the assumed-untracked file is changed upstream,\n@@ -102,7 +100,8 @@ you will need to handle the situation manually.\n \n --really-refresh::\n \tLike '--refresh', but checks stat information unconditionally,\n-\twithout regard to the \"assume unchanged\" setting.\n+\twithout regard to the \"assume unchanged\" setting. The \"assume\n+\tunchanged\" bit is unset for all paths.\n \n --skip-worktree::\n --no-skip-worktree::\n-- \n1.7.0.5.3.ga76e\n"},{"id":"140895","messageId":"20100504085722.GA32217@localhost","threadId":"23649","inReplyTo":"20100501092720.GB15941@localhost","subject":"update-index --really-refresh unsets assume-unchanged bit","fromName":"Clemens Buchacher","fromEmail":"drizzd@aon.at","sentAt":"2010-05-04T08:57:22Z","receivedAt":"2010-05-04T08:57:22Z","isPatch":false,"sender":{"key":"drizzd@gmx.net","avatar":"https://avatars.githubusercontent.com/u/59082?v=4"},"body":"On Sat, May 01, 2010 at 11:27:20AM +0200, Clemens Buchacher wrote:\n\n>  --really-refresh::\n>  \tLike '--refresh', but checks stat information unconditionally,\n> -\twithout regard to the \"assume unchanged\" setting.\n> +\twithout regard to the \"assume unchanged\" setting. The \"assume\n> +\tunchanged\" bit is unset for all paths.\n\nScratch that latter part, please. I just noticed the bit is unset only for\nmodified files. If the file matches the index, or even if it has been\ndeleted in the work tree, the bit is _not_ unset.\n\nSo the current behavior is quite strange. I see several possible\ninterpretations of --really-refresh:\n\n Update index for specified paths, disregarding the assume-unchanged bit,\n\n a) ... and do not ignore work tree changes for tracked files any more.\n    I.e., unset the assume-unchanged bit for all files.\n\n b) ... and do not ignore work tree changes for the specified paths any more.\n    I.e., unset assume-unchanged bit only for specified paths.\n\n c) ... but continue ignoring work tree changes as before.\n    I.e., do not unset the assume-unchanged bit for any paths.\n\n(and the current behavior)\n\n d) ... and do not ignore work tree changes for modified files any more.\n    I.e., unset assume-unchanged bit for modified paths.\n\nI believe c) is the most useful, since it allows the user to deactivate the\nassume-unchanged bit temporarily. All other options potentially change the\nassume-unchanged bit, which the user may or may not want. In my opinion, it\nmakes no sense to bundle the two operations \"update index disregarding the\nassume-unchanged bit\" and \"(conditionally) unset assume-unchanged bit.\"\n\nClemens\n"},{"id":"140919","messageId":"z2h32541b131005040941m79724daq4cd8b0c427bb218a@mail.gmail.com","threadId":"23649","inReplyTo":"20100504085722.GA32217@localhost","subject":"Re: update-index --really-refresh unsets assume-unchanged bit","fromName":"Avery Pennarun","fromEmail":"apenwarr@gmail.com","sentAt":"2010-05-04T16:41:22Z","receivedAt":"2010-05-04T16:41:22Z","isPatch":false,"sender":{"key":"apenwarr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/20592?v=4"},"body":"On Tue, May 4, 2010 at 4:57 AM, Clemens Buchacher <drizzd@aon.at> wrote:\n> On Sat, May 01, 2010 at 11:27:20AM +0200, Clemens Buchacher wrote:\n>\n>>  --really-refresh::\n>>       Like '--refresh', but checks stat information unconditionally,\n>> -     without regard to the \"assume unchanged\" setting.\n>> +     without regard to the \"assume unchanged\" setting. The \"assume\n>> +     unchanged\" bit is unset for all paths.\n>\n> Scratch that latter part, please. I just noticed the bit is unset only for\n> modified files. If the file matches the index, or even if it has been\n> deleted in the work tree, the bit is _not_ unset.\n>\n> So the current behavior is quite strange. I see several possible\n> interpretations of --really-refresh:\n\nI don't know, the current behaviour sounds consistent with the name:\n\"assume unchanged.\"\n\nIf the index says the file is unmodified, then assume it's unchanged;\ndon't check for changes.\n\nIf the index says the file is modified, then clearly it's changed; it\nwould be pointless to assume otherwise, so the \"assume unchanged\" bit\nshould probably not be set.  (Plus it's quite possibly dangerous to\nassume the file permissions are the same as they were when you first\nnoticed they were changed; imagine if the file has changed twice and\nnow has a different length or mode.)\n\nSince most of the time most of your files won't have changed,\nassume-unchanged gets you the optimization without too much danger.\nThe cost of not assuming a changed file is unchanged is pretty low.\n\n...now if only there was a global \"just never check for changes or new\nfiles or anything, even if I run git status\" bit, someone could write\na useful git inotify daemon :)\n\nHave fun,\n\nAvery\n"},{"id":"140931","messageId":"20100504194136.GA19300@localhost","threadId":"23649","inReplyTo":"z2h32541b131005040941m79724daq4cd8b0c427bb218a@mail.gmail.com","subject":"Re: update-index --really-refresh unsets assume-unchanged bit","fromName":"Clemens Buchacher","fromEmail":"drizzd@aon.at","sentAt":"2010-05-04T19:41:36Z","receivedAt":"2010-05-04T19:41:36Z","isPatch":false,"sender":{"key":"drizzd@gmx.net","avatar":"https://avatars.githubusercontent.com/u/59082?v=4"},"body":"On Tue, May 04, 2010 at 12:41:22PM -0400, Avery Pennarun wrote:\n\n> On Tue, May 4, 2010 at 4:57 AM, Clemens Buchacher <drizzd@aon.at> wrote:\n>\n> > Scratch that latter part, please. I just noticed the bit is unset only for\n> > modified files. If the file matches the index, or even if it has been\n> > deleted in the work tree, the bit is _not_ unset.\n> >\n> > So the current behavior is quite strange. I see several possible\n> > interpretations of --really-refresh:\n> \n> I don't know, the current behaviour sounds consistent with the name:\n> \"assume unchanged.\"\n> \n> If the index says the file is unmodified, then assume it's unchanged;\n> don't check for changes.\n\nThis is not about changes with respect to HEAD.  The \"assume unchanged\" flag\nis unset if the work tree differs from the index.  Whether or not the file\nis modified in the index is irrelevant.\n\n> If the index says the file is modified, then clearly it's changed; it\n> would be pointless to assume otherwise, so the \"assume unchanged\" bit\n> should probably not be set.\n\nOn the contrary. I _want_ git to assume the file is unchanged, even though I\nknow it changed. This is an intended and documented use case (from the\ngit-update-index manpage):\n\n This option can be also used as a coarse file-level mechanism\n to ignore uncommitted changes in tracked files (akin to what\n `.gitignore` does for untracked files).\n\nBut even if you look at it from the performance optimization perspective,\nthe behavior is still inconsistent, because it does not unset the bit for\ndeleted files.\n\nFurthermore, after update-index --really-refresh --add, the file is in fact\nunchanged again and it would make much more sense to keep the\nassume-unchanged flag.\n\n> (Plus it's quite possibly dangerous to\n> assume the file permissions are the same as they were when you first\n> noticed they were changed; imagine if the file has changed twice and\n> now has a different length or mode.)\n\nWhat do you mean, \"dangerous\"? I tell git to update the index, and then\ncontinue to ignore changes to the work tree, until I explicitly update\nagain. I can already achieve this behavior using\n\n git ls-files -v | grep ^h | cut -f2 -d' ' >my-ignored-files\n git update-index --really-refresh\n cat my-ignored-files | xargs git update-index --assume-unchanged\n\nClemens\n"},{"id":"140945","messageId":"7v39y7mglb.fsf@alter.siamese.dyndns.org","threadId":"23649","inReplyTo":"20100504194136.GA19300@localhost","subject":"Re: update-index --really-refresh unsets assume-unchanged bit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-05-04T22:45:20Z","receivedAt":"2010-05-04T22:45:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Clemens Buchacher <drizzd@aon.at> writes:\n\n> On the contrary. I _want_ git to assume the file is unchanged, even though I\n> know it changed. This is an intended and documented use case (from the\n> git-update-index manpage):\n\nThe intended use of *really* one is to ignore the assume unchanged bit and\nmake the bit reflect reality.  The bit was originally invented back when\nthe machinery was too lstat(2) heavy so that people on slow filesystems\ncan say \"I haven't changed these paths, and I promise I won't, so you can\ntrust this and assume that the working tree file exactly matches what is\nrecorded in the index.\"  Obviously we needed to give such users an way to\ntell git that they broke their promise, and that is what *really* refresh\nmeant to give.\n\nNote that the promise is _different_ from telling \"I may or may not have\nchanged the work tree files, but don't bother telling me that I did\".  The\npromise you make by \"assume unchanged\" bit allows git to read from the\nworking tree file when it needs the contents of blob recorded in the index\nand the bit is set, as you promised that you will never change it.\n"},{"id":"140997","messageId":"20100505154459.GA24447@localhost","threadId":"23649","inReplyTo":"7v39y7mglb.fsf@alter.siamese.dyndns.org","subject":"Re: update-index --really-refresh unsets assume-unchanged bit","fromName":"Clemens Buchacher","fromEmail":"drizzd@aon.at","sentAt":"2010-05-05T15:44:59Z","receivedAt":"2010-05-05T15:44:59Z","isPatch":false,"sender":{"key":"drizzd@gmx.net","avatar":"https://avatars.githubusercontent.com/u/59082?v=4"},"body":"On Tue, May 04, 2010 at 03:45:20PM -0700, Junio C Hamano wrote:\n> Clemens Buchacher <drizzd@aon.at> writes:\n> \n> > On the contrary. I _want_ git to assume the file is unchanged, even though I\n> > know it changed. This is an intended and documented use case (from the\n> > git-update-index manpage):\n> \n> The intended use of *really* one is to ignore the assume unchanged bit and\n> make the bit reflect reality.\n\nYes, and right below the part you are quoting I explained why this is not\nwhat it does either.\n\n> The bit was originally invented back when\n> the machinery was too lstat(2) heavy so that people on slow filesystems\n> can say \"I haven't changed these paths, and I promise I won't, so you can\n> trust this and assume that the working tree file exactly matches what is\n> recorded in the index.\"  Obviously we needed to give such users an way to\n> tell git that they broke their promise, and that is what *really* refresh\n> meant to give.\n\nYes, but after the index is refreshed, the file is now, again, unchanged.\nYet, the assume-unchanged bit is unset.\n\nBut there is no reason presume that the user will break their promise again\nin the future. If they plan to do so, they can always use git update-index\n--no-assume-unchanged.\n\n> Note that the promise is _different_ from telling \"I may or may not have\n> changed the work tree files, but don't bother telling me that I did\".  The\n> promise you make by \"assume unchanged\" bit allows git to read from the\n> working tree file when it needs the contents of blob recorded in the index\n> and the bit is set, as you promised that you will never change it.\n\nAnd in what case does git do that? I can only find commands which read from\nthe object store and not from the work tree. This would also break the\n\"ignore changes to tracked files\" use case.\n\nClemens\n"}]}