我正在尝试从 Git 中提取并收到错误:
The following untracked working tree files would be overwritten by merge:
:q
Please move or remove them before you merge.
我既找不到这个文件,也不知道它可能指的是什么,或者为什么它以 :
git diff 显示它是一个新文件
(从评论中大大扩展;也许是一个答案,尽管原始问题中没有足够的信息可以说明。
首先,旁注:这是在Windows上吗? Windows 名称中带有冒号的文件存在"问题"。 (我尽可能避免使用Windows,并且不确定这一点,但我认为即使在那里创建这样的文件也是不可能的。 其他系统应该可以很好地处理它,它不应该被神秘地隐藏起来——但我将在下面探讨两种可能性。
另一个旁注:git pull
只是运行git fetch
(从另一个 Git 获取提交并将它们放入origin/master
等下的存储库中),然后是git merge
(将现在在您的origin/master
中的提交合并到您自己的master
中)。 我没有设置远程,所以下面,我直接使用git merge
,在我自己的仓库中有一个命名的侧分支,而不是这些origin/master
的东西之一(它们很像分支,但不是 - 至少不完全- 实际上是分支,因为 Git 术语很糟糕)。
查找名称奇怪的文件
你说你找不到:q
文件,但(a)不要提到你使用什么工具来查找它,(b)确实说git diff
将一个名为:q
的文件显示为一个新文件(同样没有引用实际的git diff
输出,很难猜到你的意思)。 这意味着您可以通过某些工具查看文件,即使只是间接查看,也可以通过您正在使用的工具以外的工具查看文件,该工具通常会直接显示文件。
作为实验,我创建了一个新的存储库,并在其中创建了一些虚拟文件和一个侧分支。 在侧分支中,我创建并提交了两个具有"有趣"名称的文件。 一个具有四个字符名称冒号Q退格键 - 朴素程序可以通过将:q
字符串写入显示器,然后将两个退格写入显示器来"显示"此文件的名称,以便下一个字符覆盖冒号和小写-q。 然后,下一个文件名可能会覆盖刚刚显示的文件名。 另一个"有趣的名称"文件是冒号Q空格,在显示时,它看起来像没有空格的:q
,因为屏幕的大部分空间都充满了空间,看起来与空格一模一样。:-)
现在,这个特定系统上的ls
命令并不那么幼稚,因此运行ls
我们得到:
$ ls
:q?? :q README file
显示在屏幕上,但如果我运行ls -C | expand
我会得到:
$ ls -C | expand
:q README file
如您所见,或者"看不到"会更好措辞,名称中带有退格键的文件似乎已经消失,除了在列化文件列表中占据一个插槽。 不过我们知道它在那里!
通过git status
查找名称奇怪的文件
如果我现在运行git status
,这就是它显示的内容:
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
":qbb"
:q
nothing added to commit but untracked files present (use "git add" to track)
在这里,Git 特别注意特别显示嵌入式退格名称:它添加了双引号并使用b
对退格进行编码。 然而,用尾随空格拼写的名称仍然相当巧妙地伪装:它显示为冒号、Q、空格,而"空格"看起来与没有空格完全相同。
合并时 Git 的作用
由于我已经在侧分支sidebr
上提交了这些文件,因此任何合并它们的尝试都会产生:
$ git merge sidebr
error: The following untracked working tree files would be overwritten by merge:
:q??
:q
Please move or remove them before you merge.
Aborting
同样,Git 对退格键做了一些聪明的事情,但尾随空白只是简单地复制到屏幕(好吧,Terminal
窗口),在那里它看起来与背景相同。
从工作树中删除不需要的文件
要删除不需要的文件,我可以简单地删除所有以冒号和 q 开头的文件:
$ rm :q*
$ ls
README file
之后git merge sidebr
成功:
$ git merge sidebr
<git makes me enter a merge commit message>
Merge made by the 'recursive' strategy.
":qbb" | 1 +
:q | 1 +
2 files changed, 2 insertions(+)
create mode 100644 ":qbb"
create mode 100644 :q
在下次提交中删除不需要的文件
现在不需要的文件又回来了 - 毕竟,我故意将它们提交到分支sidebr
中,专门用于设置此问题。 但是现在它们不再是未跟踪的文件,因此要删除它们,我想使用git rm
而不是普通rm
,然后我也想提交删除。
在这一点上,我遇到了另一个问题:
$ git rm :q*
fatal: pathspec ':q??' did not match any files
这里发生的事情是 Git 特别处理以冒号开头的参数。 为了解决此问题,我首先正常删除了文件:
$ rm :q*
然后告诉 Git 更新它知道的所有文件,其中当然包括这两个:q<otherstuff>
文件:
$ git add -u
现在git status
显示:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: ":qbb"
deleted: :q
我可以运行git commit
:
$ git commit -m 'remove icky colon-named files'
[master 1e4e9f6] remove icky colon-named files
2 files changed, 2 deletions(-)
delete mode 100644 ":qbb"
delete mode 100644 :q
由于您从git merge
收到同样的投诉,一旦您实际从工作树中删除了不需要的文件,您的git pull
或git merge
会将其作为已提交(而不是未跟踪)文件恢复,您将需要使用类似于上述两步过程的内容提交删除。
为了完整起见(无需阅读本节):为什么git rm :q*
失败
还有一个替代技巧,我在这里包括它进行说明。 Git 对名为:q<space>
等的文件的问题不是空格,而是前导冒号。 这记录在 Git 术语表中的pathspec
定义下。
以冒号开头的路径规范 : 具有特殊含义。在简称中,前导冒号:后跟零个或多个"魔术签名"字母(可选择由另一个冒号:)终止,其余部分是与路径匹配的模式。"魔术签名"由既不是字母数字、glob、正则表达式特殊字符或冒号的 ASCII 符号组成。如果模式以不属于"魔术签名"符号集且不是冒号的字符开头,则可以省略终止"魔术签名"的可选冒号。
在长形式中,前导冒号:后跟一个左括号(以逗号分隔的零个或多个"魔术词"列表,以及一个右括号),其余部分是与路径匹配的模式。
在这种特殊情况下,:q<backspace><backspace>
被视为:
- 开始使用PathSpec Magic(
:
启动Magic) - 不要魔法(
q
是字母数字,不是左括号,所以这是缩写形式,没有魔法字符) - 使用名称
q<backspace><backspace>
当然,该文件不是命名为q<backspace><backspace>
而是:q<backspace><backspace>
.
在这里输入::q<backspace><backspace>
是可行的,但是在 shell 中使用:q*
的要点是,键入退格字符,而不是以通常的方式擦除它们,是很困难的,所以这违背了重点。
使用rm :q*
和git add -u
使 Git 搜索目录,从而避开了路径规范的魔力。 但还有另一个简单的技巧:名称为:q<backspace><backspace>
的文件具有无限多的名称,其中大多数名称不以冒号开头。 其中最简单的是./:q<backspace><backspace>
. (其他包括././:q<backspace><backspace>
等,用于无限数量的前导./
序列。 所以我们只是让 shell 为我们生成这些名称:
git rm ./:q*
现在我们已经准备好承诺了。
我选择了上面的git add -u
方法,因为最有可能的是,无论谁创建并提交这个名称奇怪的文件,无论它的名字是什么 - 它可能是:q<space>
,或:q<space><space>
,或:q<tab>
,或:q<newline>
,在众多可能性中 - 可能首先使用git add .
或git add -A
等将其添加到提交中。
在我看来,您在尝试退出 vi 时键入:w:q而不是:wq。 我不清楚为什么合并会破坏这个文件,但如果它的存在确实是偶然的,那么删除它是安全的。
我不确定为什么找到它会有问题。 但我不明白为什么
rm :q
(在工作树根目录中)不会解决问题,如果您确实知道这是一个垃圾文件