Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Git not ignoring case in filenames that are checked out from another commit #2502

Closed
1 task done
eggonzal opened this issue Jan 30, 2020 · 8 comments
Closed
1 task done
Labels
case-insensitive-fs Bug related to case-insensitive file systems question

Comments

@eggonzal
Copy link

  • I was not able to find an open or closed issue matching what I'm seeing

Setup

  • Which version of Git for Windows are you using? Is it 32-bit or 64-bit?
$ git --version --build-options

git version 2.19.2.windows.1
cpu: x86_64
built from commit: 26dcaa1b6b5fd862db3ec40983e33ff3432f1166
sizeof-long: 4
sizeof-size_t: 8
  • Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.17763.973]
  • What options did you set as part of the installation? Or did you choose the
    defaults?
# One of the following:
> type "C:\Program Files\Git\etc\install-options.txt"
> type "C:\Program Files (x86)\Git\etc\install-options.txt"
> type "%USERPROFILE%\AppData\Local\Programs\Git\etc\install-options.txt"
$ cat /etc/install-options.txt

Editor Option: VIM
Custom Editor Path:
Path Option: Cmd
SSH Option: OpenSSH
CURL Option: OpenSSL
CRLF Option: CRLFAlways
Bash Terminal Option: MinTTY
Performance Tweaks FSCache: Enabled
Use Credential Manager: Enabled
Enable Symlinks: Disabled
  • Any other interesting things about your environment that might be related
    to the issue you're seeing?

My config is set to ignore case as the OS does.

Details

  • Which terminal/shell are you running Git from? e.g Bash/CMD/PowerShell/other

CMD, gitpython, gitbash

git checkout -b branchA
echo "Some text" > MyFile.txt
git add MyFile.txt
git commit -m"Added MyFile"
git checkout master
git checkout -b branchB
echo "Other text" > myfile.txt
git add myfile.txt
git commit -m"Added myfile"
git checkout branchA
git checkout branchB -- myfile.txt

  • What did you expect to occur after running these commands?

Expected git to ignore the file name upper and lower cases, as it does when you try to add a file with the cases modified with git add or by manually changing the file name in the OS.

  • What actually happened instead?

Git thinks that there are 2 different files but the OS only sees one.

In this scenario git says that there is a New file named myfile.txt and a modified file named MyFile.txt. So it causes some conflicts with a GitPython application that I use to automate the code tracking using git.

I'm not sure if that is the only possible way to trigger this behavior but I'm sure that is not being consistent with how it handles a scenario like:

echo "something" > MyFile.txt
git commit -am"Added MyFile.txt"
echo "something else" > myfile.txt
git commit -am"Added myfile.txt"  

In this scenario git ignores the upper and lower case differences as expected.

  • If the problem was occurring with a specific repository, can you provide the
    URL to that repository to help us with testing?

Any repo

@tboegi
Copy link

tboegi commented Jan 31, 2020

This is the expected behavior, kind of.
You told Git to track "MyFile.txt" and "myfile.txt".
Both are different "objects". Doing so on a case insensitive file system
produces a conflict, which Git cannot resolve:
a) You want both be tracked -> that is impossible in the FS. Rename one of them (or both)
b) You want to go for myfile.txt -> then please rename "git mv MyFile.txt myfile.txt"
c) You want to go for MyFile.txt -> then please rename "git mv myfile.txt MyFile.txt"

Git can not make any decision, which of those 3 is the "right one".

@dscho dscho added the case-insensitive-fs Bug related to case-insensitive file systems label Jan 31, 2020
@dscho
Copy link
Member

dscho commented Jan 31, 2020

I concur with @tboegi: there is little Git can do in this case. Maybe warn, or error out, because the two files cannot be represented by two separate files on a case-insensitive filesystem.

@dscho dscho added the question label Jan 31, 2020
@dscho
Copy link
Member

dscho commented Jan 31, 2020

there is little Git can do in this case. Maybe warn, or error out

@eggonzal are you feeling up to providing an awesome patch to implement that warning/error message?

If so, first upgrade from your (vulnerable) version to v2.25.0 and see whether such a message has already been implemented. If not:

  1. install Git for Windows' SDK,
  2. sdk cd git,
  3. look around the code to see where such a message might be appropriate,
  4. build Git via make -j$(nproc)
  5. test in-place via ./git --exec-path="$PWD" -C <directory> <command>?
  6. open a PR?

@eggonzal
Copy link
Author

This is the expected behavior, kind of.
You told Git to track "MyFile.txt" and "myfile.txt".
Both are different "objects". Doing so on a case insensitive file system
produces a conflict, which Git cannot resolve:
a) You want both be tracked -> that is impossible in the FS. Rename one of them (or both)
b) You want to go for myfile.txt -> then please rename "git mv MyFile.txt myfile.txt"
c) You want to go for MyFile.txt -> then please rename "git mv myfile.txt MyFile.txt"

Git can not make any decision, which of those 3 is the "right one".

Is not possible for Git to behave as the OS would behave? For example if I manually want to reproduce that conflicting state by copying and pasting files or redirecting an input to the file with the case letters changed, I'm not able to fool Git, but if I checkout files from a different revision into the working index, it gets conflicted (isn't it possible to fix it at this stage?).

I guess I could look in advance for the issues and programmatically fix them but still I'm not sure how I can tell which file was in place and which file is new. Ideally Git would override the existing file with the new one or at least that would be what I want to do.

@dscho
Copy link
Member

dscho commented Jan 31, 2020

I think the problem here is that you switch from one revision that has the file to another revision that has the file with a different casing. So if you lstat() the first revision's file, the OS will report that it exists already.

When I looked around for a way to find the on-disk casing for any given file, I found only solutions that would put a serious performance dent into things.

So I guess you would need to do this on the index, probably using the name_hash attribute of the index_state (as far as I remember, the name_hash is a case-insensitive hashmap when core.ignoreCase = true).

@eggonzal
Copy link
Author

eggonzal commented Feb 1, 2020

I think the problem here is that you switch from one revision that has the file to another revision that has the file with a different casing. So if you lstat() the first revision's file, the OS will report that it exists already.

When I looked around for a way to find the on-disk casing for any given file, I found only solutions that would put a serious performance dent into things.

So I guess you would need to do this on the index, probably using the name_hash attribute of the index_state (as far as I remember, the name_hash is a case-insensitive hashmap when core.ignoreCase = true).

Can you elaborate more on the name_hash? That sounds useful, but is that from GitPython? Can you point me into some documentation?

Thanks

@dscho
Copy link
Member

dscho commented Feb 1, 2020

No, name_hash is in the C source code of Git (for Windows).

Just get the Git for Windows SDK, call sdk cd git and then git grep name_hash (sorry for the brevity, am on the phone).

@tboegi
Copy link

tboegi commented Feb 1, 2020

For those who are interested to work on Git, there is a check when
git clone is used and the resulting worktree has a upper/lowercase conflict.

commit b878579
Author: Nguyễn Thái Ngọc Duy pclouds@gmail.com
Date: Fri Aug 17 20:00:39 2018 +0200
clone: report duplicate entries on case-insensitive filesystems

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
case-insensitive-fs Bug related to case-insensitive file systems question
Projects
None yet
Development

No branches or pull requests

3 participants