# Bug: lowercase "head" resolves to wrong commit in linked worktrees on case-insensitive filesystems

3 messages from 2026-05-13 to 2026-05-15. Participants: Alexander Sandström, D. Ben Knoble, Torsten Bögershausen.
Thread: https://gitlist.dev/t/65630

## Alexander Sandström, 2026-05-13 08:18

Subject: Bug: lowercase "head" resolves to wrong commit in linked worktrees on case-insensitive filesystems
Message-ID: <95BE8E60-1684-4E0A-9E46-E61E81D06CE1@alexandersandstrom.se>

```
Hello everyone,

I ran into a bug that took me a while to figure out. 

I'm sadly not a good enough C programmer to submit a proper patch,
but perhaps this bug report will at least be indexed by search engines
and help others that might have this issue to understand the cause. 

My guess is that it will happen much more frequently now that 
worktrees are more popular.

**Report**

On case-insensitive filesystems (macOS APFS/HFS+), `git rev-parse head`
(lowercase) in a linked worktree resolves to the main worktree's HEAD
rather than the current worktree's HEAD. This causes commands like
`git reset --soft head~1` to silently operate on the wrong commit.

**Setup**

ˋˋˋsh
$ git init main && cd main
$ git commit --allow-empty -m "base"
$ git commit --allow-empty -m "main-only"
$ git worktree add ../linked HEAD~1
$ cd ../linked
$ git commit --allow-empty -m "linked-only"
ˋˋˋ

**Expected** `head` and `HEAD` resolve to the same commit in the
linked worktree (or `head` is rejected as an unknown revision).

**Actual**

ˋˋˋ
$ cd ../linked
$ git rev-parse HEAD
<commit: "linked-only">
$ git rev-parse head
<commit: "main-only">
ˋˋˋ

`HEAD` (uppercase) correctly resolves via the per-worktree ref at
`.git/worktrees/linked/HEAD`. But lowercase `head` falls through to
general ref resolution, which opens a file named `head` on disk. On a
case-insensitive filesystem, this matches `.git/HEAD`, the main
worktree's HEAD, instead of the linked worktree's HEAD.

Without worktrees the bug is latent: `.git/HEAD` is the only HEAD file,
so the wrong codepath happens to produce the correct result. The bug
becomes observable only with linked worktrees, where the main and linked
worktree HEADs diverge.

**Impact** `git reset --soft head~1` in a linked worktree silently
resets to the wrong commit, staging unexpected changes. This is
particularly confusing because there is no error or warning. The
command appears to succeed.

I realize one argument might simply be "lower-case head isn't a thing",
so feel free to disregard if that is the projects stance.

**Possible fix** During ref resolution, when the input string matches
`HEAD` case-insensitively but is not exactly `HEAD`, git could either:
- reject it with an error (matching Linux behavior, where lowercase
  `head` fails with "unknown revision"), or
- normalize it to `HEAD` and route through the per-worktree codepath.

**Environment**
- git 2.53.0
- macOS 15.6 (APFS, case-insensitive)


Regards,
Alexander


```

## D. Ben Knoble, 2026-05-13 15:42

Subject: Re: Bug: lowercase "head" resolves to wrong commit in linked worktrees on case-insensitive filesystems
Message-ID: <CALnO6CAZ+Z_ZzkqXHu45A3cwZTZD4=MEz-vx0PEoD05bJ=0bzw@mail.gmail.com>
In-Reply-To: <95BE8E60-1684-4E0A-9E46-E61E81D06CE1@alexandersandstrom.se>

```
On Wed, May 13, 2026 at 4:27 AM Alexander Sandström
<mail@alexandersandstrom.se> wrote:
>
> Hello everyone,
>
> I ran into a bug that took me a while to figure out.
>
> I'm sadly not a good enough C programmer to submit a proper patch,
> but perhaps this bug report will at least be indexed by search engines
> and help others that might have this issue to understand the cause.
>
> My guess is that it will happen much more frequently now that
> worktrees are more popular.
>
> **Report**
>
> On case-insensitive filesystems (macOS APFS/HFS+), `git rev-parse head`
> (lowercase) in a linked worktree resolves to the main worktree's HEAD
> rather than the current worktree's HEAD. This causes commands like
> `git reset --soft head~1` to silently operate on the wrong commit.

See also https://lore.kernel.org/git/20240701033145.GB610406@coredump.intra.peff.net/
and https://lore.kernel.org/git/8BABB6F0-517F-4AA0-9FF9-92AF8C33CD0E@strongestfamilies.com/

In short, it's a known issue (that I don't think we're going to solve
in the ref store where refs are just named files). Using reftables
ought to make the papercuts go away.

-- 
D. Ben Knoble

```

## Torsten Bögershausen, 2026-05-15 09:47

Subject: Re: Bug: lowercase "head" resolves to wrong commit in linked worktrees on case-insensitive filesystems
Message-ID: <a77695ea-ae24-45ca-8c14-966e25bb90ba@web.de>
In-Reply-To: <95BE8E60-1684-4E0A-9E46-E61E81D06CE1@alexandersandstrom.se>

```


On 2026-05-13 10:18, Alexander Sandström wrote:
> Hello everyone,
> 
> I ran into a bug that took me a while to figure out.

Thanks for the report.
> 
> I'm sadly not a good enough C programmer to submit a proper patch,
> but perhaps this bug report will at least be indexed by search engines
> and help others that might have this issue to understand the cause.
> 
> My guess is that it will happen much more frequently now that
> worktrees are more popular.
> 
> **Report**
> 
> On case-insensitive filesystems (macOS APFS/HFS+), `git rev-parse head`
> (lowercase) in a linked worktree resolves to the main worktree's HEAD
> rather than the current worktree's HEAD. This causes commands like
> `git reset --soft head~1` to silently operate on the wrong commit.
> 
> **Setup**
> 
> ˋˋˋsh
> $ git init main && cd main
> $ git commit --allow-empty -m "base"
> $ git commit --allow-empty -m "main-only"
> $ git worktree add ../linked HEAD~1
> $ cd ../linked
> $ git commit --allow-empty -m "linked-only"
> ˋˋˋ
> 
> **Expected** `head` and `HEAD` resolve to the same commit in the
> linked worktree (or `head` is rejected as an unknown revision).

This is probably not what you expect.
head should not be used at all, since it is not a valid reference.


When using case-insensitive file systems, head and HEAD may
be the same, but that is not a feature.

In theory, we may be able to refuse head on a case insensitive file system.
And Head, hEad, HEad, you got it.

In practice nobody has done that yet.
And a quick search for
git refs case insensitive
shows a lot of reports about the limitations that a
case insensitive file system gives you.

And yes, you can format a partition on MacOs case-insensitive.
Or live with the limitations that arise.
Or send a patch. For the documentation.

HTH


> 
> **Actual**
> 
> ˋˋˋ
> $ cd ../linked
> $ git rev-parse HEAD
> <commit: "linked-only">
> $ git rev-parse head
> <commit: "main-only">
> ˋˋˋ
> 
> `HEAD` (uppercase) correctly resolves via the per-worktree ref at
> `.git/worktrees/linked/HEAD`. But lowercase `head` falls through to
> general ref resolution, which opens a file named `head` on disk. On a
> case-insensitive filesystem, this matches `.git/HEAD`, the main
> worktree's HEAD, instead of the linked worktree's HEAD.
> 
> Without worktrees the bug is latent: `.git/HEAD` is the only HEAD file,
> so the wrong codepath happens to produce the correct result. The bug
> becomes observable only with linked worktrees, where the main and linked
> worktree HEADs diverge.
> 
> **Impact** `git reset --soft head~1` in a linked worktree silently
> resets to the wrong commit, staging unexpected changes. This is
> particularly confusing because there is no error or warning. The
> command appears to succeed.
> 
> I realize one argument might simply be "lower-case head isn't a thing",
> so feel free to disregard if that is the projects stance.
> 
> **Possible fix** During ref resolution, when the input string matches
> `HEAD` case-insensitively but is not exactly `HEAD`, git could either:
> - reject it with an error (matching Linux behavior, where lowercase
>    `head` fails with "unknown revision"), or
> - normalize it to `HEAD` and route through the per-worktree codepath.
> 
> **Environment**
> - git 2.53.0
> - macOS 15.6 (APFS, case-insensitive)
> 
> 
> Regards,
> Alexander
> 
> 


```
