{"thread":{"id":"57971","subject":"Git apply fails on case-only rename on case-insensitive filesystem","startedAt":"2022-06-08T13:07:22Z","lastAt":"2022-06-09T04:57:49Z","messageCount":3,"participants":["Tao Klerks","brian m. carlson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"456862","messageId":"CAPMMpojwV+f=z9sgc_GaUOTFBCUVdbrGW8WjatWWmC3WTcsoXw@mail.gmail.com","threadId":"57971","inReplyTo":null,"subject":"Git apply fails on case-only rename on case-insensitive filesystem","fromName":"Tao Klerks","fromEmail":"tao@klerks.biz","sentAt":"2022-06-08T13:07:05Z","receivedAt":"2022-06-08T13:07:22Z","isPatch":false,"sender":{"key":"tao@klerks.biz","avatar":"https://avatars.githubusercontent.com/u/531704?v=4"},"body":"Hi folks,\n\nI just found out that \"git apply\" has a faulty existence check on\ncase-insensitive filesystems (or, at least, windows?).\n\nSimplest repro I could come up with:\n\ngit init renamefun\ncd renamefun\necho \"Test\" > file1\ngit add .\ngit commit -m \"first commit\"\ngit mv file1 File1\ngit commit -m \"second commit\"\ngit checkout master~1\ngit diff master~1..master | git apply\n\n-> error:\nerror: File1: already exists in working directory\n\n(on linux, the same sequence of commands completes correctly)\n\nI was able to work around this for my purposes by avoiding rename\ndetection on the diff, and only passing the \"Add\" (and \"Modify\")\noperations through to the \"apply\", after having separately/manually\nhandled the deletions.\n\nIs this a known issue that someone might be working on, or worth\ndigging into / trying to fix?\n\nThanks,\nTao\n"},{"id":"456902","messageId":"YqEiPf/JR/MEc3C/@camp.crustytoothpaste.net","threadId":"57971","inReplyTo":"CAPMMpojwV+f=z9sgc_GaUOTFBCUVdbrGW8WjatWWmC3WTcsoXw@mail.gmail.com","subject":"Re: Git apply fails on case-only rename on case-insensitive filesystem","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2022-06-08T22:27:09Z","receivedAt":"2022-06-08T22:27:15Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2022-06-08 at 13:07:05, Tao Klerks wrote:\n> Hi folks,\n> \n> I just found out that \"git apply\" has a faulty existence check on\n> case-insensitive filesystems (or, at least, windows?).\n> \n> Simplest repro I could come up with:\n> \n> git init renamefun\n> cd renamefun\n> echo \"Test\" > file1\n> git add .\n> git commit -m \"first commit\"\n> git mv file1 File1\n> git commit -m \"second commit\"\n> git checkout master~1\n> git diff master~1..master | git apply\n> \n> -> error:\n> error: File1: already exists in working directory\n\nYour problem here is that the file does already exist.  To Windows\n\"file1\" and \"File1\" are the same file.  Git wants to create the new\nfile before deleting the old one, but it already exists.\n\n> (on linux, the same sequence of commands completes correctly)\n> \n> I was able to work around this for my purposes by avoiding rename\n> detection on the diff, and only passing the \"Add\" (and \"Modify\")\n> operations through to the \"apply\", after having separately/manually\n> handled the deletions.\n> \n> Is this a known issue that someone might be working on, or worth\n> digging into / trying to fix?\n\nAs I explained to someone else just today, the rules for case-folding on\nWindows differ based on the version of the tool that was used to format\nthe file system and cannot be inspected without reading the raw file\nsystem.  (This is also true of macOS.)  Thus, we cannot know ahead of\ntime whether two files differ only in case.\n\nThe way we could determine this on Unix would be to stat both files and\ncompare device and inode data when we get EEXIST, but I don't think our\nWindows stat emulation supports that.  Having said that, for\ncase-insensitive macOS, I think the rename detection could be fixed here\nusing that technique.  I don't think anyone's working on such a thing at\nthe moment, though.\n-- \nbrian m. carlson (he/him or they/them)\nToronto, Ontario, CA\n"},{"id":"456915","messageId":"CAPMMpoi=4Ke=Zq1ZRR7Y4nbO_1jTBe4to7p9qKtuY-UoFxaXRw@mail.gmail.com","threadId":"57971","inReplyTo":"YqEiPf/JR/MEc3C/@camp.crustytoothpaste.net","subject":"Re: Git apply fails on case-only rename on case-insensitive filesystem","fromName":"Tao Klerks","fromEmail":"tao@klerks.biz","sentAt":"2022-06-09T04:57:31Z","receivedAt":"2022-06-09T04:57:49Z","isPatch":false,"sender":{"key":"tao@klerks.biz","avatar":"https://avatars.githubusercontent.com/u/531704?v=4"},"body":"On Thu, Jun 9, 2022 at 12:27 AM brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n>\n> Git wants to create the new\n> file before deleting the old one, but it already exists.\n>\n\nAh, thanks for that observation, I didn't consider that git might\ngenerally want to do renames in a \"safe\" order.\n\n> The way we could determine this on Unix would be to stat both files and\n> compare device and inode data when we get EEXIST, but I don't think our\n> Windows stat emulation supports that.  Having said that, for\n> case-insensitive macOS, I think the rename detection could be fixed here\n> using that technique.\n\nI have not yet tried to find out whether this \"sameness determination\"\nis possible in windows, but I have one more interesting observation: I\njust realized that \"git checkout\" probably wants to do the same thing\nin the same safe order, and indeed, when I do \"git config\ncore.ignorecase false\" the \"checkout\" command fails with a very\nsimilar error:\n\nerror: The following untracked working tree files would be overwritten\nby checkout:\n        file1\nPlease move or remove them before you switch branches.\nAborting\n\n(in fact, even \"git mv\" fails with a similar error)\n\nThis suggests that there is a strategy based on the \"core.ignorecase\"\nconfig, which might not hinge on determining the \"sameness\" of\ndiffering-only-in-case files, which is applied in other places and\nsimply wasn't considered in \"git apply\" yet.\n\n> I don't think anyone's working on such a thing at\n> the moment, though.\n\nThanks, I'll try to look a little deeper at some point.\n"}]}