Git:无法创建符号链接(文件名太长)

33

我把一个项目从Linux推送到Bitbucket,然后在Windows上克隆了它。结果发现有两个符号链接,在Windows上显示为文本文件。由于我知道它们应该指向哪里,我将它们替换为其目标文件的副本,进行了提交并推送。

现在当我从Unix机器上进行git克隆时,Bitbucket存储库在Web界面上看起来正常。但是会给我两条像这样的消息:

error: unable to create symlink ... (File name too long)

两个之前是符号链接的文件现在已经不存在了。我尝试在/tmp/...中进行克隆以获得更短的文件名,但是得到了相同的结果。这表明,Bitbucket存储库出了问题。我已经尝试打开和关闭 core.symlinks

我可以不使用符号链接,但我希望有一个可用的存储库。有没有人知道其他方法(而不是重新创建存储库)?

6个回答

36

以下是不需要你回去修改提交记录的解决方案。 因为如果代码库是远程或共享的,则这可能是不可行的。 该方案使用core.symlinks=false。 你说过你尝试过,但没有说明何时尝试过。 你必须在检出之前进行此操作,而普通克隆默认会检出。 因此,你必须使用--no-checkout选项进行克隆。

git clone --no-checkout the-repo tmp-clone-dir
cd tmp-clone-dir
git config core.symlinks false
git checkout
cp the-problem-file the-problem-file.bak # make a backup
git rm the-problem-file
git commit -m 'Removed problem file pretending to be a symlink' the-problem-file
mv the-problem-file.bak the-problem-file # restore the backup; now it will be of type file
git commit -m 'Added back the problem file - now with the correct type' the-problem-file
git push origin master
cd ..
\rm -rf tmp-clone-dir  # IMPORTANT

这是非常重要的一步,因为您不希望在 core.symlinks=false 的存储库中进行更多的工作。这只会引起麻烦。

上述假设您想让文件成为文件而不是符号链接。如果它应该是符号链接,那么您将在第一个提交之后停止,删除tmp-clone-dir,并返回到正常的仓库检出以创建符号链接并提交它。

这种方法的好处在于,它不会破坏任何相关克隆和分支,因为它保留了历史记录。缺点是,损坏的提交仍然存在,如果任何人尝试使用该特定的坏提交,将会导致问题。


如果我能的话,加2。 - jomofrodo
这个方法非常有效,应该被采纳为最佳答案。 - Robb Vandaveer
2
在第二次提交之前,必须使用 git add <问题文件> 才能正常工作。完美的答案! - JustCoding
对我来说,本地仓库的简单克隆并没有起作用,因为之后远程“origin”的URL指向了git pull失败的目录——有问题的提交不在那里。(也许在较新版本的Git中已更改?)基本上,我不得不使用: git clone --no-checkout --reference the-repo <CLONEURL> tmp-clone-dir(使用引用可以使克隆更快。)或者您可以使用原始命令,只需编辑.git/config - hansfn

19

我遇到过同样的问题,这个方法解决了我的问题:

git config core.symlinks false
git rm <problem-file>
git commit <problem-file>
git push
git config core.symlinks true

第一条命令后面不是应该加一个checkout命令吗? - mattalxndr
是的,这可能是最简单的解决方案。暂时禁用符号链接使我们能够拉取有问题的提交,而且似乎只影响新创建的文件。如果您还拉取添加正确符号链接的提交,可能会变得混乱... PS!缺少的步骤是git pull,而不是git checkout - hansfn
只有 git config core.symlinks false 对我起作用。 - FractalSpace

16

一旦你更改了一个伪符号链接文件的内容,且没有将其模式从符号链接更改为常规文件并提交结果,您就创建了一个不能在具有真实符号链接的操作系统中提取的 blob,因为您拥有一个应该是符号链接但其内容太长而无法成为路径名的对象。网页界面隐藏了这个问题,对你没有任何帮助。

你可能需要返回到那个提交,修复它,并重新提交之后的所有内容。git rebase -i会有所帮助,但这仍然可能不容易,尤其是如果在这些虚假的符号链接状态下进行了更多文件更改。

假设坏的提交是abcdef123,你需要这样做:

git rebase -i 'abcdef123^'

这将使您进入带有提交列表的编辑器。 abcdef123 应该在第一行。 在该行上,将 pick 改为 edit。 如果有多个错误提交,则全部更改为 edit。 保存并退出编辑器。

现在,您将回到提交错误文件的时间点。 这是您修改历史记录的机会,纠正曾经出错的事情。 使用以下命令检查提交:

git show

通过将原始符号链接路径名恢复到文件中并使用git add来撤消错误部分。或者,您可以使用git rm彻底摆脱符号链接,然后创建一个新文件并git add它。如果选择第一种选项,请注意符号链接的内容只是一个路径名。它不是文本文件-它没有换行符。如果您使用添加换行符的文本编辑器进行编辑,则会出现损坏的符号链接(指向名称中带有换行符的文件)。

完成git add后,将修复的提交重新插入历史记录中的相应位置:

git commit --amend
git rebase --continue

如果你将多个提交从pick更改为edit,则必须对每个提交重复该过程。最终的git rebase --continue将带您回到当前状态。

如果在rebase期间你发现自己处于一个错误的提交中(它除了用文件指向的未修改内容替换符号链接外没有其他操作),那么你可以使用git rebase --skip而不是修订并继续。如果你预先知道这将会发生,你只需从git rebase -i列表中删除错误的提交,而不是将其pick更改为edit

如果有多个分支受到坏提交的影响,你必须对每个分支重复整个过程。检出一个分支,运行git rebase -i完成(即当git rebase --continue显示“成功rebase”时),然后检出下一个分支再重复上述步骤。

在将来,当你把开发工作分配到Windows和真正的操作系统之间时,请使用cygwin进行Windows工作。在cygwin内部,符号链接就是符号链接,你不会像以前那样搞砸它们。

3

我曾经遇到过一些文件出现同样的问题。我通过使用git remove --cached <file>将它们从仓库中删除来解决了这个问题(这不会删除我的源文件,它们不再是符号链接)。一旦所有文件都被删除,git会发现它们仍然存在,所以我可以使用git add .将它们重新添加,并提交回去。现在git将它们视为普通文件。

最初的回答:

我用 git remove --cached <file> 将文件从代码库中移除,这并不会删除我的源文件(这些源文件不再是符号链接)。然后我再使用 git add . 将文件重新加入代码库,并提交更改。这样Git就会将它们视为普通文件。


1
这个操作完美地执行了,但命令是 git rm --cached <file> - Mattias Axelsson

0

git config --global core.longpaths true

将此命令输入并重试,它会起作用的。


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community
这应该是被接受的答案。问题不在于符号链接,而在于若没有正确设置,git会无法接受长路径。 - Cobra

-1

如果您使用的是Bitbucket,那么还有一种更简单的方法。现在Bitbucket支持在线删除文件,您可以转到Bitbucket上的存储库,找到有问题的文件,在“编辑”按钮旁边的下拉按钮和“删除”中选择。

这将删除带有损坏符号链接的文件,并使您的工作目录恢复正常。如果可能的话,这比手动重新定位和删除快得多。


1
问题是关于 Git,而不是 Bitbucket。 - Denis Matafonov
因为这个“解决方案”可能会导致数据丢失,所以被踩了! 你没有理解原问题是什么。他不想完全摆脱符号链接,而是想将符号链接转换为普通文件并保留文件的内容。如果你删除符号链接,就会丢失内容,却没有任何收益。 - Mike

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