从git中删除一个文件名奇怪的文件

11

我有一个文件,它自己设定了一个名字:

# file's name (both lines)
companies.yml
companies.yml

# entry in my git working tree
"test/fixtures/companies.yml\342\200\250companies.yml"

由于某些烦人的原因,这个特定项目的工作树充满了其他仍需要组织的文件。我想把上述条目从中移除,但是当我尝试使用 git add "test/fixtures..."git rm "test/fixtures..." 时它会失败:
fatal: pathspec 'test/fixtures/companies.yml\342\200\250companies.yml' did not match any files

我该怎么处理?


Git状态

On branch master
# Your branch is ahead of 'production/master' by 4 commits.
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)

modified:   [other files]
modified:   "test/fixtures/companies.yml\342\200\250companies.yml"

我可以轻松地创建、git addgit rm一个同名的文件。你在哪个平台上? - Fred Foo
git rm test/fixtures/companies.yml*(如果您没有其他与该模式匹配的文件)?使用通配符解决问题文件名的方法是一种古老的传统。 - Michał Politowski
git checkout -- test/fixtures... 做什么? - Yuval Adam
@larsmans - 我在使用 OS X。 - sscirrus
@MichałPolitowski - 我尝试过了,文件已经消失了,但是工作树仍然有“删除”的行项目。 - sscirrus
3个回答

14

Git正在打印文件名UTF-8编码的字面八进制值,因为它们是非ASCII字符,并将它们作为八进制转义序列打印出来。但是,当你剪切和粘贴时,你的shell不理解它们,并向git命令发送字面反斜杠和数字,因此你实际上输入了一个不同的文件名。

要么在键入test/fixtures/companies.yml后使用选项卡自动完成(如果您的shell支持此功能),这将输入实际字符,要么在逃逸序列中使用通配符,如test/fixtures/companies.yml*companies.yml。后者可能会与其他文件名匹配,但也可能不匹配。

另一个可能性是将文件重命名为更合理的名称,然后使用git add -u/git add .让git注意到重命名。


我在我的shell中没有tab补全功能,所以我直接从Finder中复制名称到git rm "text/fixtures/[paste]"。这个方法奏效了!+1 - sscirrus
@sscirrus提供了一个非常完整的问题解释,并且给出了可行的解决方案。我也赞同他的说法。 - VonC
我正在从我的本地代码库中移除一个WordPress安装(其中包含UTF8字符的上传文件),并且“git rm blog/*”非常好用。谢谢! - h2ooooooo

12

由于您正在使用bash,您可以使用printf命令

git rm --cached `printf "test/fixtures/companies.yml\342\200\250companies.yml"`

\0开头的八进制转义字符可以包含最多四个数字。
(POSIX规定最多三个)

你可以在“Git:如何在命令行中指定包含八进制表示法的文件名”中看到类似的解决方案。

这将从索引中删除该文件,同时仍将其保留在工作目录中。
然后,如果需要,可以将其重命名。


更新Git 2.18(2018年第二季度,6年后),使用简单完成应该可以奏效。

请参见提交3dfe23b(2018年4月16日)由SZEDER Gábor(szeder

完成:支持完成非ASCII路径名

  

除非用户在配置中某处设置了'core.quotePath=false',否则'git ls-files'和'git diff-index'默认情况下都会引用任何包含值高于0x80的字节的路径名,并将这些字节作为“\nnn”八进制值进行转义。
这会防止完成包含任何非ASCII(尤其是UTF-8)字符的当前路径组件时,因为列出的引用路径都不会与命令行上的当前单词匹配。

  

为那些'git ls-files'和'git diff-index'调用设置'core.quotePath=false',这样它们就不会将高于0x80的字节视为“异常”,也不会引用包含这些字符的路径名。

  

请注意,仍将引用包含反斜杠、双引号或控制字符的路径名; 该系列中的后续补丁将处理这些情况。


我刚意识到这些解决方案只是将文件移动到“要提交的更改”中。它并没有让我的工作树保持不变... - sscirrus
@sscirrus,我已经编辑了答案,以确保工作树不受影响。 - VonC

1
我想删除我的git仓库中一个包含俄语字母的文件夹:"Файлы Mail.Ru Агента"。首先我手动删除了该文件夹,然后想用git删除它。
git rm "..."

在下一步中使用命令。但是,git向我显示了一个非常晦涩的删除文件夹名称: "\320\244\320\260\320\271\320\273\321\213 Mail.Ru \320\220\320\263\320\265\320\275\321\202\320\260"。 我使用以下命令恢复了该文件夹:
git checkout

然后只需复制文件夹名称并执行命令。
git rm "Файлы Mail.Ru Агента/*"

它成功了!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接