{"thread":{"id":"1475","subject":"Re: bisect gives strange answer","startedAt":"2005-08-11T22:07:45Z","lastAt":"2005-08-11T22:07:45Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"7079","messageId":"7vk6isgma6.fsf@assigned-by-dhcp.cox.net","threadId":"1475","inReplyTo":"E1E3HoN-0002ET-Ht@approximate.corpus.cam.ac.uk","subject":"Re: bisect gives strange answer","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-11T22:07:45Z","receivedAt":"2005-08-11T22:07:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sanjoy Mahajan <sanjoy@mrao.cam.ac.uk> writes:\n\n> I'm having doing a stupidity with git, but here's what is confusing me\n> about using bisect:\n>\n> If I start with a clean directory except for a 2.6 .git/ (where master =\n> d95a1b4818f2fe38a3cfc9a7d5817dc9a1a69329), then do\n>\n> $ cd linux-2.6\n> $ ls\n> $ cat .git/HEAD\n> d95a1b4818f2fe38a3cfc9a7d5817dc9a1a69329\n> $ git bisect start\n> $ git bisect good 17af691cd19765b782d891fc50c1568d0f1276b3\n> $ git bisect bad c101f3136cc98a003d0d16be6fab7d0d950581a6  \n> Bisecting: 42 revisions left to test after this\n> $ ls\n> arch\t Documentation\tinclude  kernel       Makefile\tREADME\t  sound\n> CREDITS  drivers\tinit\t lib\t      mm\tscripts\n> crypto\t fs\t\tipc\t MAINTAINERS  net\tsecurity\n>\n> What happened to, for example, COPYING?  Maybe I am doing something\n> silly (which I did before so I didn't get the right kernel trees to\n> compile?).  If I do 'git reset' first, then COPYING is there.\n\nAlthough I think what you saw is pathological, I do not think it\nis what you did that is wrong.  The same thing happens if you\nhave .git/HEAD pointing at some version, you have nothing\nchecked out, and \"git pull\" from the upstream which results in a\nfast forward merge.  Only the files that have been changed\nbetween ORIG_HEAD and FETCH_HEAD are checked out.\n\nWhat is happening is that git-checkout-script, which uses\n\"git-read-tree -m -u\", checks out only the files that have\nchanged between the \"current suspect\" version and \"next suspect\"\nversion, leaving other paths untouched.  This means that if\n\"other paths\" were not in the working tree to begin with, they\nare left not-checked-out.\n\nThis is because the 'git-read-tree -m A B' is designed to allow\ntwo-tree fast-forward merge work safely in a working tree that\nhas local modifications.  The local modification in your case is\nthat \"you removed all files\".  This is further complicated by\nthat the low-level git design wants to work in a non-populated\ntree and treats not having a file in the working tree a bit\ndifferently from having a file that is modified in the working\ntree.  read-tree.c::verify_uptodate() function says when you\nremoved a file that is recorded in the index, it does not\nconsider you have a local modification on that path.\n\nThe paths that were not checked out fall in the case 14 in the\nDocumentation/git-read-tree.txt \"Two Tree Merge\" table, and the\npath is not marked for update in \"keep index\" cases.\n\nAlthough I think what git-read-tree currently does is\ndefensible, I do not think what \"git checkout\" does is.  The\nuser is asking things to be checked out so it is not a \"work\nwithout files in working tree\" case anymore.\n\nMaybe we should check if the working tree is clean before using\ngit-read-tree -m -u and require --force if it is not, perhaps?\n\nThe following patch is not tested at all but I am throwing it\nout in the open early, in case the approach I am taking is\ntotally going in the wrong direction.\n\n\n---\ncd /opt/packrat/playpen/public/in-place/git/git.junio/\njit-diff\n# - pu: Debian packaging fixes.\n# + (working tree)\ndiff --git a/git-checkout-script b/git-checkout-script\n--- a/git-checkout-script\n+++ b/git-checkout-script\n@@ -56,7 +56,9 @@ then\n     git-read-tree --reset $new &&\n \tgit-checkout-cache -q -f -u -a\n else\n-    git-read-tree -m -u $old $new\n+    git-update-cache --refresh &&\n+    git-read-tree -m -u $old $new ||\n+    \tdie \"git checkout: your working tree is dirty\"\n fi\n \n # \ndiff --git a/read-tree.c b/read-tree.c\n--- a/read-tree.c\n+++ b/read-tree.c\n@@ -86,7 +86,7 @@ static void verify_uptodate(struct cache\n \t\t\treturn;\n \t\terrno = 0;\n \t}\n-\tif (errno == ENOENT)\n+\tif (errno == ENOENT && !update)\n \t\treturn;\n \tdie(\"Entry '%s' not uptodate. Cannot merge.\", ce->name);\n }\n"}]}