如何在OS X上清除git中的区分大小写问题?

时间:2016-07-11 14:10:44

标签: git macos

尝试时

git mv dir1/File.py dir2

我得到了

fatal: not under version control, source=dir1/File.py, destination=dir2/File.py

调试我运行

git ls-files | grep File.py

幸运的是我有alias grep="grep -i",问题很明显。 file.py受版本控制。 File.py不是。

我猜我曾经从shell重命名file.pyFile.py(在OS X上,这通常需要通过第三个名称)。 Git继续将这两个文件视为相同,因为OS X将它们视为一个。但是除非案例也匹配,否则git拒绝移动文件。

如何系统地确定git仓库中是否存在类似的区分大小写问题?

我使用的是OS X extended (Journaled)的默认格式,区分大小写,我希望保持这种格式。

更新

我刚注意到这个relevant帖子。

1 个答案:

答案 0 :(得分:0)

This is a bit hacky, but it should work, in Bash:

git ls-files | xargs -I{} sh -c 'ls "{}"* &>/dev/null || echo {}'

The goal is to run a command that reveals the actual case of the file.

Consider this:

$ ls
A.md

We have a single file named A.md. But then:

$ ls a.md
a.md

What? Even though the actual name is A.md, the shell matches it to a.md -- the wrong case.

Luckily, this works differently when we use globs:

$ ls a.md*
ls: a.md*: No such file or directory
$ ls A.md*
A.md

This is what we're looking for: by doing ls the-file*, we can verify if that exact name really exists or not.

For this to work, the nocaseglob option of Bash must be off:

shopt -u nocaseglob

The command at the very top runs for each file in the repository this shell:

ls "{}"* &>/dev/null || echo {}

Here, {} is the name of the file in the loop iteration, and we try to do a ls {}*, discard the output of the command, and if the command failed, we print the filename that we tried. The command fails if the file doesn't exist: for example because the case of the filename is different.

The output of the command at the top will be the list of files that are in your Git repository, but cannot be found by the same name. These are the files you need to fix.

Limitations: the command may not work well in some cases:

  • If you have multiple files with the same beginning
  • If you have files with newline in the name

Lastly, you can change the case of a file without going through a 3rd intermediary name in Finder.

If you have no changes in your working tree, then a simple way to fix the names is to remove them from the workspace and then checkout:

git ls-files | xargs -I{} sh -c 'ls "{}"* &>/dev/null || echo {}' | xargs rm
git checkout .