git - 如何更改已提交的多个文件名称的大小写?
问题描述
我想将我在 Git 上上传的所有 500 张图片重命名为小写。
如果我使用小写图像推送代码,Git 会忽略大小写。
是否有任何特定的命令来修复它?
操作系统:MAC
解决方案
如果我用小写图像推送代码,Git 会忽略大小写...
这实际上不是真的。
要正确理解问题,您需要了解以下内容:
Git 不存储文件,而是提交。
提交确实存储文件,但与您的计算机正常存储的方式不同。存储在提交中的文件始终具有区分大小写的名称。
git push
发送提交。
从这个意义上说,Git 完全有能力用新提交Y中的新小写名称替换提交X中的所有仅大写名称,同时保持每个文件的所有内容相同。也就是说,在提交X中,您会找到 file ,而在提交Y中, file将与之前的文件是“相同的文件”,除了它的名称现在全小写而不是全大写这一事实。X:PATH/TO/FOO.JPG
Y:path/to/foo.jpg
请注意,提交中的文件具有长路径,其中似乎包含文件夹名称。就 Git 而言,它们仍然只是具有这些长路径的文件。事实上,您的计算机需要先创建一个名为的文件夹path
,然后再创建一个path
名为的文件夹to
,这样它就可以在其中有一个名为的文件foo.jpg
,您可以访问它path/to/foo.jpg
......好吧,那是您的计算机的问题;Git 会尽力去适应它。
这也是名称大小写问题出现的地方。您的计算机坚持命名的文件夹PATH
和命名的文件夹path
是同一个文件夹。两者都不会!如果您尝试在名为 的文件夹中创建一个名为 的新文件to
夹path
,并且该文件夹PATH
存在,则您的计算机坚持将该文件夹to
放入名为 的文件夹PATH
中。更糟糕的是,如果名为 的文件夹TO
存在于名为 的文件夹中PATH
,您的计算机会坚持使用该文件夹,而不是创建一个新文件夹。
如果这些都不妨碍,您的计算机将继续创建path
,然后创建path/to
. 因此,您拥有的一个选项1是删除 中的所有内容PATH/TO
,完全删除该文件夹TO
,然后删除其中的所有内容PATH
并完全删除该文件夹PATH
。现在 Git 可以创建path
和path/to
.
无论path/to
or PATH/to
or path/TO
or pAtH/tO
or 发生什么,现在假设 Git 想要创建或修改foo.jpg
此文件夹中命名的文件。如果没有具有该名称的文件,您的计算机很乐意创建一个新文件并保留全小写的名称,这样您就可以foo.jpg
在那里结束。但是,如果已经有一个名为 的文件FOO.JPG
,那么任何创建新文件foo.jpg
并对其进行写入的尝试都只会写入现有的FOO.JPG
,它会保留其大写的名称。
换句话说,这不是Git 的问题。这是你电脑的问题。当然,Git 正在您的计算机上运行,这使它成为您和 Git 需要处理的问题。但重要的是要了解这里到底出了什么问题:是你的计算机,而不是 Git,对你这样做。如果我们让你的 Mac 停止对你这样做,问题就会消失:文件名大小写突然变得重要,Git 认为事情应该是这样,其他一切都正常工作。
1显然,您还有其他选择:例如,您可以重命名PATH
为I_LIKE_YELLING_PATH
,它会保留所有现有文件。最终,您可以将其重命名,或将文件移出,或其他任何方式。
修复它的最简单方法是使用不折叠大小写的文件系统
在 Mac 上,您可以启动运行 Linux 的 VM(例如,参见https://apple.stackexchange.com/questions/264527/linux-vm-installation-on-macbook-pro-with-macos-sierra-10 -12,这是旧的但可能仍然有效;我有一个带有 VirtualBox 的 Linux VM,我在这台特定的笔记本电脑上用于各种事情)。默认的 Linux 文件系统不认为这README
是同一个文件ReadMe
,并且会让您将两个文件都放入文件系统中。Git 在这里工作得非常好,这可能并不奇怪。
(据我了解,VM 也可以在 Windows 上运行良好,并且可能是最简单的方法。不过,我不“做”Windows。)
您还可以制作非大小写折叠文件系统。我不建议将您的主文件系统重新格式化为区分大小写(请参阅https://superuser.com/questions/203896/case-sensitive-folder-names-in-os-x),但您可以制作可挂载的图像,或者使用 U 盘。例如,使用磁盘工具创建一个新的空白图像。将其命名为 -这case-sensitive
将是.dmg
文件的名称 - 并将其放置在您可以轻松访问的地方,例如,Desktop
或Downloads
. 让它足够大,例如,1 GB 应该足够了。对于Format
,选择区分大小写的文件系统,例如Mac OS Extended (Case-sensitive, Journaled)
:
也更改Name
字段,就在上方Size
(我在制作屏幕截图时忘记了这样做)。也就是说,Save As
应该是.dmg
文件的易记名称,并且Name
应该是您希望磁盘在/Volumes
挂载时出现的位置。单击Save
并完成后,单击Done
按钮以关闭弹出窗口。
您现在可以随时挂载此文件系统(磁盘工具现在已经完成;稍后,只需双击该.dmg
文件)并cd /Volumes/case-sensitive
在终端窗口或选项卡中使用。在这里,您可以克隆和使用区分大小写的存储库,而不必担心大小写。
现在您有了一个区分大小写的本地文件系统,克隆您的存储库并重命名您的文件
cd /Volumes/case-sensitive
git clone <url>
cd <clone>/<path>
您现在已准备好重命名。有很多方法可以做到这一点。有关示例 bash 脚本,请参阅VonC 的答案。这是一个/bin/sh
适用于 MacOS 的 shell 片段:
for name in *.JPG; do
lc=$(echo $name | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/')
echo git mv $name $lc
done
运行一次以确保您喜欢该产品,然后再次echo
删除,以便它实际发出git mv
命令。
我自己的首选方法是将文件名转储到/tmp
文件中:
ls *.JPG > /tmp/x # note: ls, not echo, to get one per line
然后将/tmp
文件编辑成正确的一系列命令,在vim
:
vim /tmp/x
:%s/.*/git mv & \L&/
一旦结果看起来正确,我就写出临时文件并退出(ZZ
或:x
)然后执行它。完成后将其删除:
sh /tmp/x
rm /tmp/x
您现在已准备好进行所需的任何其他更改git commit
,并且git push
从/Volumes/case-sensitive
.
(一旦你完成了区分大小写的文件系统.dmg
文件,你可以像处理任何.dmg
文件一样弹出和删除它。如果它不占用太多空间,你也可以随意保留它.)
推荐阅读
- postgresql - 定义从一个实体到另一个实体的一对多映射的问题
- mysql - 在现有项目上从 sqlite3 更改为 mysql
- android - 车辆行驶时 Android 指南针不工作
- java - 用于 javax.validation.ConstraintViolationException 的 Dropwizard 自定义 ExceptionMapper
- reactjs - 可能未处理的 Promise Rejection (id: 0): [Answer] React Native Error while making XMLHttpRequest via device or emulator
- azure - 从 cosmos DB 中提取分区键
- ios - RxSwift:链 Completable 到 Observable
- spring - 使用任何字段分隔符处理文本文件
- git - Jenkins - 如何将变量传递给 Bitbucket 状态通知插件?
- cakephp - 如何在 Cakephp3 的 bootstrp.php 文件中读取会话变量