# Case insensitive branch names

5 messages from 2015-12-21 to 2015-12-21. Participants: Philip Oakley, Duy Nguyen, Junio C Hamano, Torsten Bögershausen.
Thread: https://gitlist.dev/t/41051

## Philip Oakley, 2015-12-21 10:22

Subject: Case insensitive branch names
Message-ID: <D350A5BC87B74A53B5BE4B10BC658208@PhilipOakley>
URL: https://gitlist.dev/e/D350A5BC87B74A53B5BE4B10BC658208%40PhilipOakley

```
On the Git User's list, Diego J. reported that:

'When I "checkout" a branch using different Upper Case/Lower Case than the
original, the branch doesn't show in "git branch [--list]"' [1]

While case sensitivity for filenames is a common issue on Windows and the
like, I haven't seen any discussion regarding ref name sensitivity - any
pointers to past discussions?

In particular, if I have a branch 'nocase', and ask to checkout 'NoCase',
then git(-for-Windows) will happily say that 'NoCase' has been checked out,
but then it gets confusing.

We are both, not on any branch, and yet not detached. In fact HEAD points to
NoCase (which does not exist with that case setting). The checkout is
actually of 'nocase', and 'git branch' does not mark any branch ref current
(with the *). [see test script: 2].

While this is the way it is, should the 'git checkout' in some way check for
the branch case sensitivity issue?

For example, maybe simply correcting the checkout name to that as recorded
in the File System (but that has lots of code impact because the path and 
name are distinct elements of the branch struct), or maybe a warning could 
be emitted (config?), or even
an err/die.

My gut feeling was that, at least for refs, that something should be done.
My delving into the complexities of the code for 'git checkout' got me to
refs.c ~#L1603 where the requested path is lstat'd. Perhaps this point is a
special case for the mingw_lstat where the true pathname can be compared to
the requested pathname (or at least the refs/heads/name part) to detect this
mis-checkout case?

Thoughts? Is it a rabbit hole others have explored? Is it even worth 
pursuing?

--
Philip

[1] https://groups.google.com/forum/#!topic/git-users/EryCnwKL4_E
[2] Script
git init casetest
cd casetest/
>temp.txt
git add -A & git commit -m'first'
git status
git branch case
git branch
# two branches, * on master.
git status
git checkout Case
# successful checkout, uses branch name as given!
git branch
# note that no branch is marked as current, but neither are we detached 
head..
git status
cat .git/HEAD
# HEAD records the requested name, not the branch that was actually checked 
out!
# User left confused...

=== output
Philip@PhilipOakley MINGW32 /c
$ bash -v ./casetest.sh

git init casetest
Initialized empty Git repository in C:/casetest/.git/
cd casetest/
>temp.txt
git add -A & git commit -m'first'
[master (root-commit) 988c046] first
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 temp.txt
git status
On branch master
nothing to commit, working directory clean
git branch case
git branch
case
* master
# two branches, * on master.
git status
On branch master
nothing to commit, working directory clean
git checkout Case
Switched to branch 'Case'
# successful checkout, uses branch name as given!
git branch
case
master
# note that no branch is marked as current, but neither are we detached 
head..
git status
On branch Case
nothing to commit, working directory clean
cat .git/HEAD
ref: refs/heads/Case
# HEAD records the requested name, not the branch that was actually checked 
out!
# User left confused..
-- 

```

## Duy Nguyen, 2015-12-21 12:21

Subject: Re: [git-for-windows] Case insensitive branch names
Message-ID: <CACsJy8CEYaf9NA4J_2u1cqsikYvtR7nz=FEiwAxsKMLSREDhCg@mail.gmail.com>
URL: https://gitlist.dev/e/CACsJy8CEYaf9NA4J_2u1cqsikYvtR7nz%3DFEiwAxsKMLSREDhCg%40mail.gmail.com
In-Reply-To: <D350A5BC87B74A53B5BE4B10BC658208@PhilipOakley>

```
On Mon, Dec 21, 2015 at 6:01 PM, Philip Oakley <philipoakley@iee.org> wrote:
> On the Git User's list, Diego J. reported that:
>
> 'When I "checkout" a branch using different Upper Case/Lower Case than the
> original, the branch doesn't show in "git branch [--list]"' [1]
>
> While case sensitivity for filenames is a common issue on Windows and the
> like, I haven't seen any discussion regarding ref name sensitivity - any
> pointers to past discussions?

Multiple ref backend [1] should solve this.It's supposed to help
handle a huge number refs. But a side effect from not using file
system for refs is we can handle ref case-sensitivity much easier. And
I believe David had that in mind he chose lmdb (because of Mac, which
shares the same problem with Windows)

[1] http://thread.gmane.org/gmane.comp.version-control.git/281925
-- 
Duy

```

## Junio C Hamano, 2015-12-21 17:37

Subject: Re: [git-for-windows] Case insensitive branch names
Message-ID: <xmqqa8p3hfej.fsf@gitster.mtv.corp.google.com>
URL: https://gitlist.dev/e/xmqqa8p3hfej.fsf%40gitster.mtv.corp.google.com
In-Reply-To: <CACsJy8CEYaf9NA4J_2u1cqsikYvtR7nz=FEiwAxsKMLSREDhCg@mail.gmail.com>

```
Duy Nguyen <pclouds@gmail.com> writes:

> On Mon, Dec 21, 2015 at 6:01 PM, Philip Oakley <philipoakley@iee.org> wrote:
>> On the Git User's list, Diego J. reported that:
>>
>> 'When I "checkout" a branch using different Upper Case/Lower Case than the
>> original, the branch doesn't show in "git branch [--list]"' [1]
>>
>> While case sensitivity for filenames is a common issue on Windows and the
>> like, I haven't seen any discussion regarding ref name sensitivity - any
>> pointers to past discussions?
>
> Multiple ref backend [1] should solve this.

Yup, I had the same reaction.  Instead of restricting the namespace
of branches even on systems that do not have this problem, use a ref
backend that is not limited by the underlying filesystem.  A much
better solution.

In addition to the LMDB backend, it might not be a bad idea to add
another filesystem-based backend that encodes the refnames safely on
case insensitive or case destroying filesystem.  That way, those who
do not want an extra dependency but do want case sensitive refnames
would have an option, and having two non-default backends with quite
different semantics may be a good way to ensure that the API for
refs backend is kept sane.

```

## Torsten Bögershausen, 2015-12-21 18:22

Subject: Re: [git-for-windows] Case insensitive branch names
Message-ID: <5678434B.5040506@web.de>
URL: https://gitlist.dev/e/5678434B.5040506%40web.de
In-Reply-To: <xmqqa8p3hfej.fsf@gitster.mtv.corp.google.com>

```


On 2015-12-21 18.37, Junio C Hamano wrote:
> Duy Nguyen <pclouds@gmail.com> writes:
>
>> On Mon, Dec 21, 2015 at 6:01 PM, Philip Oakley <philipoakley@iee.org> wrote:
>>> On the Git User's list, Diego J. reported that:
>>>
>>> 'When I "checkout" a branch using different Upper Case/Lower Case than the
>>> original, the branch doesn't show in "git branch [--list]"' [1]
>>>
>>> While case sensitivity for filenames is a common issue on Windows and the
>>> like, I haven't seen any discussion regarding ref name sensitivity - any
>>> pointers to past discussions?
>> Multiple ref backend [1] should solve this.
> Yup, I had the same reaction.  Instead of restricting the namespace
> of branches even on systems that do not have this problem, use a ref
> backend that is not limited by the underlying filesystem.  A much
> better solution.
>
> In addition to the LMDB backend, it might not be a bad idea to add
> another filesystem-based backend that encodes the refnames safely on
> case insensitive or case destroying filesystem.  That way, those who
> do not want an extra dependency but do want case sensitive refnames
> would have an option, and having two non-default backends with quite
> different semantics may be a good way to ensure that the API for
> refs backend is kept sane.

This has been reported (probably a couple of times),
one copy I have here was under "Branch Name Case Sensitivity"
around Feb/March 2014.

The lstat() in refs.c can not be fixed, as the underlying OS/FS thinks
that lstat("nocase") == lstat("NoCase") and
open("nocase") == NoCase").

The the "real name" will not be detected, unless somebody does
opendir(), readdir() and closedir().
This is expensive (in terms of execution time), and nobody
has tried to do something.


One cheap solution would be to run "git pack-refs" internally,
either from C-code inside Git itself, or from a script.

```

## Philip Oakley, 2015-12-21 19:58

Subject: Re: [git-for-windows] Case insensitive branch names
Message-ID: <93EE538CE2634272BABFCEB55C6A091E@PhilipOakley>
URL: https://gitlist.dev/e/93EE538CE2634272BABFCEB55C6A091E%40PhilipOakley
In-Reply-To: <5678434B.5040506@web.de>

```
From: "Torsten Bögershausen" <tboegi@web.de>
>
> On 2015-12-21 18.37, Junio C Hamano wrote:
>> Duy Nguyen <pclouds@gmail.com> writes:
>>
>>> On Mon, Dec 21, 2015 at 6:01 PM, Philip Oakley <philipoakley@iee.org> 
>>> wrote:
>>>> On the Git User's list, Diego J. reported that:
>>>>
>>>> 'When I "checkout" a branch using different Upper Case/Lower Case than 
>>>> the
>>>> original, the branch doesn't show in "git branch [--list]"' [1]
>>>>
>>>> While case sensitivity for filenames is a common issue on Windows and 
>>>> the
>>>> like, I haven't seen any discussion regarding ref name sensitivity - 
>>>> any
>>>> pointers to past discussions?
>>> Multiple ref backend [1] should solve this.
>> Yup, I had the same reaction.  Instead of restricting the namespace
>> of branches even on systems that do not have this problem, use a ref
>> backend that is not limited by the underlying filesystem.  A much
>> better solution.

My thought was more that on a case preserving FS we (that FS Git 
implementation) might warn if they have ended up not on a valid branch name. 
It felt wrong that the checkout reported success.

>>
>> In addition to the LMDB backend, it might not be a bad idea to add
>> another filesystem-based backend that encodes the refnames safely on
>> case insensitive or case destroying filesystem.  That way, those who
>> do not want an extra dependency but do want case sensitive refnames
>> would have an option, and having two non-default backends with quite
>> different semantics may be a good way to ensure that the API for
>> refs backend is kept sane.

A suitable case sensitive, case preserving backend would solve it for those 
using it, which will be a help. Though those that don't will still need to 
be careful.

>
> This has been reported (probably a couple of times),
> one copy I have here was under "Branch Name Case Sensitivity"
> around Feb/March 2014.

Found the thread 
http://thread.gmane.org/gmane.comp.version-control.git/242768/focus=242846
though I try to avoid having a 'don't do that' response for some of these 
potentially hazardous cases (though the cost benefit may not justify it;-)

>
> The lstat() in refs.c can not be fixed, as the underlying OS/FS thinks
> that lstat("nocase") == lstat("NoCase") and
> open("nocase") == NoCase").
>
> The the "real name" will not be detected, unless somebody does
> opendir(), readdir() and closedir().
> This is expensive (in terms of execution time), and nobody
> has tried to do something.

That's probably a key bit of info I didn't know - that the true file name 
can't be known without that overhead. Various stackoverflow Q&As [1] show 
that others have also had some difficulties...

>
> One cheap solution would be to run "git pack-refs" internally,
> either from C-code inside Git itself, or from a script.
>

--
Philip
[1] Windows methods of getting true file name (allegedly)
http://stackoverflow.com/questions/4763117/how-can-i-obtain-the-case-sensitive-path-on-windows/4763137#4763137
http://stackoverflow.com/questions/478826/c-sharp-filepath-recasing/479198#479198
http://stackoverflow.com/questions/74451/getting-actual-file-name-with-proper-casing-on-windows

```
