Git – Branch Name Case Sensitivity Explained

gitgit-branchgithubversion-control

I am a new git user and recently been handed with an out of date git repository to look after.

This is the original state ( output by git show-branch):

! [cr232] CR 232 Release
        * [dev] Style Changes
---------------
        *   [dev] Style Changes
        *   [dev^] SMS 5.4
        *   [dev~2] Logo Change
        *   [dev~3] SMS 5.3
        *   [dev~4] SMS 5.2
        *   [dev~5] SIT R-0.3.3 EDW SMS Layers
        *   [dev~6] SIT Release R 0.3.0
       +*   [cr232] CR 232 Release
       +*   [cr232^] Dashboard Fix
       +*   [cr232~2] Release for system testing

Note that there is a branch called ‘dev’ at this point. Note that highlighted there are several references to dev (i.e. dev, dev^, dev~2 etc).

For my development purpose, I was trying to come up with a branch called ‘DEV’, all capital.

So I went ahead and create new branch (git branch DEV) and now running git show-branch –date-order:

! [DEV] Style Changes
    ! [cr232] CR 232 Release
        * [dev] Style Changes
---------------
        *   [DEV] Style Changes
        *   [DEV^] SMS 5.4
        *   [DEV~2] Logo Change
        *   [DEV~3] SMS 5.3
        *   [DEV~4] SMS 5.2
        *   [DEV~5] SIT R-0.3.3 EDW SMS Layers
        *   [DEV~6] SIT Release R 0.3.0
       +*   [cr232] CR 232 Release
       +*   [cr232^] Dashboard Fix
       +*   [cr232~2] Release for system testing

Note that both dev and DEV are listed as branch. Note also that on the 5th line the references to dev have now changed to DEV (i.e. DEV, DEV^, DEV~2 etc).

What is the 5th line output referring to? I would expect it to remain “dev” instead of being changed to “DEV” as the descriptions next to it refers to the description of old work during “dev” branch.

I am trying to return back to how it was by modifying the DEV branch name to DV (running git branch –m DEV DV) and showing the branch now look like:

! [DV] Style Changes
    ! [cr232] CR 232 Release
        * [dev] Style Changes
---------------
        *   [DV] Style Changes
        *   [DV^] SMS 5.4
        *   [DV~2] Logo Change
        *   [DV~3] SMS 5.3
        *   [DV~4] SMS 5.2
        *   [DV~5] SIT R-0.3.3 EDW SMS Layers
        *   [DV~6] SIT Release R 0.3.0
       +*   [cr232] CR 232 Release
       +*   [cr232^] Dashboard Fix
       +*   [cr232~2] Release for system testing

Note that the branch is now including DV and dev. Note also that the 5th line references to dev have now changed to DV (i.e. DV, DV^, DV~2 etc).

Is there any way to get back to how it was during original state in term of the DV references? Did the git got confused and renamed my historic information with a branch that is similar and only differs by capital case?

Please assist on how I can fix this. Thanks heaps

Best Answer

Answering just the question in the subject line, without addressing anything about git show-branch (like ElpieKay, I never actually use git show-branch; it seems mainly mis-informative):

Git branch names—and tag names, and all other reference names, as Git calls them—were originally intended to be case-sensitive.

This all works perfectly on Linux / Unix machines, where Git's code is case-sensitive to start with. When Git stores branch names in the file system as file names (which it only does sometimes), the file system is also case-sensitive.1

It sometimes fails on Windows and some MacOS systems. Specifically, it fails when Git stores references in individual files, whose names are derived from the reference name, and those file names are case-insensitive (e.g., case-preserving, but fold case during name-matching; or even converting everything to uppercase-only, as in the really old FAT 8.3 format, but we can hope no modern file system does this).

As noted above, Git does not always store reference names as file names. In fact, on initial clone, all the names are in a single file called .git/packed-refs,2 so at this point they are case sensitive. But they become "unpacked" over time,3 and then on some systems they become case-folding.

Because it sometimes fails on some systems, it's generally best to avoid using multiple reference names that differ only in case.


1Of course, on modern Unix/Linux systems, you can now get access to case-preserving-but-case-insensitive file systems, and Windows and MacOS can now be told not to do case-folding for some file systems. (But if you change from the defaults, expect software that is intended for your box to fail, because it will. Things like Photoshop internally try to use files named foo and FOO and expect this to refer to the same file!)

2This packed-references file has been around for quite a while, but not forever, and very early versions of Git may not use it. Internally, Git is acquiring a new "pluggable reference name interface" and future versions of Git might use neither this file, nor individual per-reference files.

3In general, creating or updating a reference causes an unpacked reference file to come into existence. Running git pack-refs --all will replace unpacked references with packed ones, restoring full case-sensitivity. Without --all, git pack-refs only packs already-packed references, which is largely a useless mode of operation (it was intended for a case that is no longer used).

Related Question