{"thread":{"id":"61698","subject":"Confusing treatment of \"head\" in worktree on case-insensitive FS","startedAt":"2024-06-29T14:39:41Z","lastAt":"2024-07-01T18:28:26Z","messageCount":4,"participants":["Julia Evans","Jeff King","Phillip Wood"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"497836","messageId":"A72DCB1B-8D81-4DD7-93AD-BF37E88E9D63@jvns.ca","threadId":"61698","inReplyTo":null,"subject":"Confusing treatment of \"head\" in worktree on case-insensitive FS","fromName":"Julia Evans","fromEmail":"julia@jvns.ca","sentAt":"2024-06-29T14:39:29Z","receivedAt":"2024-06-29T14:39:41Z","isPatch":false,"sender":{"key":"julia@jvns.ca","avatar":"https://avatars.githubusercontent.com/u/817739?v=4"},"body":"Hello,\n\nWhen I run `git rev-parse head` inside a worktree on a case insensitive filesystem,\nthe result is different from `git rev-parse HEAD`.\n\nSteps to reproduce, on a case insensitive filesystem:\n\n$ git init\n$ git commit --allow-empty -m'test'\n$ git worktree add /tmp/myworktree\n$ cd /tmp/myworktree\n$ git commit --allow-empty -m'test'\n$ git rev-parse head\nadf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n$ git rev-parse hEAd\nadf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n$ git rev-parse HEAD\nfbb28196d08d74aa61f65e5cee3cb11cc24c338a\n\nThis also happens when using any other command involving \"head\", like\n`git show head`, `git diff head`, etc.\n\nWhat did you expect to happen?\n\nIf `git rev-parse head` returns anything at all (of course on a case-sensitive\nfilesystem it just returns an error), I'd expect it to be the same as `git rev-parse HEAD`.\n\nI accidentally got into the happen of using `git diff head` instead of `git\ndiff HEAD` on a case insensitive filesystem and was thrown off by this\nwhen I ran into it.\n\nWhat happened instead?\n\nWhen in a worktree, `head` appears to get resolved to the value of `HEAD`\nin `git rev-parse --git-common-dir`, while `HEAD` gets resolved to the\nvalue of `HEAD` in the worktree.\n\n[System Info]\ngit version:\ngit version 2.39.2 (Apple Git-143)\ncpu: arm64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nfeature: fsmonitor--daemon\nuname: Darwin 23.4.0 Darwin Kernel Version 23.4.0: Fri Mar 15 00:12:41 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_T8103 arm64\ncompiler info: clang: 14.0.3 (clang-1403.0.22.14.1)\nlibc info: no libc information available\n$SHELL (typically, interactive shell): /usr/bin/fish\n\n"},{"id":"497871","messageId":"20240701033145.GB610406@coredump.intra.peff.net","threadId":"61698","inReplyTo":"A72DCB1B-8D81-4DD7-93AD-BF37E88E9D63@jvns.ca","subject":"Re: Confusing treatment of \"head\" in worktree on case-insensitive FS","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2024-07-01T03:31:45Z","receivedAt":"2024-07-01T03:31:47Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jun 29, 2024 at 10:39:29AM -0400, Julia Evans wrote:\n\n> When I run `git rev-parse head` inside a worktree on a case insensitive filesystem,\n> the result is different from `git rev-parse HEAD`.\n\nThis is a known issue in general. It can get even more confusing when\nyou pack refs, since we do case-sensitive matches within the packed-refs\nfile, and then the filesystem gives us case-insensitive matching for\nloose refs.\n\nI don't know of a good short-term solution, but the long-term one is for\nus to eventually move to ref storage that doesn't rely on the filesystem\n(like the recent reftables work).\n\nWith the current tip of 'master', you can do:\n\n  git init --ref-format=reftable\n\nI think initial support there shipped in v2.45.0, and I think things\nshould mostly work. But I won't be too surprised if you find a corner\ncase or rough edge somewhere. Bug reports welcome. ;)\n\n> Steps to reproduce, on a case insensitive filesystem:\n> \n> $ git init\n> $ git commit --allow-empty -m'test'\n> $ git worktree add /tmp/myworktree\n> $ cd /tmp/myworktree\n> $ git commit --allow-empty -m'test'\n> $ git rev-parse head\n> adf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n> $ git rev-parse hEAd\n> adf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n> $ git rev-parse HEAD\n> fbb28196d08d74aa61f65e5cee3cb11cc24c338a\n\nI admit this is an unexpected case, as I'd expect both on-disk files to\nbe spelled \"HEAD\". I didn't dig into the details, though, so it's\npossible there's something we could be doing differently or better. But\nI do think it's mostly the tip of the iceberg for case-insensitivity\nissues with refs.\n\n-Peff\n"},{"id":"497884","messageId":"bfa964a5-c366-47c7-a325-44fa4687432a@gmail.com","threadId":"61698","inReplyTo":"20240701033145.GB610406@coredump.intra.peff.net","subject":"Re: Confusing treatment of \"head\" in worktree on case-insensitive FS","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2024-07-01T13:17:21Z","receivedAt":"2024-07-01T13:17:24Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 01/07/2024 04:31, Jeff King wrote:\n> On Sat, Jun 29, 2024 at 10:39:29AM -0400, Julia Evans wrote:\n>> $ git init\n>> $ git commit --allow-empty -m'test'\n>> $ git worktree add /tmp/myworktree\n>> $ cd /tmp/myworktree\n>> $ git commit --allow-empty -m'test'\n>> $ git rev-parse head\n>> adf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n>> $ git rev-parse hEAd\n>> adf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n>> $ git rev-parse HEAD\n>> fbb28196d08d74aa61f65e5cee3cb11cc24c338a\n> \n> I admit this is an unexpected case, as I'd expect both on-disk files to\n> be spelled \"HEAD\". I didn't dig into the details, though, so it's\n> possible there's something we could be doing differently or better. But\n> I do think it's mostly the tip of the iceberg for case-insensitivity\n> issues with refs.\n\nI think what's happening is that the checks in is_current_worktree_ref() \nare case sensitive so \"head\" is not treated as local to the current \nworktree and ends up being resolved in the main worktree. I guess we \ncould make those checks case-insensitive but as you say it'd only be \ndealing the tip of the iceberg.\n\nOn a related note do MacOs and Windows do any unicode normalization when \nlooking up filenames? If so then that's probably another can of worms \nfor filesystem based refs.\n\nBest Wishes\n\nPhillip\n"},{"id":"497911","messageId":"20240701182824.GE3199@coredump.intra.peff.net","threadId":"61698","inReplyTo":"bfa964a5-c366-47c7-a325-44fa4687432a@gmail.com","subject":"Re: Confusing treatment of \"head\" in worktree on case-insensitive FS","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2024-07-01T18:28:24Z","receivedAt":"2024-07-01T18:28:26Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Jul 01, 2024 at 02:17:21PM +0100, Phillip Wood wrote:\n\n> On 01/07/2024 04:31, Jeff King wrote:\n> > On Sat, Jun 29, 2024 at 10:39:29AM -0400, Julia Evans wrote:\n> > > $ git init\n> > > $ git commit --allow-empty -m'test'\n> > > $ git worktree add /tmp/myworktree\n> > > $ cd /tmp/myworktree\n> > > $ git commit --allow-empty -m'test'\n> > > $ git rev-parse head\n> > > adf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n> > > $ git rev-parse hEAd\n> > > adf59ca8da0ee5c4eb455f87efecc6c79eaf030f\n> > > $ git rev-parse HEAD\n> > > fbb28196d08d74aa61f65e5cee3cb11cc24c338a\n> > \n> > I admit this is an unexpected case, as I'd expect both on-disk files to\n> > be spelled \"HEAD\". I didn't dig into the details, though, so it's\n> > possible there's something we could be doing differently or better. But\n> > I do think it's mostly the tip of the iceberg for case-insensitivity\n> > issues with refs.\n> \n> I think what's happening is that the checks in is_current_worktree_ref() are\n> case sensitive so \"head\" is not treated as local to the current worktree and\n> ends up being resolved in the main worktree. I guess we could make those\n> checks case-insensitive but as you say it'd only be dealing the tip of the\n> iceberg.\n\nAh, right, that makes perfect sense (well, why it happens that way, not\nfrom the perspective of a user :) ).\n\nSo one thing we could do (but I am not sure is wise) is for those checks\nto become case-insensitive for a case-insensitive ref store. And then at\nleast if you use consistent case when writing refs, you should get\nreasonable behavior (whereas if you make \"hEaD\" and \"HEAD\" yourself, all\nbets are off). But I'd worry about opening up even more weird corner\ncases. And you can already avoid this problem (I think) by using the\ncase-sensitive spelling \"HEAD\" on lookups.\n\n> On a related note do MacOs and Windows do any unicode normalization when\n> looking up filenames? If so then that's probably another can of worms for\n> filesystem based refs.\n\nAt least macOS does. That's why we have all of the precompose-unicode\ncode, which tries to normalize arguments to match what the OS will do.\nIn theory we could do something like that for case normalizing, but I\ndon't think it's nearly as simple.\n\nFor a read, normalizing \"head\" to \"HEAD\" on a case-insensitive\nfilesystem is OK, since the OS will return the same set for each group.\n\nBut writing is harder. The unicode normalization in the filesystem is\nnot \"preserving\". So if I pass in a decomposed string, the filesystem is\ngoing to silently convert it to the precomposed form anyway. But case is\nusually preserving. So if I write \"hEaD\", I'll get that in the\nfilesystem, and not actually \"HEAD\". I dunno. Maybe it would be OK if we\ndid that only for root refs which would otherwise be forbidden. But it\nreally feels like opening up a can of complexity worms and corner cases.\n\n-Peff\n"}]}