{"thread":{"id":"53508","subject":"Bug: git worktree remove and overwritten directory","startedAt":"2020-05-20T10:36:39Z","lastAt":"2020-06-08T14:07:44Z","messageCount":6,"participants":["Jonathan Müller","Shourya Shukla","Eric Sunshine"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"398244","messageId":"89526b3a-297d-591d-6e12-48580d697ed5@gmail.com","threadId":"53508","inReplyTo":null,"subject":"Bug: git worktree remove and overwritten directory","fromName":"Jonathan Müller","fromEmail":"jonathanmueller.dev@gmail.com","sentAt":"2020-05-20T10:36:34Z","receivedAt":"2020-05-20T10:36:39Z","isPatch":false,"sender":{"key":"jonathanmueller.dev@gmail.com","avatar":"https://gravatar.com/avatar/b2125bfca28c0051a03f69c4e09a215a45dc71418de7b1ffeb63cf779f4f1c85?d=mp&s=160"},"body":"Apologies, if this has already been reported.\n\nIt seems to be impossible to remove a git worktree whose location has \nbeen replaced by the main working tree (don't ask how I found out). \nSteps to reproduce:\n\n```\ngit init test\ncd test\ngit commit --allow-empty -m\"Initial commit\"\ngit branch some-branch\ngit worktree add ../test2 some-branch\ncd ../\nrm -rf test2  # Remove the worktree folder\nmv test test2 # Main git repository now located where the worktree used \nto be\n```\n\nAfterwards, `git worktree list` reports:\n\n/home/foonathan/test2  e7bb748 [master]\n/home/foonathan/test2  e7bb748 [some-branch]\n\nAnd both `git worktree remove .` and `git worktree remove ../test2` \nreport an error `fatal: '../test2' is a main working tree`. I had to \nmanually remove the corresponding folder from `.git/worktree` to get rid \nof it. The issue is especially annoying, because you can't check out \n`some-branch` anymore (as it's already checked out in the worktree).\n\nI've tested it with git version 2.26.2 and also the version currently on \nthe next branch.\n\nThank you,\nJonathan\n"},{"id":"398248","messageId":"20200520133820.GA15133@konoha","threadId":"53508","inReplyTo":"89526b3a-297d-591d-6e12-48580d697ed5@gmail.com","subject":"Re: Bug: git worktree remove and overwritten directory","fromName":"Shourya Shukla","fromEmail":"shouryashukla.oo@gmail.com","sentAt":"2020-05-20T13:38:20Z","receivedAt":"2020-05-20T13:38:28Z","isPatch":false,"sender":{"key":"shouryashukla.oo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43680618?v=4"},"body":"Hello Jonathan!\n\n> And both `git worktree remove .` and `git worktree remove ../test2`\n> report an error `fatal: '../test2' is a main working tree`. I had to\n> manually remove the corresponding folder from `.git/worktree` to get rid\n> of it. The issue is especially annoying, because you can't check out\n> `some-branch` anymore (as it's already checked out in the worktree).\n\nIf you refer to the documentation of `git worktree` you may find this:\n\n    Multiple checkout in general is still experimental, and the support\n    for submodules is incomplete. It is NOT recommended to make multiple\n    checkouts of a superproject.\n\nAlright, so if you were to do a checkout to `some-branch` even if you\nnever deleted anything, you won't be able to perform this action because\nit's not possible, therefore *this* thing is not a bug. Why can't you\nperform this you ask? Because this is the point of the whole command. If\nyou were allowed to checkout, then you would be able to have two\ndifferent copies of the same thing at one instant of time, which is\nsomething we don't want.\n\nMoving on, one may say, \"I am technically in the same repo only, its\njust that the folder names are changed, so I can technically do a\ncheckout now because my worktree is gone right?\". No, we cannot,\nbecause: technicalities. You see, that when you create a worktree,\nyou add an entry in `$GIT_DIR/worktrees/` that `test2` is a registered\nworktree by you. Now if one does the mischief you did by renaming `test`\nto `test2`, you confuse the system as to what exactly is going on. It\nstill thinks that we are on `test2`, but in fact we are on `test`.\nHence, the dual nature we have here. Please refer to this for more detail:\nhttps://git-scm.com/docs/git-worktree#_details\n\nNow, if you delete the `$GIT_DIR/worktrees/` folder (proceeding\nfurther), you will be able to checkout to `some-branch` because the\nconfusion is gone now as Git is not aware of any worktrees you ever\ncreated.\n\nTherefore the final set of commands to overcome this will be:\n    git init test\n    cd test\n    git commit --allow-empty -m\"Initial commit\"\n    git branch some-branch\n    git worktree add ../test2 some-branch\n    cd ../\n    rm -rf test2\n    mv test test2\n    rm -rf .git/worktrees\n    git checkout some-branch\n    ... we can checkout successfully now :)\n\nNow, I can be wrong in some places in my explanation, but this is what\nI could infer from the problem.\n\nSo, coming to the ultimate question:\n    Is this a bug?\nI don't really think so. Why you ask? Because this is the way things\nshould have functioned. It is more of a vulnerability.\nYou may want to refer to this:\nhttps://stackoverflow.com/a/402944/10751129\n\nBut again, this doesn't mean that it can't be fixed.\nThanks to you I got introduced to a new git command (git worktree) :)\n\nRegards,\nShourya Shukla\n"},{"id":"398251","messageId":"CAPig+cTU8+N6Chimpoa2_T-TcXxw-3B9-9pjCLz7WeOh472P_A@mail.gmail.com","threadId":"53508","inReplyTo":"89526b3a-297d-591d-6e12-48580d697ed5@gmail.com","subject":"Re: Bug: git worktree remove and overwritten directory","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2020-05-20T14:22:45Z","receivedAt":"2020-05-20T14:23:01Z","isPatch":false,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, May 20, 2020 at 6:36 AM Jonathan Müller\n<jonathanmueller.dev@gmail.com> wrote:\n> It seems to be impossible to remove a git worktree whose location has\n> been replaced by the main working tree [...]\n>\n> cd test\n> git worktree add ../test2 some-branch\n> cd ../\n> rm -rf test2  # Remove the worktree folder\n> mv test test2 # Main git repository now located where the worktree used\n> to be\n>\n> Afterwards, `git worktree list` reports:\n>\n> /home/foonathan/test2  e7bb748 [master]\n> /home/foonathan/test2  e7bb748 [some-branch]\n>\n> And both `git worktree remove .` and `git worktree remove ../test2`\n> report an error `fatal: '../test2' is a main working tree`. I had to\n> manually remove the corresponding folder from `.git/worktree` to get rid\n> of it. The issue is especially annoying, because you can't check out\n> `some-branch` anymore (as it's already checked out in the worktree).\n\nGit tries hard to prevent the same directory from being registered to\nmultiple worktrees, however, there is not much it can do to prevent a\nperson from shooting himself in the foot by making changes like this\noutside of Git's control. Thus, this seems like a case of \"if it\nhurts, don't do it\".\n\nHowever, \"git worktree\" could possibly do a better job of helping you\nrecover from such a situation. In particular, I think it should be\nreasonably easy to enhance \"git worktree prune\" to detect this\nsituation and automatically prune the non-main now-bogus worktree\nentry.\n\nIt may be possible to special-case \"git worktree remove\" to detect\nthis situation and automatically prune the bogus entry too, but I'm\nquite hesitant to suggest that sort of special case both because the\nimplementation would likely be ugly, and it could lead to a plethora\nof additional ugly special-cases as people discover even more ways to\nshoot themselves in the feet.\n\nIf you have ideas about how else the situation can be improved, please\nfeel free to share them, as such discussion may shed light on\npossibilities which are not presently obvious.\n"},{"id":"398252","messageId":"dd7c3a11-6537-74ec-053c-0c9c946c5f19@gmail.com","threadId":"53508","inReplyTo":"CAPig+cTU8+N6Chimpoa2_T-TcXxw-3B9-9pjCLz7WeOh472P_A@mail.gmail.com","subject":"Re: Bug: git worktree remove and overwritten directory","fromName":"Jonathan Müller","fromEmail":"jonathanmueller.dev@gmail.com","sentAt":"2020-05-20T14:28:10Z","receivedAt":"2020-05-20T14:28:18Z","isPatch":false,"sender":{"key":"jonathanmueller.dev@gmail.com","avatar":"https://gravatar.com/avatar/b2125bfca28c0051a03f69c4e09a215a45dc71418de7b1ffeb63cf779f4f1c85?d=mp&s=160"},"body":"On 20.05.20 16:22, Eric Sunshine wrote:\n> Git tries hard to prevent the same directory from being registered to\n> multiple worktrees, however, there is not much it can do to prevent a\n> person from shooting himself in the foot by making changes like this\n> outside of Git's control. Thus, this seems like a case of \"if it\n> hurts, don't do it\".\n> \n\nI agree and didn't expect git to \"work\".\n\n> However, \"git worktree\" could possibly do a better job of helping you\n> recover from such a situation. In particular, I think it should be\n> reasonably easy to enhance \"git worktree prune\" to detect this\n> situation and automatically prune the non-main now-bogus worktree\n> entry.\n\nAt the very least, the somewhat confusing error message could be \nreplaced by a \"you messed up the worktrees, please delete the \ncorresponding entry in .git/worktree\" or something like that. But \nenhancing `git worktree prune` would be better. It was, in fact, the \nfirst command I ran to try and fix the problem.\n\n> It may be possible to special-case \"git worktree remove\" to detect\n> this situation and automatically prune the bogus entry too, but I'm\n> quite hesitant to suggest that sort of special case both because the\n> implementation would likely be ugly, and it could lead to a plethora\n> of additional ugly special-cases as people discover even more ways to\n> shoot themselves in the feet.\n\nAs said above, I think git worktree remove could issue a better error if \nit detects multiple worktrees with an identical path.\n"},{"id":"399281","messageId":"CAPig+cTpcgunPNKrzfqKYRb3gVhYff7UiBza-xaTH9GqH_Y+gA@mail.gmail.com","threadId":"53508","inReplyTo":"dd7c3a11-6537-74ec-053c-0c9c946c5f19@gmail.com","subject":"Re: Bug: git worktree remove and overwritten directory","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2020-06-08T06:42:05Z","receivedAt":"2020-06-08T06:42:21Z","isPatch":false,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, May 20, 2020 at 10:28 AM Jonathan Müller\n<jonathanmueller.dev@gmail.com> wrote:\n> On 20.05.20 16:22, Eric Sunshine wrote:\n> > Git tries hard to prevent the same directory from being registered to\n> > multiple worktrees, however, there is not much it can do to prevent a\n> > person from shooting himself in the foot by making changes like this\n> > outside of Git's control. Thus, this seems like a case of \"if it\n> > hurts, don't do it\".\n>\n> I agree and didn't expect git to \"work\".\n\nI just posted a patch series[1] which enhances \"git worktree prune\" to\ndetect and deal with multiple worktree entries referencing the same\npath.\n\n> > However, \"git worktree\" could possibly do a better job of helping you\n> > recover from such a situation. In particular, I think it should be\n> > reasonably easy to enhance \"git worktree prune\" to detect this\n> > situation and automatically prune the non-main now-bogus worktree\n> > entry.\n>\n> At the very least, the somewhat confusing error message could be\n> replaced by a \"you messed up the worktrees, please delete the\n> corresponding entry in .git/worktree\" or something like that. But\n> enhancing `git worktree prune` would be better. It was, in fact, the\n> first command I ran to try and fix the problem.\n>\n> As said above, I think git worktree remove could issue a better error if\n> it detects multiple worktrees with an identical path.\n\nHmm, the message it printed complaining that you tried removing the\nmain worktree seems pretty accurate since that extra worktree entry\nwas indeed pointing at the main worktree. I suppose it would be\npossible to have \"git worktree remove\" also perform \"corruption\ndetection\" so as to present additional information which might clarify\nthe complaint. Of course, if that is done, then it would make sense to\nmake all \"git worktree\" commands likewise report corruption. However,\nI haven't convinced myself that we need to go that far. Anyhow, the\nposted patch series[1] addresses the immediate problem.\n\n[1]: https://lore.kernel.org/git/20200608062356.40264-1-sunshine@sunshineco.com/T/\n"},{"id":"399296","messageId":"bfc471e6-c82e-ba22-79d1-349e071c6b17@gmail.com","threadId":"53508","inReplyTo":"CAPig+cTpcgunPNKrzfqKYRb3gVhYff7UiBza-xaTH9GqH_Y+gA@mail.gmail.com","subject":"Re: Bug: git worktree remove and overwritten directory","fromName":"Jonathan Müller","fromEmail":"jonathanmueller.dev@gmail.com","sentAt":"2020-06-08T14:07:39Z","receivedAt":"2020-06-08T14:07:44Z","isPatch":false,"sender":{"key":"jonathanmueller.dev@gmail.com","avatar":"https://gravatar.com/avatar/b2125bfca28c0051a03f69c4e09a215a45dc71418de7b1ffeb63cf779f4f1c85?d=mp&s=160"},"body":"On 08.06.20 08:42, Eric Sunshine wrote:\n> On Wed, May 20, 2020 at 10:28 AM Jonathan Müller\n> <jonathanmueller.dev@gmail.com> wrote:\n>> On 20.05.20 16:22, Eric Sunshine wrote:\n>>> Git tries hard to prevent the same directory from being registered to\n>>> multiple worktrees, however, there is not much it can do to prevent a\n>>> person from shooting himself in the foot by making changes like this\n>>> outside of Git's control. Thus, this seems like a case of \"if it\n>>> hurts, don't do it\".\n>>\n>> I agree and didn't expect git to \"work\".\n> \n> I just posted a patch series[1] which enhances \"git worktree prune\" to\n> detect and deal with multiple worktree entries referencing the same\n> path.\n\nExcellent, thank you!\n\n> \n>>> However, \"git worktree\" could possibly do a better job of helping you\n>>> recover from such a situation. In particular, I think it should be\n>>> reasonably easy to enhance \"git worktree prune\" to detect this\n>>> situation and automatically prune the non-main now-bogus worktree\n>>> entry.\n>>\n>> At the very least, the somewhat confusing error message could be\n>> replaced by a \"you messed up the worktrees, please delete the\n>> corresponding entry in .git/worktree\" or something like that. But\n>> enhancing `git worktree prune` would be better. It was, in fact, the\n>> first command I ran to try and fix the problem.\n>>\n>> As said above, I think git worktree remove could issue a better error if\n>> it detects multiple worktrees with an identical path.\n> \n> Hmm, the message it printed complaining that you tried removing the\n> main worktree seems pretty accurate since that extra worktree entry\n> was indeed pointing at the main worktree. I suppose it would be\n> possible to have \"git worktree remove\" also perform \"corruption\n> detection\" so as to present additional information which might clarify\n> the complaint. Of course, if that is done, then it would make sense to\n> make all \"git worktree\" commands likewise report corruption. However,\n> I haven't convinced myself that we need to go that far. Anyhow, the\n> posted patch series[1] addresses the immediate problem.\n> \n> [1]: https://lore.kernel.org/git/20200608062356.40264-1-sunshine@sunshineco.com/T/\n> \n\nYou're probably right. Fixing git worktree prune to handle the situation \nis sufficient for me, as that was what I tried.\n\nThanks a lot,\nJonathan\n"}]}