{"thread":{"id":"4558","subject":"git 1.4.0 usability problem","startedAt":"2006-06-18T13:40:06Z","lastAt":"2006-06-20T14:07:11Z","messageCount":17,"participants":["Jeff Garzik","Ryan Anderson","Junio C Hamano","Santi Béjar","Alexander Litvinov","Carl Worth"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"22019","messageId":"449557B6.1080907@garzik.org","threadId":"4558","inReplyTo":null,"subject":"git 1.4.0 usability problem","fromName":"Jeff Garzik","fromEmail":"jeff@garzik.org","sentAt":"2006-06-18T13:40:06Z","receivedAt":"2006-06-18T13:40:06Z","isPatch":false,"sender":{"key":"jeff@garzik.org","avatar":null},"body":"Now that kernel 2.6.17 is out, I updated all my repositories to be based \nagainst that kernel.  And for each repository I updated, my merge was \nrejected, due to an error similar to:\n\n> fatal: Untracked working tree file '.gitignore' would be overwritten by merge.\n\nI am only able to merge if I delete files in the working directory, so \nthat git stops complaining on merge.\n\nThis behavior is new with git 1.4.0, which Fedora Extras just added.  I \nverified that merges work as expected in git 1.3.3, the last version \nFedora Extras shipped prior to 1.4.0.\n\nThis behavior is a definite regression, that impacts workflow :(\n\nHere is how to reproduce:\n\ngit clone -l $url/torvalds/linux-2.6.git tmp-2.6\ncd tmp-2.6\ncp .git/refs/tags/v2.6.12 .git/refs/heads/tmp\ngit checkout -f tmp\ngit pull . master\n# watch OBVIOUS FAST-FORWARD MERGE complain about untracked\n# working tree files\n\nRegards,\n\n\tJeff\n"},{"id":"22030","messageId":"20060618164300.GI25520@h4x0r5.com","threadId":"4558","inReplyTo":"449557B6.1080907@garzik.org","subject":"Re: git 1.4.0 usability problem","fromName":"Ryan Anderson","fromEmail":"ryan@michonline.com","sentAt":"2006-06-18T16:43:00Z","receivedAt":"2006-06-18T16:43:00Z","isPatch":false,"sender":{"key":"ryan@michonline.com","avatar":null},"body":"On Sun, Jun 18, 2006 at 09:40:06AM -0400, Jeff Garzik wrote:\n> Now that kernel 2.6.17 is out, I updated all my repositories to be based \n> against that kernel.  And for each repository I updated, my merge was \n> rejected, due to an error similar to:\n> \n> >fatal: Untracked working tree file '.gitignore' would be overwritten by \n> >merge.\n> \n> I am only able to merge if I delete files in the working directory, so \n> that git stops complaining on merge.\n> \n> This behavior is new with git 1.4.0, which Fedora Extras just added.  I \n> verified that merges work as expected in git 1.3.3, the last version \n> Fedora Extras shipped prior to 1.4.0.\n> \n> This behavior is a definite regression, that impacts workflow :(\n> \n> Here is how to reproduce:\n> \n> git clone -l $url/torvalds/linux-2.6.git tmp-2.6\n\nAt this point you have master checked out, and recorded properly in the\nindex.\n\n> cd tmp-2.6\n> cp .git/refs/tags/v2.6.12 .git/refs/heads/tmp\n> git checkout -f tmp\n\nHere, you throw that index away, ignore the contents of the working\ntree, and checkout tmp.\n\n> git pull . master\n> # watch OBVIOUS FAST-FORWARD MERGE complain about untracked\n> # working tree files\n\nAt this point, you have a working tree containing files leftover from\nthe checkout of master, but which are totally unknown to the 2.6.12\ntree, and so are untracked.  The fast-forward is trying hard not to\noverwrite things it shouldn't be messing with, and so complains.\n\nThe fix is to drop the \"-f\" from git checkout, and things should work\ncorrectly.  (\"-f\" should really not be a normal thing to use. For\nswitching branches, \"git checkout\" should be sufficient, and should\nresult ina working tree that doesn't contain nearly as many potential\nconflict sources.\n\n-- \n\nRyan Anderson\n  sometimes Pug Majere\n"},{"id":"22037","messageId":"7vac8a1cuc.fsf@assigned-by-dhcp.cox.net","threadId":"4558","inReplyTo":"449557B6.1080907@garzik.org","subject":"Re: git 1.4.0 usability problem","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-18T19:30:03Z","receivedAt":"2006-06-18T19:30:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff Garzik <jeff@garzik.org> writes:\n\n> Now that kernel 2.6.17 is out, I updated all my repositories to be\n> based against that kernel.  And for each repository I updated, my\n> merge was rejected, due to an error similar to:\n>\n>> fatal: Untracked working tree file '.gitignore' would be overwritten by merge.\n>\n> I am only able to merge if I delete files in the working directory, so\n> that git stops complaining on merge.\n>\n> This behavior is new with git 1.4.0, which Fedora Extras just added.\n> I verified that merges work as expected in git 1.3.3, the last version\n> Fedora Extras shipped prior to 1.4.0.\n>\n> This behavior is a definite regression, that impacts workflow :(\n>\n> Here is how to reproduce:\n>\n> git clone -l $url/torvalds/linux-2.6.git tmp-2.6\n> cd tmp-2.6\n> cp .git/refs/tags/v2.6.12 .git/refs/heads/tmp\n> git checkout -f tmp\n> git pull . master\n\nI was not happy with this change myself when I saw the extent of\ndamage it caused to the existing testsuite that was loosely\nwritten (fcc387db9bc453dc7e07a262873481af2ee9e5c8 introduced\nthis change, and the needed changes to the testsuite can be seen\nin the same commit).\n\nThis was done in response to this problem report:\n\n        From: Santi <sbejar@gmail.com>\n        Subject: Merge with local conflicts in new files\n        Date: Wed, 17 May 2006 00:00:10 +0200\n        Message-ID: <8aa486160605161500m1dd8428cj@mail.gmail.com>\n\n        Hi *,\n\n              In the case of:\n\n        - You merge from a branch with new files\n        - You have these files in the working directory\n        - You do not have these files in the HEAD.\n\n          The end result is that you lose the content of these files.\n\nIt is an improvement not to lose untracked files, and this is\nconsistent with how \"read-tree -m -u\" tries to protect your\nchanges to tracked files.  When moving around in the history of\nthe same project without using \"git checkout\" (sans -f),\nhowever, it is bound to cause the above trouble whenever your\nversion switching involves created/deleted files.\n\nI am open to suggestions to make this check easily overridable.\nI suspect it should be sufficient to disable verify_absent()\ncheck in builtin-read-tree.c when the user tells us to do so,\nbut the issue is how.  I can think of a few ways:\n\n (1) define an environment variable, return from verify_absent()\n     without checking when that variable is set, and have the\n     user run\n\n     \t$ GIT_UNTRACKED_CLOBBER_OK=t git pull\n\n     when clobbering is desired.\n\n (2) In addition to the above, modify Porcelainish commands such\n     as checkout, pull, and merge to set the environment variable\n     when --clobber-ok flag is given to them.\n\n (3) define a new flag --clobber-ok to git-read-tree, pass it\n     around from Porcelainish commands that would eventually\n     call \"read-tree -m -u\".\n\nI suspect the last one would be quite intrusive.  Independent of\nthe above, we could have a configuration item \"core.clobberok = true\"\nto always disable the check for the repository.\n\nIt might be better to give the user a way to recover from the\nsituation while keeping things still safer than before by not\ngiving the above \"clobber-ok\" flag.  For example, \"read-tree -m\n-u\" currently dies on the first \"refraining from clobbering\nuntracked file\" message, but there is not an obvious way to list\nall untracked files that will be clobbered by the operation so\nthat you can make sure they are something you do not care about\nand remove them yourself before retrying.\n"},{"id":"22045","messageId":"7vbqsqdru0.fsf@assigned-by-dhcp.cox.net","threadId":"4558","inReplyTo":"449557B6.1080907@garzik.org","subject":"Re: git 1.4.0 usability problem","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-18T22:25:27Z","receivedAt":"2006-06-18T22:25:27Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff Garzik <jeff@garzik.org> writes:\n\n> Here is how to reproduce:\n\nThis is not related to the \"not clobbering untracked files\"\nsafety valve under discussion, but one thing I noticed.\n\n> git clone -l $url/torvalds/linux-2.6.git tmp-2.6\n> cd tmp-2.6\n> cp .git/refs/tags/v2.6.12 .git/refs/heads/tmp\n> git checkout -f tmp\n\nThis should never have been supported.  At this point tmp is a\ntag object that is under heads/ -- a definite no-no.  We should\nmake checkout more careful to complain about it.\n\nDoing\n\n        git update-ref refs/heads/tmp $(git rev-parse v2.6.12^0)\n\ninstead of \"cp\" is kosher, and\n\n\tgit-rev-parse v2.6.12^0 >.git/refs/heads/tmp\n\nis OK under the current implementation of refs.\n\n> git pull . master\n> # watch OBVIOUS FAST-FORWARD MERGE complain about untracked\n> # working tree files\n\nIn any case, here is a patch I think would alleviate your\noriginal problem.\n\nSorry for the trouble.  I really did not want to disrupt the\nworkflow of old timers in the name of making it safer for new\npeople.  Could you comment on whether this is an acceptable\napproach?\n\n-- >8 --\n[PATCH] Conditionally loosen \"no clobber untracked files\" safety valve.\n\nThis introduces a new configuration item \"core.oktoclobber\" to\ncontrol how untracked working tree file is handled during branch\nswitching.\n\nThe safety valve introduced during 1.4.0 development cycle\nrefrains from checking out a file that exists in the working\ntree, not in the current HEAD tree and exists in the branch we\nare switching to, in order to prevent accidental and\nirreversible lossage of user data.  This can be controlled by\nhaving core.oktoclobber configuration item:\n\n - When core.oktoclobber is set to \"false\" (the default),\n   untracked working tree files are never overwritten.\n\n - When core.oktoclobber is set to \"true\", the check is\n   disabled.\n\n - When core.oktoclobber is set to \"ask\", and both standard\n   input and standard error streams are connected to the\n   terminal, we ask the user if it is OK to clobber.  You can\n   answer:\n\n\ty: to allow clobbering only one path; the question is\n\t   asked again for other paths.\n        n: to stop the operation.\n\ta: to allow clobbering any untracked files; the question\n\t   is not asked again.\n\n   If the configuration item is set to \"ask\" but the program is\n   not talking to a terminal, it refrains from clobbering the\n   untracked files.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n builtin-read-tree.c |   43 ++++++++++++++++++++++++++++++++++++++++++-\n cache.h             |    6 ++++++\n config.c            |   20 ++++++++++++++++++++\n environment.c       |    1 +\n 4 files changed, 69 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 04506da..7a7018c 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -477,6 +477,46 @@ static void invalidate_ce_path(struct ca\n \t\tcache_tree_invalidate_path(active_cache_tree, ce->name);\n }\n \n+static int ok_to_clobber_untracked(const char *path, const char *action)\n+{\n+\tswitch (ok_to_clobber_untracked_files) {\n+\tcase NEVER_CLOBBER:\n+\t\treturn 0;\n+\tcase OK_TO_CLOBBER:\n+\t\treturn 1;\n+\tcase ASK_TO_CLOBBER:\n+\t\tif (isatty(0) && isatty(2)) {\n+\t\t\tchar answer[1024];\n+\t\t\twhile (1) {\n+\t\t\t\tanswer[0] = '\\0';\n+\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t\"Untracked working tree file '%s' is\"\n+\t\t\t\t\t\" about to be %s.  Is it OK \"\n+\t\t\t\t\t\"[y]es/[n]o/yes to [a]ll? \",\n+\t\t\t\t\tpath, action);\n+\t\t\t\tfgets(answer, sizeof(answer), stdin);\n+\t\t\t\tswitch (answer[0]) {\n+\t\t\t\tcase 'y': case 'Y':\n+\t\t\t\t\treturn 1;\n+\t\t\t\tcase 'n': case 'N':\n+\t\t\t\t\treturn 0;\n+\t\t\t\tcase 'a': case 'A':\n+\t\t\t\t\tok_to_clobber_untracked_files =\n+\t\t\t\t\t\tOK_TO_CLOBBER;\n+\t\t\t\t\treturn 1;\n+\t\t\t\tdefault:\n+\t\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t\t\"I do not understand.\\n\");\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\telse {\n+\t\t\tok_to_clobber_untracked_files = NEVER_CLOBBER;\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+}\n+\n /*\n  * We do not want to remove or overwrite a working tree file that\n  * is not tracked.\n@@ -485,7 +525,8 @@ static void verify_absent(const char *pa\n {\n \tstruct stat st;\n \n-\tif (index_only || reset || !update)\n+\tif (index_only || reset || !update ||\n+\t    ok_to_clobber_untracked(path, action))\n \t\treturn;\n \tif (!lstat(path, &st))\n \t\tdie(\"Untracked working tree file '%s' \"\ndiff --git a/cache.h b/cache.h\nindex f630cf4..7468440 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -183,6 +183,12 @@ extern int log_all_ref_updates;\n extern int warn_ambiguous_refs;\n extern int diff_rename_limit_default;\n extern int shared_repository;\n+enum ok_to_clobber {\n+\tNEVER_CLOBBER = 0,\n+\tOK_TO_CLOBBER,\n+\tASK_TO_CLOBBER\n+};\n+extern enum ok_to_clobber ok_to_clobber_untracked_files;\n extern const char *apply_default_whitespace;\n \n #define GIT_REPO_VERSION 0\ndiff --git a/config.c b/config.c\nindex 984c75f..13f5f4f 100644\n--- a/config.c\n+++ b/config.c\n@@ -251,6 +251,21 @@ int git_config_bool(const char *name, co\n \treturn git_config_int(name, value) != 0;\n }\n \n+static enum ok_to_clobber git_config_clobber(const char *var, const char *value)\n+{\n+\tif (!strcasecmp(value, \"ask\"))\n+\t\treturn ASK_TO_CLOBBER;\n+\tif (!strcasecmp(value, \"yes\"))\n+\t\treturn OK_TO_CLOBBER;\n+\tif (!strcasecmp(value, \"ok\"))\n+\t\treturn NEVER_CLOBBER;\n+\tif (!strcasecmp(value, \"no\"))\n+\t\treturn NEVER_CLOBBER;\n+\tif (git_config_bool(var, value))\n+\t\treturn OK_TO_CLOBBER;\n+\treturn NEVER_CLOBBER;\n+}\n+\n int git_default_config(const char *var, const char *value)\n {\n \t/* This needs a better name */\n@@ -279,6 +294,11 @@ int git_default_config(const char *var, \n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.oktoclobber\")) {\n+\t\tok_to_clobber_untracked_files = git_config_clobber(var, value);\n+\t\treturn 0;\n+\t}\n+\n \tif (!strcmp(var, \"user.name\")) {\n \t\tsafe_strncpy(git_default_name, value, sizeof(git_default_name));\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 2e79eab..c388b5b 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -19,6 +19,7 @@ int warn_ambiguous_refs = 1;\n int repository_format_version = 0;\n char git_commit_encoding[MAX_ENCODING_LENGTH] = \"utf-8\";\n int shared_repository = 0;\n+extern enum ok_to_clobber ok_to_clobber_untracked_files = NEVER_CLOBBER;\n const char *apply_default_whitespace = NULL;\n \n static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,\n"},{"id":"22046","messageId":"20060618222732.GJ25520@h4x0r5.com","threadId":"4558","inReplyTo":"20060618164300.GI25520@h4x0r5.com","subject":"Re: git 1.4.0 usability problem","fromName":"Ryan Anderson","fromEmail":"ryan@michonline.com","sentAt":"2006-06-18T22:27:33Z","receivedAt":"2006-06-18T22:27:33Z","isPatch":false,"sender":{"key":"ryan@michonline.com","avatar":null},"body":"On Sun, Jun 18, 2006 at 09:43:00AM -0700, Ryan Anderson wrote:\n> \n> The fix is to drop the \"-f\" from git checkout, and things should work\n> correctly.  (\"-f\" should really not be a normal thing to use. For\n> switching branches, \"git checkout\" should be sufficient, and should\n> result ina working tree that doesn't contain nearly as many potential\n> conflict sources.\n\nI wrote all of that from memory, but I figured I should really test it:\n\n$ git branch tmp v2.6.12\n$ git checkout tmp\n$ git pull . master\nUpdating from 9ee1c939d1cb936b1f98e8d81aeffab57bae46ab to\n553698f944ed715dfe023b4cef07601f0ce735f0\nChecking files out...\n 100% (14284/14284) done\n Fast forward\n(Watch insanely large diffstat blow by)\n$ git status\n# On branch refs/heads/tmp\nnothing to commit\n$ git branch\n  master\n  origin\n  ryan\n* tmp\n\nSo, I think all you need to do is drop the \"-f\" from the call to\ncheckout, and the issues will be fixed, for your particular use case.\n\n\n\n\n-- \n\nRyan Anderson\n  sometimes Pug Majere\n"},{"id":"22049","messageId":"4495DB3B.10403@garzik.org","threadId":"4558","inReplyTo":"7vbqsqdru0.fsf@assigned-by-dhcp.cox.net","subject":"Re: git 1.4.0 usability problem","fromName":"Jeff Garzik","fromEmail":"jeff@garzik.org","sentAt":"2006-06-18T23:01:15Z","receivedAt":"2006-06-18T23:01:15Z","isPatch":false,"sender":{"key":"jeff@garzik.org","avatar":null},"body":"Junio C Hamano wrote:\n> Jeff Garzik <jeff@garzik.org> writes:\n> \n>> Here is how to reproduce:\n> \n> This is not related to the \"not clobbering untracked files\"\n> safety valve under discussion, but one thing I noticed.\n> \n>> git clone -l $url/torvalds/linux-2.6.git tmp-2.6\n>> cd tmp-2.6\n>> cp .git/refs/tags/v2.6.12 .git/refs/heads/tmp\n>> git checkout -f tmp\n> \n> This should never have been supported.  At this point tmp is a\n> tag object that is under heads/ -- a definite no-no.  We should\n> make checkout more careful to complain about it.\n> \n> Doing\n> \n>         git update-ref refs/heads/tmp $(git rev-parse v2.6.12^0)\n> \n> instead of \"cp\" is kosher, and\n> \n> \tgit-rev-parse v2.6.12^0 >.git/refs/heads/tmp\n> \n> is OK under the current implementation of refs.\n\nSorry about that.  The contrived example produced the same results as \nthe real-world example (updating jgarzik/{libata-dev,scsilun-2.6}.git \nbranches).\n\n\n>> git pull . master\n>> # watch OBVIOUS FAST-FORWARD MERGE complain about untracked\n>> # working tree files\n> \n> In any case, here is a patch I think would alleviate your\n> original problem.\n> \n> Sorry for the trouble.  I really did not want to disrupt the\n> workflow of old timers in the name of making it safer for new\n> people.  Could you comment on whether this is an acceptable\n> approach?\n> \n> -- >8 --\n> [PATCH] Conditionally loosen \"no clobber untracked files\" safety valve.\n> \n> This introduces a new configuration item \"core.oktoclobber\" to\n> control how untracked working tree file is handled during branch\n> switching.\n> \n> The safety valve introduced during 1.4.0 development cycle\n> refrains from checking out a file that exists in the working\n> tree, not in the current HEAD tree and exists in the branch we\n> are switching to, in order to prevent accidental and\n> irreversible lossage of user data.  This can be controlled by\n> having core.oktoclobber configuration item:\n\nI'm a bit under the weather today, so I must defer thinking about this. \n  :)  But if what Ryan says is true, about simply needing to ditch the \n\"-f\" argument I habitually pass to 'git checkout', would that alleviate \nthe need for a patch?\n\nFWIW, my workflow is\n\n\tcd /repos\n\tcd linux-2.6\n\tgit pull\n\tcd ../libata-dev\n\tgit checkout -f master\t# guarantee any WIP goes away\n\tgit pull ../linux-2.6\t# update vanilla branch\n\tgit checkout -f upstream# switch to working branch,\n\t\t\t\t# guarantee any WIP goes away.\n\tgit pull . master\t# pull latest upstream updates\n\tbuild/test/etc.\n\tgit checkout -f sii-m15w # switch to topic-specific branch,\n\t\t\t\t # whose parent is always #upstream\n\tgit pull . upstream\n\tbuild/test/etc.\n\trepeat for several topics (on-going devel branches)\n\tgit checkout -f -b ALL upstream\t# create everything-together\n\t\t\t\t\t# test branch\n\tgit pull . sii-m15w\n\tgit pull . topicB\n\tgit pull . topicC\n\tbuild/test/etc.\n\tgit checkout -f master\n\t./push\t\t# calls 'git push --force --all $url'\n\nMore tomorrow,\n\n\tJeff\n"},{"id":"22051","messageId":"7v4pyhdel5.fsf@assigned-by-dhcp.cox.net","threadId":"4558","inReplyTo":"4495DB3B.10403@garzik.org","subject":"Re: git 1.4.0 usability problem","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-19T03:11:34Z","receivedAt":"2006-06-19T03:11:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff Garzik <jeff@garzik.org> writes:\n\n> But if what Ryan says is true, about simply needing to ditch\n> the \"-f\" argument I habitually pass to 'git checkout', would that\n> alleviate the need for a patch?\n\nTo a certain degree, yes.\n\nBut I suspect (I am not a kernel person so I can only speculate)\nin the kernel workflow you would often pick up a patch from the\nlist, apply it to your working tree (without applying it to your\nindex, IOW with \"patch -p1\" or \"git apply\", not with \"git apply\n--index\"), and then decide to pull from somewhere else while\nyour working tree is dirty (but index is not).  The patch might\nhave created a new file or two, and the pull may also contain a\ncommit that applied the same patch in question.  The no-clobber\ncheck would trigger in such a case preventing you from pulling,\nand neither \"checkout\" nor \"checkout -f\" would clean these new\nfiles that you have not told git about.\n\n> FWIW, my workflow is\n>\n> \tcd /repos\n> \tcd linux-2.6\n> \tgit pull\n> \tcd ../libata-dev\n> \tgit checkout -f master\t# guarantee any WIP goes away\n\nWe kept saying \"with checkout -f any dirty state goes away from\nyour working tree\".  It is true only with respect to the files\ngit knows about.  The trouble you experienced was about\nuntracked files -- files git does not know about, and they will\nbe left behind.\n\nSo if path F is in test branch head and linus branch head, but\nnot in your master branch head, and you have checked out test in\nyour working tree, even if path F in the working tree is clean:\n\n\tgit checkout -f master\n\nwill leave F behind.  If you pull from linus at this point, the\ncheck would trigger.  Running \"git checkout master\" without -f\nwould however remove it and you would not have the problem.\nThat is what Ryan's suggestion is about.\n\nHowever, if you have a patch you got from somebody on the net\nthat creates F (maybe it is the same patch linus accepted\nrecently) while on your master branch, and you tried to examine\nit by applying it to your working tree with \"patch -p1\" or \"git\napply\", your working tree will have F that is not in index (and\nin your branch head).  In that state if you pull from linus, the\nno-clobber check triggers.  In this case, neither \"git checkout\nmaster\", \"git checkout -f master\", nor \"git reset --hard master\"\nwould remove F, because git does not even know about it, so\npulling from linus would fail.  \"git clean\" would removes F, so\nit may not be a big deal, but it is rather a heavy-handed\noperation that removes all crufts, so you may find it a\nnot-so-useful workaround (I certainly would, and that is the\nprimary reason I rarely use \"git clean\" myself).\n\nIt's a bit sad situation.  One of the useful feature of git is\nthat you can continue working in a dirty working tree as long as\nyour index is clean and your local changes do not interfere with\na merge, patch application, or branch switching.  Strictly\nspeaking, this no-clobber check _is_ about a local change that\ndoes interfere with the operation, so from theoretical point of\nview it is a good safety measure, but at the same time we did\nnot consider untracked files as precious until recently, and I\nsuspect that \"the same patch applied elsewhere to create the\nsame file\" pattern is reasonably common that this safety valve\nmay interfere the work more often than it may help avoiding\nmistakes.\n"},{"id":"22118","messageId":"4497B39E.2050205@garzik.org","threadId":"4558","inReplyTo":"7v4pyhdel5.fsf@assigned-by-dhcp.cox.net","subject":"Re: git 1.4.0 usability problem","fromName":"Jeff Garzik","fromEmail":"jeff@garzik.org","sentAt":"2006-06-20T08:36:46Z","receivedAt":"2006-06-20T08:36:46Z","isPatch":false,"sender":{"key":"jeff@garzik.org","avatar":null},"body":"Here's a real world example of the 1.4.0 change breaking a merge:\n\n(\"netdev-2.6\" == local clone of kernel.org/...jgarzik/netdev-2.6.git)\n[jgarzik@pretzel netdev-2.6]$ git branch\n   ALL\n   e100-sbit\n* master\n   upstream\n   upstream-linus\n\n[jgarzik@pretzel netdev-2.6]$ git pull /spare/repo/linux-2.6\nGenerating pack...\nDone counting 3427 objects.\nResult has 2510 objects.\nDeltifying 2510 objects.\n  100% (2510/2510) done\nUnpacking 2510 objects\nTotal 2510, written 2510 (delta 2024), reused 0 (delta 0)\n  100% (2510/2510) done\nUpdating from 427abfa28afedffadfca9dd8b067eb6d36bac53f to \n25f42b6af09e34c3f92107b36b5aa6edc2fdba2f\nfatal: Untracked working tree file 'drivers/net/myri10ge/Makefile' would \nbe overwritten by merge.\n\nEXPLANATION:\n\n* drivers/net/myri10ge/Makefile exists in latest Linus kernel tree, \nstored locally in /spare/repo/linux-2.6.\n* drivers/net/myri10ge/Makefile exists in netdev-2.6#upstream and \nnetdev-2.6#upstream-linus branches.\n* drivers/net/myri10ge/Makefile does not exist in current branch, \nnetdev-2.6#master.\n"},{"id":"22121","messageId":"20060620091622.GP25520@h4x0r5.com","threadId":"4558","inReplyTo":"4497B39E.2050205@garzik.org","subject":"Re: git 1.4.0 usability problem","fromName":"Ryan Anderson","fromEmail":"ryan@michonline.com","sentAt":"2006-06-20T09:16:23Z","receivedAt":"2006-06-20T09:16:23Z","isPatch":false,"sender":{"key":"ryan@michonline.com","avatar":null},"body":"On Tue, Jun 20, 2006 at 04:36:46AM -0400, Jeff Garzik wrote:\n> Here's a real world example of the 1.4.0 change breaking a merge:\n> \n> (\"netdev-2.6\" == local clone of kernel.org/...jgarzik/netdev-2.6.git)\n> [jgarzik@pretzel netdev-2.6]$ git branch\n>   ALL\n>   e100-sbit\n> * master\n>   upstream\n>   upstream-linus\n> \n> [jgarzik@pretzel netdev-2.6]$ git pull /spare/repo/linux-2.6\n> Generating pack...\n> Done counting 3427 objects.\n> Result has 2510 objects.\n> Deltifying 2510 objects.\n>  100% (2510/2510) done\n> Unpacking 2510 objects\n> Total 2510, written 2510 (delta 2024), reused 0 (delta 0)\n>  100% (2510/2510) done\n> Updating from 427abfa28afedffadfca9dd8b067eb6d36bac53f to \n> 25f42b6af09e34c3f92107b36b5aa6edc2fdba2f\n> fatal: Untracked working tree file 'drivers/net/myri10ge/Makefile' would \n> be overwritten by merge.\n> \n> EXPLANATION:\n> \n> * drivers/net/myri10ge/Makefile exists in latest Linus kernel tree, \n> stored locally in /spare/repo/linux-2.6.\n> * drivers/net/myri10ge/Makefile exists in netdev-2.6#upstream and \n> netdev-2.6#upstream-linus branches.\n> * drivers/net/myri10ge/Makefile does not exist in current branch, \n> netdev-2.6#master.\n\nIf that is the case, how did it get into the directory, then?\n\nI suspect the history we're missing is this:\n\ngit checkout upstream\n...\ngit checkout -f master\n\nIf you have a clean tree, there's not really a reason to use -f.  It\nactively hurts you by confusing git as to what state your directory is\nin. (If you don't have a clean tree, well, using -f will orphan new\nfiles that Git knows about, and overwrite the changes on ones it does,\nso it's still rather inconsistent, and probably not at all what you\nintend.)\n\nInstead of using \"git checkout -f\" to abandon any WIP, try something\nlike this:\n\n\tgit branch throw-away HEAD\n\tgit checkout throw-away\n\tgit commit -a -m \"throw away\"\n\tgit checkout $1\n\tgit branch -D throw-away\n\n\ni.e:\n$ sed -i -e 's/PHONY/YNOHP/g' Makefile\n$ git branch throw-away HEAD\n$ git checkout throw-away\n$ git diff |diffstat\n Makefile |   60 ++++++++++++++++++++++++++++++------------------------------\n$ git commit -a -m \"throw-away\"\n$ git checkout master\n$ git branch -d throw-away\nThe branch 'throw-away' is not a strict subset of your current HEAD.\nIf you are sure you want to delete it, run 'git branch -D throw-away'.\n$ git branch -D throw-away\nDeleted branch throw-away.\n$ git diff | diffstat\n0 files changed\n$ git branch throw-away HEAD\n$ cp Makefile Makefile-ryan\n$ git add Makefile-ryan \n$ git checkout throw-away\n$ git diff | diffstat\n 0 files changed\n$ git status\n# On branch refs/heads/throw-away\n#\n# Updated but not checked in:\n#   (will commit)\n#\n#\tnew file: Makefile-ryan\n#\n$ git commit -a -m \"throw-away\"\n$ git checkout master\n$ git status\nnothing to commit\n\nNote that using plain \"checkout\" should be noticeably faster, too.\n\n\n\n\n\n-- \n\nRyan Anderson\n  sometimes Pug Majere\n"},{"id":"22122","messageId":"7vr71kb257.fsf@assigned-by-dhcp.cox.net","threadId":"4558","inReplyTo":"4497B39E.2050205@garzik.org","subject":"Re: git 1.4.0 usability problem","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-20T09:35:32Z","receivedAt":"2006-06-20T09:35:32Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff Garzik <jeff@garzik.org> writes:\n\n> Here's a real world example of the 1.4.0 change breaking a merge:\n>\n> (\"netdev-2.6\" == local clone of kernel.org/...jgarzik/netdev-2.6.git)\n> [jgarzik@pretzel netdev-2.6]$ git branch\n>   ALL\n>   e100-sbit\n> * master\n>   upstream\n>   upstream-linus\n>\n> [jgarzik@pretzel netdev-2.6]$ git pull /spare/repo/linux-2.6\n> ...\n> Updating from 427abfa28afedffadfca9dd8b067eb6d36bac53f to\n> 25f42b6af09e34c3f92107b36b5aa6edc2fdba2f\n> fatal: Untracked working tree file 'drivers/net/myri10ge/Makefile'\n> would be overwritten by merge.\n>\n> EXPLANATION:\n>\n> * drivers/net/myri10ge/Makefile exists in latest Linus kernel tree,\n> stored locally in /spare/repo/linux-2.6.\n> * drivers/net/myri10ge/Makefile exists in netdev-2.6#upstream and\n> netdev-2.6#upstream-linus branches.\n> * drivers/net/myri10ge/Makefile does not exist in current branch,\n> netdev-2.6#master.\n\nRequesting one more bit of explanation.\n\nWhen you did this pull, you were on your \"master\" branch.  Whose\nHEAD does not have the myri10ge/Makefile in its tree.  And you\ndid not have that path in the index either (otherwise it would\nnot have said \"untracked working tree file\").  Did you have that\nfile in your working tree?  And if so how/why?\n\nIf you did something like this before ending up in your \"master\"\nbranch, I think you would have such a file:\n\n\t$ git branch ;# you were in upstream-linus branch\n          ALL\n          e100-sbit\n          master\n          upstream\n        * upstream-linus\n        $ git diff      ;# and were up-to-date -- no output nor\n        $ git diff HEAD ;# local changes\n        $ git checkout -f master ;# but you switched to master with -f\n\nWith \"checkout -f\", your local changes to files that appear in\nthe \"master\" branch will be overwritten, but the files that are\nsupposed to disappear because you are switching out of the\ncurrent branch (e.g. myri10ge/Makefile) are left behind.\n\nIt probably would make sense to change \"checkout -f\" so that it\nremoves such files from your working tree to support this\nparticular usage.  We kept saying \"with -f local dirty state\nwill be gone\", but \"checkout -f\" does not do as thorough job as\n\"reset --hard\".  Changing \"checkout -f next-branch\" to do the\nmoral equivalent of \"reset --hard HEAD && checkout next-branch\"\nwould solve this problem, and I do not think changing it that\nway would not have any negative impact.\n\nI suspect this patch would do exactly that...\n\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 564117f..193f6c5 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -137,7 +137,7 @@ # what we already had\n \n if [ \"$force\" ]\n then\n-    git-read-tree --reset $new &&\n+    git-read-tree --reset -u $new &&\n \tgit-checkout-index -q -f -u -a\n else\n     git-update-index --refresh >/dev/null\n"},{"id":"22125","messageId":"7vfyi0b1gv.fsf_-_@assigned-by-dhcp.cox.net","threadId":"4558","inReplyTo":"7vr71kb257.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] checkout -f: do not leave untracked working tree files.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-20T09:50:08Z","receivedAt":"2006-06-20T09:50:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Earlier we did not consider untracked working tree files\n\"precious\", but we have always considered them fair game to\nclobber.  These days, branch switching by read-tree is more\ncareful and tries to protect untracked working tree files.  This\ncaused the following workflow to stop working:\n\n\tgit checkout one-branch-with-file-F\n\tgit checkout -f another-without-file-F\n\tgit pull . one-branch-with-file-F\n\nBecause the second checkout leaves F from the previous state as\nuntracked file in the working tree, the merge would fail, trying\nto protect F from being clobbered.\n\nThis changes \"git checkout -f\" to remove working tree files that\nare known to git in the switched-from state but do not exist in\nthe switched-to state, borrowing the same logic from \"reset --hard\".\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n * I am going to bed without trying this out since it is very\n   late tonight.  Might be in \"pu\" or \"next\" tomorrow depending\n   on my mood.  If this works out for Jeff, I can simply drop\n   the \"core.oktoclobber = ask\" patch from my topics -- although\n   I kind of liked that one ;-).\n\n git-checkout.sh |    3 +--\n 1 files changed, 1 insertions(+), 2 deletions(-)\n\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 564117f..77c2593 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -137,8 +137,7 @@ # what we already had\n \n if [ \"$force\" ]\n then\n-    git-read-tree --reset $new &&\n-\tgit-checkout-index -q -f -u -a\n+    git-read-tree --reset -u $new\n else\n     git-update-index --refresh >/dev/null\n     merge_error=$(git-read-tree -m -u $old $new 2>&1) || (\n-- \n1.4.0.g59268\n"},{"id":"22128","messageId":"8764iw5bvl.fsf@gmail.com","threadId":"4558","inReplyTo":"7vfyi0b1gv.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] checkout -f: do not leave untracked working tree files.","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2006-06-20T11:01:50Z","receivedAt":"2006-06-20T11:01:50Z","isPatch":true,"sender":{"key":"santi@agolina.net","avatar":null},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Earlier we did not consider untracked working tree files\n> \"precious\", but we have always considered them fair game to\n> clobber.  These days, branch switching by read-tree is more\n> careful and tries to protect untracked working tree files.  This\n> caused the following workflow to stop working:\n>\n> \tgit checkout one-branch-with-file-F\n> \tgit checkout -f another-without-file-F\n> \tgit pull . one-branch-with-file-F\n>\n> Because the second checkout leaves F from the previous state as\n> untracked file in the working tree, the merge would fail, trying\n> to protect F from being clobbered.\n>\n> This changes \"git checkout -f\" to remove working tree files that\n> are known to git in the switched-from state but do not exist in\n> the switched-to state, borrowing the same logic from \"reset --hard\".\n>\n\nI agree with this patch (without testing).\n\nAnother thing to take into account is that, for this particular\ncase/sequence, the untracked file-F is exactly the same as the one from\nthe pull, so you are not overwritting that file and it could succeed.\n\n    Santi\n"},{"id":"22129","messageId":"7vfyi09isf.fsf@assigned-by-dhcp.cox.net","threadId":"4558","inReplyTo":"8764iw5bvl.fsf@gmail.com","subject":"Re: [PATCH] checkout -f: do not leave untracked working tree files.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-20T11:18:56Z","receivedAt":"2006-06-20T11:18:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Santi Béjar <sbejar@gmail.com> writes:\n\n> Another thing to take into account is that, for this particular\n> case/sequence, the untracked file-F is exactly the same as the one from\n> the pull, so you are not overwritting that file and it could succeed.\n\nYes and no.  The untracked file is not even known to git when\npull is happening (that is the definition of \"untracked\").  Yes,\nwe could see if the contents happen to match and choose to\noverwrite, but I think it is often more likely that the contents\ndo not match that it is not worth it (I have not examined what\nit would involve to add that check yet, so it might turn out to\nbe a cheap check but I doubt it).\n"},{"id":"22130","messageId":"200606201827.50808.lan@academsoft.ru","threadId":"4558","inReplyTo":"7vfyi09isf.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] checkout -f: do not leave untracked working tree files.","fromName":"Alexander Litvinov","fromEmail":"lan@academsoft.ru","sentAt":"2006-06-20T11:27:50Z","receivedAt":"2006-06-20T11:27:50Z","isPatch":true,"sender":{"key":"lan@academsoft.ru","avatar":null},"body":"Good news. I have a habbit to switch branches using two commands:\n\ngit checkout -f second-branch\ngit clean -d -q\n\nNow this will work with single command. Thanks.\n"},{"id":"22131","messageId":"7vveqw82qd.fsf@assigned-by-dhcp.cox.net","threadId":"4558","inReplyTo":"200606201827.50808.lan@academsoft.ru","subject":"Re: [PATCH] checkout -f: do not leave untracked working tree files.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-20T11:51:06Z","receivedAt":"2006-06-20T11:51:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alexander Litvinov <lan@academsoft.ru> writes:\n\n> Good news. I have a habbit to switch branches using two commands:\n>\n> git checkout -f second-branch\n> git clean -d -q\n>\n> Now this will work with single command. Thanks.\n\n\"will\" meaning \"you suspect\" or \"you tried and confirmed\"?\n"},{"id":"22132","messageId":"200606201908.53318.lan@academsoft.ru","threadId":"4558","inReplyTo":"7vveqw82qd.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] checkout -f: do not leave untracked working tree files.","fromName":"Alexander Litvinov","fromEmail":"lan@academsoft.ru","sentAt":"2006-06-20T12:08:53Z","receivedAt":"2006-06-20T12:08:53Z","isPatch":true,"sender":{"key":"lan@academsoft.ru","avatar":null},"body":"> \"will\" meaning \"you suspect\" or \"you tried and confirmed\"?\n:-) I suspect.\n\nLets test. Your pu branch (5af05efbeaa06005596129fb111a739a87f8a883) really \nworks. I have cvs repo and use git for daily work. I have head and 2 branches \nfrom cvs and store CVS/* files in git too. Usualy this operation pruduce a \nlot of CVS/Tag files:\n\ngit checkout -f cvs-v52 (this is one of by cvs's branch)\ncvs -q up -dP (nothing have been updated)\ngit checkout -f master (this is a dev branch from cvs head)\ngit status\n\npu branch nuke them when use git checkout -f !\n"},{"id":"22139","messageId":"87sllzsyy8.wl%cworth@cworth.org","threadId":"4558","inReplyTo":"7vfyi0b1gv.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] checkout -f: do not leave untracked working tree files.","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-06-20T14:07:11Z","receivedAt":"2006-06-20T14:07:11Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Tue, 20 Jun 2006 02:50:08 -0700, Junio C Hamano wrote:\n> \n> Earlier we did not consider untracked working tree files\n> \"precious\", but we have always considered them fair game to\n> clobber.  These days, branch switching by read-tree is more\n> careful and tries to protect untracked working tree files.  This\n> caused the following workflow to stop working:\n> \n> \tgit checkout one-branch-with-file-F\n> \tgit checkout -f another-without-file-F\n> \tgit pull . one-branch-with-file-F\n\nAnother one that a colleague of mine hit is:\n\n\tgit checkout -b branch-without-file branch-with-file\n\tgit rm some-file\n\t# Allow for some external changes on branch-with-file\n\tgit pull . branch-with-file\n\nOne possibility for fixing this case is to make git-rm delete the file\nby default, (that is, act as if the current -f option is\npassed). There's no real safety concern unless the file is dirty,\n(could require -f again for that case).\n\n>                 If this works out for Jeff, I can simply drop\n>    the \"core.oktoclobber = ask\" patch from my topics -- although\n>    I kind of liked that one ;-).\n\nFixing the behavior instead of adding configuration is definitely a\ngood plan.\n\n-Carl\n"}]}