{"thread":{"id":"59123","subject":"Race condition on `git checkout -c`","startedAt":"2023-01-19T21:20:38Z","lastAt":"2023-01-20T09:01:35Z","messageCount":3,"participants":["Arthur Milchior","Chris Torek"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"470734","messageId":"CAEcbrFdE6X6=ppBWmFZrm0Z2RqGqFatjNHdZbGb_RMteCk6P6g@mail.gmail.com","threadId":"59123","inReplyTo":null,"subject":"Race condition on `git checkout -c`","fromName":"Arthur Milchior","fromEmail":"arthur.milchior@gmail.com","sentAt":"2023-01-19T21:13:35Z","receivedAt":"2023-01-19T21:20:38Z","isPatch":false,"sender":{"key":"arthur.milchior@gmail.com","avatar":null},"body":"Thank you for filling out a Git bug report!\nPlease answer the following questions to help us understand your issue.\n\nWhat did you do before the bug happened? (Steps to reproduce your issue)\nI was working on code as usual. I should note that the repo is big, so\nit’s not unusual for some git operations to take half a minute.\n\nHere is a simpler reproduction that worked on my machine.\n\n```\nmkdir g\ncd g\ngit init\ngit touch a\ngit add a\ngit commit -am \"a\"\ngit checkout -b b\n```\n\nWhile the last command is being run, in a different terminal, run `git\ncheckout -b B`\n\nI realized that I can do it manually, by just using cmd-tab, then enter.\n\nFinally, type `git branch`\n\n\nWhat did you expect to happen? (Expected behavior)\n\nI expect either:\n* to see an error message stating that `b` already exists\n* to see `b` and `B` in the list of branch.\n\nIn any case, when both branches exists, which will be the case on\nsystem which were started with this \"bug\", I expect to see both\nbranches listed.\n\nWhat happened instead? (Actual behavior)\n\nI was able to successively create both branches.\nThe branch `b` is not listed. If I check it out, then `git branch`\ndoes not list a single branch as the current branch.\n\nWhat's different between what you expected and what actually happened?\n\nI expect that `git branch` always list me on a branch, and let me know\nof all existing branch.\n\nAnything else you want to add:\n\nFirst: I can’t reproduce with `git branch b` and `git branch B`, so I\nguess either `branch` is faster than `checkout -c`, or something else\nis done right there.\n\nI know that this race condition seems very contrived. In real life,\nthe names were `bookmarkShome` and `bookmarksHome`. Obviously, both\nwere supposed to be `bookmarksHome`, in camlCase. The first one was a\ntypo. But that was the one git show, which was confusing.\nHowever, even if the repo is big and checking out a branch can easily\ntake 30 seconds, I’m still not sure when I’d have two terminals\ncreating branchs at the same time.\n\nPlease review the rest of the bug report below.\nYou can delete any lines you don't wish to share.\n\n\n[System Info]\ngit version:\ngit version 2.39.0.246.g2a6d74b583-goog\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nfeature: fsmonitor--daemon\nuname: Darwin 22.2.0 Darwin Kernel Version 22.2.0: Fri Nov 11 02:03:51\nPST 2022; root:xnu-8792.61.2~4/RELEASE_ARM64_T6000 x86_64\ncompiler info: clang: 14.0.0 (clang-1400.0.29.202)\nlibc info: no libc information available\n$SHELL (typically, interactive shell): /bin/bash\n\n\n[Enabled Hooks]\n"},{"id":"470749","messageId":"CAPx1GvcBDcZ1K_YJKm3+fUBNYQWKE2FBz-qS6JrV2TJCTc5k1w@mail.gmail.com","threadId":"59123","inReplyTo":"CAEcbrFdE6X6=ppBWmFZrm0Z2RqGqFatjNHdZbGb_RMteCk6P6g@mail.gmail.com","subject":"Re: Race condition on `git checkout -c`","fromName":"Chris Torek","fromEmail":"chris.torek@gmail.com","sentAt":"2023-01-19T22:55:54Z","receivedAt":"2023-01-19T23:04:43Z","isPatch":false,"sender":{"key":"chris.torek@gmail.com","avatar":"https://avatars.githubusercontent.com/u/16826774?v=4"},"body":"(Top note: you mean `git checkout -b` or `git switch -c`, not `git\ncheckout -c`.)\n\nOn Thu, Jan 19, 2023 at 1:24 PM Arthur Milchior\n<arthur.milchior@gmail.com> wrote:\n>\n> I expect either:\n> * to see an error message stating that `b` already exists\n> * to see `b` and `B` in the list of branch.\n\n[snip]\n\n> uname: Darwin 22.2.0 Darwin Kernel Version 22.2.0: Fri Nov 11 02:03:51\n\nDarwin (macOS) is your problem here.  The same problem\noccurs on Windows, but not on Linux, by default.\n\nTechnically the problem is in the file system itself, combined with\nthe ways (plural) that Git stores branch names.\n\nAs far as Git itself is concerned, branch names are *always* case\nsensitive, so branches named `b` and `B` are different.  But Git\nstores branch names in two different formats, at the moment:\n\n * Some are kept in a plain-text file `.git/packed-refs`.\n * Some are stored as directory-and-file-names in `.git/refs/`.\n\nIf the OS's file system is case sensitive, as most standard Linux\nfile systems are, there's no problem with the latter. But if the OS's\nfile system is case-INsensitive, as the default file systems on\nWindows and MacOS are, this becomes a problem: the attempt\nto create both `refs/heads/b` and a different file, `refs/head/B`,\nfails, with one of the two names \"winning\" and the other attempt\nto create a new name simply re-using the existing name.\n\nIf you create a case-sensitive disk volume on your Mac, which\ncan be a simple click-to-mount virtual drive within your regular\ncase-insensitive file system, you can happily use Git without this\ncomplication. Note that the same complication applies to file\nnames: Linux users can create two different, separate files\nnamed `README.TXT` and `ReadMe.txt` in a GIt project, and\nif you use the default case-insensitive macOS file system, you\nwon't be able to check out both files.  Using your case sensitive\nvolume will allow you to work with the Linux group.\n\nIf and when a future version of Git starts using reftables instead\nof the file system to store branch and tag names, this particular\nissue will go away, but until then, I recommend keeping a case\nsensitive volume handy on your mac, and more generally,\navoiding mixing upper and lower case branch and/or file names\n(at all, ever) whenever possible.  This avoids a lot of problems,\nthough nothing can get you past the Windows `aux.h` problem. :-)\n\nChris\n"},{"id":"470774","messageId":"CAEcbrFdfZsRAxeMj+z_VBxHbtgBDKHC51rDz0duM3a0TFzqB-A@mail.gmail.com","threadId":"59123","inReplyTo":"CAPx1GvcBDcZ1K_YJKm3+fUBNYQWKE2FBz-qS6JrV2TJCTc5k1w@mail.gmail.com","subject":"Re: Race condition on `git checkout -c`","fromName":"Arthur Milchior","fromEmail":"arthur.milchior@gmail.com","sentAt":"2023-01-20T09:01:21Z","receivedAt":"2023-01-20T09:01:35Z","isPatch":false,"sender":{"key":"arthur.milchior@gmail.com","avatar":null},"body":"Thank you very much for the explanation. I’m ever so happy not to be\nworking at the file system level nor on cross platform app.\nAlas, it’s a computer configured by work, so not only do I have no\ncontrol over the disk configuration, but I’m not even allowed to plus\nexternal storage. So I guess I’ll just remain with the case\nalmost-insensitive branch. Not like I expect this to occur again in\nthe future.\n\nGood luck with whatever next change git plans.\n\nRegards,\nArthur\n\nOn Thu, Jan 19, 2023 at 11:56 PM Chris Torek <chris.torek@gmail.com> wrote:\n>\n> (Top note: you mean `git checkout -b` or `git switch -c`, not `git\n> checkout -c`.)\n>\n> On Thu, Jan 19, 2023 at 1:24 PM Arthur Milchior\n> <arthur.milchior@gmail.com> wrote:\n> >\n> > I expect either:\n> > * to see an error message stating that `b` already exists\n> > * to see `b` and `B` in the list of branch.\n>\n> [snip]\n>\n> > uname: Darwin 22.2.0 Darwin Kernel Version 22.2.0: Fri Nov 11 02:03:51\n>\n> Darwin (macOS) is your problem here.  The same problem\n> occurs on Windows, but not on Linux, by default.\n>\n> Technically the problem is in the file system itself, combined with\n> the ways (plural) that Git stores branch names.\n>\n> As far as Git itself is concerned, branch names are *always* case\n> sensitive, so branches named `b` and `B` are different.  But Git\n> stores branch names in two different formats, at the moment:\n>\n>  * Some are kept in a plain-text file `.git/packed-refs`.\n>  * Some are stored as directory-and-file-names in `.git/refs/`.\n>\n> If the OS's file system is case sensitive, as most standard Linux\n> file systems are, there's no problem with the latter. But if the OS's\n> file system is case-INsensitive, as the default file systems on\n> Windows and MacOS are, this becomes a problem: the attempt\n> to create both `refs/heads/b` and a different file, `refs/head/B`,\n> fails, with one of the two names \"winning\" and the other attempt\n> to create a new name simply re-using the existing name.\n>\n> If you create a case-sensitive disk volume on your Mac, which\n> can be a simple click-to-mount virtual drive within your regular\n> case-insensitive file system, you can happily use Git without this\n> complication. Note that the same complication applies to file\n> names: Linux users can create two different, separate files\n> named `README.TXT` and `ReadMe.txt` in a GIt project, and\n> if you use the default case-insensitive macOS file system, you\n> won't be able to check out both files.  Using your case sensitive\n> volume will allow you to work with the Linux group.\n>\n> If and when a future version of Git starts using reftables instead\n> of the file system to store branch and tag names, this particular\n> issue will go away, but until then, I recommend keeping a case\n> sensitive volume handy on your mac, and more generally,\n> avoiding mixing upper and lower case branch and/or file names\n> (at all, ever) whenever possible.  This avoids a lot of problems,\n> though nothing can get you past the Windows `aux.h` problem. :-)\n>\n> Chris\n"}]}