Nahum
Nahum

Reputation: 7197

git different folder casing in branches and ls-remote

something is wrong in my git repository. I get different case for the branch folder name. git branch -r gives me US/blabla git ls-remote gives me us/blabla thats true for all the remote us/

why is this happening, how can I make both command return the lowercase version?

command:

git branch -r | grep US/blabla

returns:

origin/US/99867_blabla

command:

git ls-remote origin US/99867_blabla

returns nothing

command:

git ls-remote origin us/99867_blabla

returns

`12312362b8f4e6dc0e1c34880f96d525d2d19d30        refs/heads/us/blabla`

command:

git branch

returns

* master

Upvotes: 1

Views: 1208

Answers (2)

torek
torek

Reputation: 487865

Git itself thinks that all uppercase letters are always distinct from all lowercase letters. Hence a file or branch named NAME is always different from one named name. A file named INCLUDE/IP.H is different from one named include/ip.h. Note that these two names have a slash in them. There is no folder named INCLUDE or include here, there are just files named INCLUDE/IP.H and include/ip.h. The same holds for branch names: FEATURE/NAME and feature/name do not have any folders; they're just two different branch names.

At various times, however, Git is forced, by your computer, to place these file or branch names into your computer's file and/or folder names.1 If the file system provided by your computer requires that slashes imply folders, Git will create a folder for you at this time, so as to hold the full name. If the file system provided by your computer conflates uppercase and lowercase, so that NAME and name are considered "the same file" and INCLUDE and include are "the same folder", the various files and folders that Git is trying to create and use here will get mixed together.

What Git does with these problematic cases is to make you, the user, miserable. The people who write and support Git code have put in various attempts to make the experience less horrible, but none of them have really solved the problem, because there is no single satisfactory solution. Your best bet is to avoid this situation entirely, if you can. If not, you must live with the weirdness until you manage to rename everything to get out of this bad situation.

Make sure that you are consistent in when or whether you use uppercase or lowercase. One relatively easy way to deal with all of this is to obtain a Linux system (or a Linux VM with a private file system), or create a case-sensitive file system on your computer, so that when Git goes to create a folder or file named NAME and another different folder or file named name, it winds up with two different folders / files. Using Git on this system will work fine and will give you the opportunity to get rid of files and/or branches that use the "wrong" case.

Remember that in Git, history is commits. Commits contain files (never any folders, just files, even if their names have slashes in them) and those files have names, and uppercase letters are always different from lowercase ones here. Old commits cannot be changed so if you have files that differ only in case in these old commits, they will continue to be that way in the old commits. Just make new commits in which the problem no longer exists, and avoid using the old commits on computers / file-systems where they are a problem. If necessary, you can even "rewrite history" by copying the old problematic commits to new-and-improved ones that avoid the problem, then making your branch and tag and other names remember only the new commits. Remember that any Git repository that has the old commits will re-introduce them to your fixed-up Git repository, so if you do rewrite history, everyone with a clone of the bad history must get rid of the bad history somehow—typically by abandoning the old clone entirely.

Fortunately, in your case, the issue is just branch names. Unfortunately, branch names also get copied by cloning. Fortunately, they're merely copied to remote-tracking names. So once you've fixed up the original source of the misery, you can, on each clone, just delete all remote-tracking names and then re-obtain them all, perhaps using:

git remote remove origin

followed by:

git remote add origin <url>
git fetch origin

with the appropriate URL (you can save it before doing the git remote remove operation).


1Since Git is eventually going to put information about a branch named feature/name into a folder named feature containing a file named name, Git won't let you create a branch named feature if you have a branch named feature/name. That accommodates the fact that even on a Linux system with case-sensitive file names, Git can't create both a file named feature and a file named feature/name. If Git always stored all branch information in encoded names, rather than just using the branch's name as a path-name, this particular problem would go away—as would the case-folding issues. In my opinion, this is the right way to solve all the branch case-folding problems. It does nothing for any file name case-folding problems, though.

Upvotes: 6

ElpieKay
ElpieKay

Reputation: 30858

origin/US/99867_blabla is a remote-tracking branch that exists in the local repository, and refs/heads/us/blabla returned by git ls-remote is a branch that exists in the remote repository.

From the output of the 3 commands, we can guess that US/99867_blabla does not exist in the remote repository any longer. It may have been renamed or deleted. If so, the local origin/US/99867_blabla is negligible and useless.

Try git fetch --prune, which is expected to create origin/us/blabla and delete origin/US/99867_blabla.

Upvotes: 0

Related Questions