由于 CONFLICT(MODIFY/DELETE) 和符号链接,无法 git 拉取

Cannot git pull due CONFLICT(MODIFY/DELETE) and symlink

我们的 Laravel 项目正在使用符号链接。最近,当我试图从我同事的工作中抽身时,我收到了这条消息:

CONFLICT (modify/delete): resources/lang/en/validation.php deleted in HEAD and modified in a262067feb430a072c1d3abf2ec500150212ff0f. Version a262067feb430a072c1d3abf2ec500150212ff0f of resources/lang/en/validation.php left in tree.
error: failed to symlink 'resources/lang/en/validation.php': File name too long

在尝试 git rm 文件时,我被告知它不存在并且已在 HEAD 中删除。然后,当我拉动时,我会收到与上面相同的消息。在尝试 touch 文件和 git add 文件,然后提交然后拉取(以便将我的更改推送到同一分支)时,我收到类似的错误消息:

CONFLICT (content): Merge conflict in resources/lang/en/validation.php
CONFLICT (modify/delete): resources/lang/en/auth.php deleted in HEAD and modified in a262067feb430a072c1d3abf2ec500150212ff0f. Version a262067feb430a072c1d3abf2ec500150212ff0f of resources/lang/en/auth.php left in tree.
error: failed to symlink 'resources/lang/en/auth.php': File name too long

我尝试跳过文件的工作树,假设文件不变,并通过 git config --local core.longpaths true 更改 git 配置设置以允许长路径。 None 有效。我认为这与符号链接有关,但我还没有 运行 脚本,所以我不知道这如何成为 git.

的障碍

当我尝试 运行 符号链接时,我收到此错误消息:

error: unable to create symlink resources/lang/en/auth.php: File name too long
error: unable to create symlink resources/lang/en/validation.php: File name too long

长话短说,我不能 git 拉,因此也不能 git 推。解决办法是什么?我不想 git push force 它。

运行 git pull 只是 运行 两个 Git 命令:

  • 首先,git pull 运行s git fetch。这将获得第二个命令所需的任何新提交。
  • 其次,git pull 运行s ...好吧,这可能很复杂。不过,您将其设为 运行 默认值:git merge.

通常当 git pull 失败时,它 运行 执行的这两个命令之一是实际失败的命令。除非您的 Internet 连接特别不稳定,否则第二个命令会更频繁地失败。在您的情况下,失败的是 git merge

失败这个词通常太强了,真的。大多数合并实际上 失败 。由于冲突(或两个冲突,在您的特定情况下),它们只是在操作中间停止。但是你的合并有点特别。确实有内部故障,重复了好几次:

error: unable to create symlink resources/lang/en/auth.php: File name too long
error: unable to create symlink resources/lang/en/validation.php: File name too long

发生这种情况是因为您的 OS 对符号 link 的目标长度设置了硬性限制。如您所见:

It seems it was trying to make a symlink out of the content inside the file instead of the file name ...

Git 的内部限制比 OS 的要大得多。

一个符号 link 在一个层面上只是数据,这就是 Git 倾向于存储它的方式(作为一个 blob 对象,但是带有 mode 120000 而不是正常的100644100755 的文件模式)。在另一个层面上,数据将被解释为文件名,而该文件名往往有长度限制,例如 1024 或 4096 字节。

What would git show do?

git show 将在指向符号-link 对象时溢出 symlink 的内容。

$ git hash-object -w -t blob /usr/share/misc/termcap
d305cd8e161ecc8a78b0485d1926b9600efc6cb7
$ git update-index --add --cacheinfo 120000,d305cd8e161ecc8a78b0485d1926b9600efc6cb7,crazy
$ git commit -m "add crazy-long symlink"
[master dbb6e35] add crazy-long symlink
 1 file changed, 4725 insertions(+)
 create mode 120000 crazy

普通工具将不再适用于此存储库(我制作它只是为了保存这个疯狂的长 symlink):

$ git log | sed 's/@/ /'
commit dbb6e35967041fa4b03812866999ea0acd640dce
Author: Chris Torek <chris.torek gmail.com>
Date:   Sun Nov 15 19:52:05 2020 -0800

    add crazy-long symlink

commit c6e238c122dcd41410e7fdcfaa47ac112e935a35
Author: Chris Torek <chris.torek gmail.com>
Date:   Sun Nov 15 19:51:58 2020 -0800

    initial commit

$ git checkout HEAD^

这工作正常,但尝试检查第二个提交失败:

$ git checkout master
error: unable to create symlink crazy: File name too long
D        crazy
Previous HEAD position was c6e238c initial commit
Switched to branch 'master'

此时发生的是 Git 只是将符号 link 完全排除在 工作树 之外。这就是它处于状态 D 的原因。您仍然可以使用存储库,但不能以常规方式使用常规工具。

通过合并,您可以完全(安全地)删除错误的符号 link,创建正确的(好的)符号,然后添加它们。