{"thread":{"id":"65630","subject":"Bug: lowercase \"head\" resolves to wrong commit in linked worktrees on case-insensitive filesystems","startedAt":"2026-05-13T08:18:31Z","lastAt":"2026-05-15T09:47:13Z","messageCount":3,"participants":["Alexander Sandström","D. Ben Knoble","Torsten Bögershausen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"543237","messageId":"95BE8E60-1684-4E0A-9E46-E61E81D06CE1@alexandersandstrom.se","threadId":"65630","inReplyTo":null,"subject":"Bug: lowercase \"head\" resolves to wrong commit in linked worktrees on case-insensitive filesystems","fromName":"Alexander Sandström","fromEmail":"mail@alexandersandstrom.se","sentAt":"2026-05-13T08:18:18Z","receivedAt":"2026-05-13T08:18:31Z","isPatch":false,"body":"Hello everyone,\n\nI ran into a bug that took me a while to figure out. \n\nI'm sadly not a good enough C programmer to submit a proper patch,\nbut perhaps this bug report will at least be indexed by search engines\nand help others that might have this issue to understand the cause. \n\nMy guess is that it will happen much more frequently now that \nworktrees are more popular.\n\n**Report**\n\nOn case-insensitive filesystems (macOS APFS/HFS+), `git rev-parse head`\n(lowercase) in a linked worktree resolves to the main worktree's HEAD\nrather than the current worktree's HEAD. This causes commands like\n`git reset --soft head~1` to silently operate on the wrong commit.\n\n**Setup**\n\n```sh\n$ git init main && cd main\n$ git commit --allow-empty -m \"base\"\n$ git commit --allow-empty -m \"main-only\"\n$ git worktree add ../linked HEAD~1\n$ cd ../linked\n$ git commit --allow-empty -m \"linked-only\"\n```\n\n**Expected** `head` and `HEAD` resolve to the same commit in the\nlinked worktree (or `head` is rejected as an unknown revision).\n\n**Actual**\n\n```\n$ cd ../linked\n$ git rev-parse HEAD\n<commit: \"linked-only\">\n$ git rev-parse head\n<commit: \"main-only\">\n```\n\n`HEAD` (uppercase) correctly resolves via the per-worktree ref at\n`.git/worktrees/linked/HEAD`. But lowercase `head` falls through to\ngeneral ref resolution, which opens a file named `head` on disk. On a\ncase-insensitive filesystem, this matches `.git/HEAD`, the main\nworktree's HEAD, instead of the linked worktree's HEAD.\n\nWithout worktrees the bug is latent: `.git/HEAD` is the only HEAD file,\nso the wrong codepath happens to produce the correct result. The bug\nbecomes observable only with linked worktrees, where the main and linked\nworktree HEADs diverge.\n\n**Impact** `git reset --soft head~1` in a linked worktree silently\nresets to the wrong commit, staging unexpected changes. This is\nparticularly confusing because there is no error or warning. The\ncommand appears to succeed.\n\nI realize one argument might simply be \"lower-case head isn't a thing\",\nso feel free to disregard if that is the projects stance.\n\n**Possible fix** During ref resolution, when the input string matches\n`HEAD` case-insensitively but is not exactly `HEAD`, git could either:\n- reject it with an error (matching Linux behavior, where lowercase\n  `head` fails with \"unknown revision\"), or\n- normalize it to `HEAD` and route through the per-worktree codepath.\n\n**Environment**\n- git 2.53.0\n- macOS 15.6 (APFS, case-insensitive)\n\n\nRegards,\nAlexander\n\n"},{"id":"543244","messageId":"CALnO6CAZ+Z_ZzkqXHu45A3cwZTZD4=MEz-vx0PEoD05bJ=0bzw@mail.gmail.com","threadId":"65630","inReplyTo":"95BE8E60-1684-4E0A-9E46-E61E81D06CE1@alexandersandstrom.se","subject":"Re: Bug: lowercase \"head\" resolves to wrong commit in linked worktrees on case-insensitive filesystems","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-05-13T15:42:12Z","receivedAt":"2026-05-13T15:42:24Z","isPatch":false,"body":"On Wed, May 13, 2026 at 4:27 AM Alexander Sandström\n<mail@alexandersandstrom.se> wrote:\n>\n> Hello everyone,\n>\n> I ran into a bug that took me a while to figure out.\n>\n> I'm sadly not a good enough C programmer to submit a proper patch,\n> but perhaps this bug report will at least be indexed by search engines\n> and help others that might have this issue to understand the cause.\n>\n> My guess is that it will happen much more frequently now that\n> worktrees are more popular.\n>\n> **Report**\n>\n> On case-insensitive filesystems (macOS APFS/HFS+), `git rev-parse head`\n> (lowercase) in a linked worktree resolves to the main worktree's HEAD\n> rather than the current worktree's HEAD. This causes commands like\n> `git reset --soft head~1` to silently operate on the wrong commit.\n\nSee also https://lore.kernel.org/git/20240701033145.GB610406@coredump.intra.peff.net/\nand https://lore.kernel.org/git/8BABB6F0-517F-4AA0-9FF9-92AF8C33CD0E@strongestfamilies.com/\n\nIn short, it's a known issue (that I don't think we're going to solve\nin the ref store where refs are just named files). Using reftables\nought to make the papercuts go away.\n\n-- \nD. Ben Knoble\n"},{"id":"543394","messageId":"a77695ea-ae24-45ca-8c14-966e25bb90ba@web.de","threadId":"65630","inReplyTo":"95BE8E60-1684-4E0A-9E46-E61E81D06CE1@alexandersandstrom.se","subject":"Re: Bug: lowercase \"head\" resolves to wrong commit in linked worktrees on case-insensitive filesystems","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2026-05-15T09:47:05Z","receivedAt":"2026-05-15T09:47:13Z","isPatch":false,"body":"\n\nOn 2026-05-13 10:18, Alexander Sandström wrote:\n> Hello everyone,\n> \n> I ran into a bug that took me a while to figure out.\n\nThanks for the report.\n> \n> I'm sadly not a good enough C programmer to submit a proper patch,\n> but perhaps this bug report will at least be indexed by search engines\n> and help others that might have this issue to understand the cause.\n> \n> My guess is that it will happen much more frequently now that\n> worktrees are more popular.\n> \n> **Report**\n> \n> On case-insensitive filesystems (macOS APFS/HFS+), `git rev-parse head`\n> (lowercase) in a linked worktree resolves to the main worktree's HEAD\n> rather than the current worktree's HEAD. This causes commands like\n> `git reset --soft head~1` to silently operate on the wrong commit.\n> \n> **Setup**\n> \n> ```sh\n> $ git init main && cd main\n> $ git commit --allow-empty -m \"base\"\n> $ git commit --allow-empty -m \"main-only\"\n> $ git worktree add ../linked HEAD~1\n> $ cd ../linked\n> $ git commit --allow-empty -m \"linked-only\"\n> ```\n> \n> **Expected** `head` and `HEAD` resolve to the same commit in the\n> linked worktree (or `head` is rejected as an unknown revision).\n\nThis is probably not what you expect.\nhead should not be used at all, since it is not a valid reference.\n\n\nWhen using case-insensitive file systems, head and HEAD may\nbe the same, but that is not a feature.\n\nIn theory, we may be able to refuse head on a case insensitive file system.\nAnd Head, hEad, HEad, you got it.\n\nIn practice nobody has done that yet.\nAnd a quick search for\ngit refs case insensitive\nshows a lot of reports about the limitations that a\ncase insensitive file system gives you.\n\nAnd yes, you can format a partition on MacOs case-insensitive.\nOr live with the limitations that arise.\nOr send a patch. For the documentation.\n\nHTH\n\n\n> \n> **Actual**\n> \n> ```\n> $ cd ../linked\n> $ git rev-parse HEAD\n> <commit: \"linked-only\">\n> $ git rev-parse head\n> <commit: \"main-only\">\n> ```\n> \n> `HEAD` (uppercase) correctly resolves via the per-worktree ref at\n> `.git/worktrees/linked/HEAD`. But lowercase `head` falls through to\n> general ref resolution, which opens a file named `head` on disk. On a\n> case-insensitive filesystem, this matches `.git/HEAD`, the main\n> worktree's HEAD, instead of the linked worktree's HEAD.\n> \n> Without worktrees the bug is latent: `.git/HEAD` is the only HEAD file,\n> so the wrong codepath happens to produce the correct result. The bug\n> becomes observable only with linked worktrees, where the main and linked\n> worktree HEADs diverge.\n> \n> **Impact** `git reset --soft head~1` in a linked worktree silently\n> resets to the wrong commit, staging unexpected changes. This is\n> particularly confusing because there is no error or warning. The\n> command appears to succeed.\n> \n> I realize one argument might simply be \"lower-case head isn't a thing\",\n> so feel free to disregard if that is the projects stance.\n> \n> **Possible fix** During ref resolution, when the input string matches\n> `HEAD` case-insensitively but is not exactly `HEAD`, git could either:\n> - reject it with an error (matching Linux behavior, where lowercase\n>    `head` fails with \"unknown revision\"), or\n> - normalize it to `HEAD` and route through the per-worktree codepath.\n> \n> **Environment**\n> - git 2.53.0\n> - macOS 15.6 (APFS, case-insensitive)\n> \n> \n> Regards,\n> Alexander\n> \n> \n\n"}]}