{"thread":{"id":"52295","subject":"[BUG] \"git checkout BRANCH -- FILE\" deletes staged commits","startedAt":"2019-11-19T17:10:07Z","lastAt":"2019-11-22T03:14:17Z","messageCount":2,"participants":["Tasnad Kernetzky","Brandon McCaig"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"386538","messageId":"5cb30154-5753-f229-9fa2-6c82d2896abc@gmail.com","threadId":"52295","inReplyTo":null,"subject":"[BUG] \"git checkout BRANCH -- FILE\" deletes staged commits","fromName":"Tasnad Kernetzky","fromEmail":"tasnadk@gmail.com","sentAt":"2019-11-19T17:10:01Z","receivedAt":"2019-11-19T17:10:07Z","isPatch":false,"sender":{"key":"tasnadk@gmail.com","avatar":null},"body":"Hi,\n\nI suppose I found a bug in git version 2.24.0. Please consider the small\nshell script to reproduce.\n\nBest,\n\nTasnad\n\n\n#!/bin/bash\n# init repo, create master branch\ngit init\necho 'master' > tst\ngit add tst\ngit ci -m 'master'\n\n# create branch \"B\" where tst contains the line from master plus a line \"B\"\ngit checkout -b B\necho 'B' >> tst\ngit commit -am 'B'\n\n# back in master: stage a change\ngit checkout master\necho 'master_dirty' >> tst\ngit add tst\necho '*** tst should contain [master, master_dirty]: ***'\ncat tst\necho '-------------'\n\n# checkout copies over contents from B -> I guess the bug is here,\nchanges are not detected\ngit checkout B -- tst\ngit status\necho '-> this seems to be wrong, change is not detected'\n\n# if we now go to B and back to master, we loose staged changes\necho '*** tst should contain [master, B]: ***'\ncat tst\necho '-------------'\ngit checkout B\necho '*** tst should contain [master, B]: ***'\ncat tst\necho '-------------'\ngit checkout master\necho '*** tst should contain [master, B]: ***'\ncat tst\necho '-------------'\necho '-> wrong / staged changes lost!?'\n\n\n"},{"id":"386792","messageId":"20191122031411.zrg5hv4dvk6dxxus@test-chamber-21.localdomain","threadId":"52295","inReplyTo":"5cb30154-5753-f229-9fa2-6c82d2896abc@gmail.com","subject":"Re: [BUG] \"git checkout BRANCH -- FILE\" deletes staged commits","fromName":"Brandon McCaig","fromEmail":"bamccaig@gmail.com","sentAt":"2019-11-22T03:14:11Z","receivedAt":"2019-11-22T03:14:17Z","isPatch":false,"sender":{"key":"bamccaig@gmail.com","avatar":"https://gravatar.com/avatar/05b01f2b62a5ddbaa1946579266a8d9e970fed0c0b3c20e8d42aca973c31531c?d=mp&s=160"},"body":"On Tue, Nov 19, 2019 at 06:10:01PM +0100, Tasnad Kernetzky wrote:\n> Hi,\n\nHello,\n\n> I suppose I found a bug in git version 2.24.0. Please consider the small\n> shell script to reproduce.\n*snip*\n> # checkout copies over contents from B -> I guess the bug is here,\n> changes are not detected\n> git checkout B -- tst\n> git status\n> echo '-> this seems to be wrong, change is not detected'\n> \n> # if we now go to B and back to master, we loose staged changes\n> echo '*** tst should contain [master, B]: ***'\n> cat tst\n> echo '-------------'\n> git checkout B\n> echo '*** tst should contain [master, B]: ***'\n> cat tst\n> echo '-------------'\n> git checkout master\n> echo '*** tst should contain [master, B]: ***'\n> cat tst\n> echo '-------------'\n> echo '-> wrong / staged changes lost!?'\n\nI don't think this is a bug at all.\n\nThis form of checkout is basically a way to \"revert\" or \"restore\"\na file to match whichever tree-ish you select:\n\n    git checkout ... -- file...\n\nIt is not a merge. It is overwriting whatever version of the file\nyou have, and staging those changes. There's no point warning you\nthat your file is different because you're giving git strict\ninstructions to overwrite the file. You shouldn't be doing that\nunless you already know what the file's state is and you know you\ndon't want it. If in doubt stash, commit, or copy the file\nfirst.\n\nWhen you do `git checkout B -- tst` you are basically saying to\ncheckout the file tst as it exists at the tip of branch B and\nstage it for commit.\n\nWhen you switch back to branch B the state of the tst file is the\nsame as it exists in the branch B. There is no conflict here so\nit succeeds, and once it does you no longer have any changes made\nto tst because the version in your index and working tree matches\nthe version in the HEAD commit.\n\ngit status at this point would report nothing (assuming no other\nfiles are modified).\n\nWhen you switch back to master it happily overwrites tst to match\nthe version committed to the head of master because the version\nyou had on B is already committed (and is easily recovered from B\nif desired). There's no conflict there and no reason to fail or\nrefuse.\n\nThis is normal behavior. Check the documentation and if you think\nit's unclear you can make suggestions to improve it or better yet\nsubmit a patch that does just that for review.\n\nI haven't really been paying much attention to the development of\ngit, but I recall efforts were being made to split the various\nbehaviors of git-checkout into separate commands to help improve\nthe interface because some people struggle with it. Sounds like\nthese take the form of git-switch to change branches and\ngit-restore to restore files to some other version. It sounds\nlike git-restore will still work the same way in this regard\nthough so I don't think that changes anything.\n\nRegards,\n\n\n\n-- \nBrandon McCaig <bamccaig@gmail.com> <bambams@castopulence.org>\nCastopulence Software <https://www.castopulence.org/>\nBlog <http://www.bambams.ca/>\nperl -E '$_=q{V zrna gur orfg jvgu jung V fnl. }.\nq{Vg qbrfa'\\''g nyjnlf fbhaq gung jnl.};\ntr/A-Ma-mN-Zn-z/N-Zn-zA-Ma-m/;say'\n\n"}]}