Subject: Re: Should "head" also work for "HEAD" on case-insensitive FS?

From: Ævar Arnfjörð Bjarmason <[email-masked]>
Date: Tue, 04 Jul 2017 10:24:30 +0200

On Tue, Jul 04 2017, Konstantin Khomoutov jotted:

> On Tue, Jul 04, 2017 at 12:00:49AM +0200, Ævar Arnfjörð Bjarmason wrote:
>
>> I don't have a OSX box, but was helping a co-worker over Jabber the
>> other day, and he pasted something like:
>>
>>     $ git merge-base github/master head
>>
>> Which didn't work for me, and I thought he had a local "head" branch
>> until realizing that of course we were just resolving HEAD on the FS.
>>
>> Has this come up before? I think it makes sense to warn/error about
>> these magic /HEAD/ revisions if they're not upper-case.
>>
>> This is likely unintentional and purely some emergent effect of how it's
>> implemented, and leads to unportable git invocations.
>
> JFTR this is one common case of confusion on Windows as well.
> To the point that I saw people purposedly using "head" on StackOverflow
> questions.  That is, they appear to think (for some reason) that
> branches in Git have case-insensitive names and prefer to spell "head"
> since it (supposedly) easier to type.
>
> I don't know what to do about it.
> Ideally we'd just have a way to perform a final check on the file into
> which a ref name was resolved to see its "real" name but I don't know
> whether all popular filesystems are case preserving (HFS+ and NTFS are,
> IIRC) and even if they are, whether the appropriate platform-specific
> APIs exists to perform such a check.

I think there's no easy way do this in the general case with the current
ref backend, because we rely on the FS to store the refs.

But I'm thinking of the more specific case where you specify
{HEAD,FETCH_HEAD,ORIG_HEAD,MERGE_HEAD,CHERRY_PICK_HEAD} as non-upper
case, and we resolve it from .git/$NAME.

So the detection would not be checking whether the file on-disk has the
same casing, but knowing that if we resolve anything from .git/$NAME
then the string provided on the command-line must be upper-case.

Although there is this:

    $ git rev-parse HEAD
    051ee1e7dd2c7b8bdc20f237eea3c7d5b1314280
    $ git rev-parse WHATEVER
    WHATEVER
    fatal: ambiguous argument 'WHATEVER': unknown revision or path not in the working tree.
    $ cp .git/{HEAD,WHATEVER}
    $ git rev-parse WHATEVER
    051ee1e7dd2c7b8bdc20f237eea3c7d5b1314280

I.e. we allow any arbitrary ref sitting in .git/, but presumably we
could just record the original string the user provided so that this
dies on OSX/Windows too:

    $ cp .git/{HEAD,Whatever}
    $ git rev-parse wHATEVER
    wHATEVER
    fatal: ambiguous argument 'wHATEVER': unknown revision or path not in the working tree.

But this may be a much deeper rabbit hole than I initially thought, I
was fishing to see if someone knew of a place in the code or WIP patch
that dealt with these special refs, but between the low-level machinery
& sha1_name.c (and others) there may be no easy one place to do this...