问题
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