After changing the case of a filename, git complains about potential data loss on checkout

耗尽温柔 提交于 2021-02-19 04:33:09

问题


Based on this answer I used git mv to change the case of the extension of a filename.

Now however, whenever I try to change branch, I get the following error:

git checkout MyBranch
error: The following untracked working tree files would be overwritten by checkout:
    MyFile/With/The/OldExtension.Ext
Please move or remove them before you switch branches.
Aborting

I can still change branches with --force, but don't really want to rely on this for obvious reasons.

It seems to me that git's index is out of sync with reality, but I'm not sure how to fix it.

What's my next move?


回答1:


TL;DR: you can probably simply remove the file before checking out the desired commit.

Assuming you're on a system that does case-folding with file names, the issue here is that if Git attempts to create and write on a file named readme.txt when a file named README.TXT exists, this will overwrite the existing README.TXT without creating a readme.txt at all.

As VonC says, if the index is out of step with reality, you can override it. Similarly, if there is nothing of value in the index, you can remove and rebuild it:

rm .git/index
git reset --mixed HEAD

This makes the index match the current commit (not the current work-tree!).

The main issue here is that Git's internals, and Git's index (because it's just a data file in .git/index), all work with raw byte-strings that can hold any file name, including for instance a simultaneous readme.txt and README.TXT. Any Linux system can store both files in the work-tree,1 but a typical MacOS or Windows file system can't. In such a situation—where the index holds both files under those two names that can exist simultaneously on Linux, but not on your own system—the index is guaranteed to be out of step with reality no matter what.

Otherwise—if there's only one case-variant in the index—it may just be that your work-tree file name case differs from that stored in the index, which initially matches that stored in the commit you check out. If/when the underlying OS subverts the file name that Git attempts to create when switching commits, Git is sure that it's created (say) readme.txt and stores that name in the index even though the OS overwrote the existing README.TXT and left that name in the work-tree.

The core.ignorecase setting, which Git sets itself when you first git init the repository (or when git clone initializes it), records how the OS treats file names, so that Git will know to check whether a README.TXT exists before Git attempts to create a readme.txt. In this, er, case, you'll get the error message you're seeing, because Git isn't sure if the README.TXT that's in the work-tree is really the readme.txt that it extracted earlier (maybe you removed that one and put a different README.TXT in that you want to keep).


1This is actually file-system-type-dependent behavior, but the default Linux file systems are case-sensitive. On HFS/HFS+ on MacOS you can choose, at file system build time, whether the file system is to be case-sensitive. I believe the same is true of NTFS, not that I have ever built an NTFS file system.




回答2:


It seems to me that git's index is out of sync with reality

Then, as shown here, try the same git mv in a new clone of the repo, to see if the index there is "less" polluted by that invisible untracked file.



来源:https://stackoverflow.com/questions/53057379/after-changing-the-case-of-a-filename-git-complains-about-potential-data-loss-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!