Git pull 提到了我找不到的未跟踪文件



我正在尝试从 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 pullgit 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

(在工作树根目录中)不会解决问题,如果您确实知道这是一个垃圾文件

最新更新