为什么我不能使用 Windows 原生符号链接在 Cygwin 中克隆带有子模块的 git 存储库?

为什么我不能使用 Windows 原生符号链接在 Cygwin 中克隆带有子模块的 git 存储库?

如果你想克隆一个带有子模块的 git 存储库,供 Cygwin 专用,那么你可以这样做。py模式,Vim 插件,作为示例。您可以在 Cygwin 中执行其文档中描述的 git clone ,而不会出现任何问题。

cd ~/.vim/pack/python-mode/start
git clone --recurse-submodules https://github.com/python-mode/python-mode.git
cd python-mode

从那里,您可以开始使用 Cygwin 版本的 Vim 来无问题地享受插件。

但是,如果您想克隆存储库以用于仅限 Windows 且不使用 Cygwin 的程序(例如 Windows 版 Vim),那么您将遇到 Cygwin 样式符号链接与本机 Windows 程序之间的不兼容问题。简而言之,它们不兼容。本机 Windows 应用程序不知道如何处理 Cygwin 符号链接。但不应期望它们能够做到!

幸运的是,Cygwin 能够在支持它的 Windows 版本上使用 Windows 本机符号链接。(Vista 及更高版本)您所要做的就是在具有管理员权限的 Cygwin 会话中export CYGWIN=winsymlinks:nativestrict。这将强制 Cygwin 使用本机 Windows 符号链接。(如果出于某种原因无法使用,则创建链接的尝试将失败。)

除了告诉 Cygwin 创建符号链接之外,您还必须告诉 git 使用 创建符号链接-c core.symlinks=true,将上面的 git clone 行替换为以下内容:

git clone --recurse-submodules https://github.com/python-mode/python-mode -c core.symlinks=true

到目前为止一切顺利。然后你运行你的克隆……但它失败了!

$ git clone --recurse-submodules https://github.com/python-mode/python-mode.git -c core.symlinks=true
Cloning into 'python-mode'...
remote: Enumerating objects: 42, done.
remote: Counting objects: 100% (42/42), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 8044 (delta 14), reused 32 (delta 12), pack-reused 8002
Receiving objects: 100% (8044/8044), 10.67 MiB | 3.39 MiB/s, done.
Resolving deltas: 100% (3234/3234), done.
error: unable to create symlink pymode/autopep8.py: No such file or directory
error: unable to create symlink pymode/libs/astroid: No such file or directory
error: unable to create symlink pymode/libs/logilab: No such file or directory
error: unable to create symlink pymode/libs/mccabe.py: No such file or directory
error: unable to create symlink pymode/libs/pycodestyle.py: No such file or directory
error: unable to create symlink pymode/libs/pydocstyle: No such file or directory
error: unable to create symlink pymode/libs/pyflakes: No such file or directory
error: unable to create symlink pymode/libs/pylama: No such file or directory
error: unable to create symlink pymode/libs/pylint: No such file or directory
error: unable to create symlink pymode/libs/rope: No such file or directory
error: unable to create symlink pymode/libs/six.py: No such file or directory
error: unable to create symlink pymode/libs/snowballstemmer: No such file or directory
fatal: unable to checkout working tree
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry the checkout with 'git checkout -f HEAD'

为什么会这样?

答案1

如果仔细查看失败原因,您会发现问题出在创建指向子模块的符号链接上。奇怪的是,错误显示“没有这样的文件或目录”。这很奇怪,因为创建指向不存在目标的符号链接是Linux视窗符号链接的版本。

然而,Cygwin不允许这种行为. 假设目录 C:\notreallythere才不是存在,创建指向它的链接失败:

$ ln -sf /cygdrive/c/notreallythere
ln: failed to create symbolic link './notreallythere': No such file or directory

此外,这个问题不太可能得到解决。之前已经有人指出过,但在撰写本文时,这个问题仍然存在。
https://sourceware.org/ml/cygwin/2016-04/msg00658.html
https://sourceware.org/ml/cygwin/2018-09/msg00115.html

那么这如何防止递归 git clone?当 git 克隆带有子模块的存储库时,它会创建指向模块的符号链接它会克隆它们。通常情况下,这是没问题的,因为您通常可以拥有悬空符号链接,并在以后填充它们。但在 Cygwin 中不行!

因此,如果您想克隆一个带有子模块的 git 存储库以在 Windows 中使用,则必须使用 Cygwin 的 git 以外的其他工具。

编辑:据我所知,这是因为 Windows 不能确定目标是文件还是目录,而 POSIX 符号链接则可以。

C:\>mklink /?
Creates a symbolic link.

MKLINK [[/D] | [/H] | [/J]] Link Target

        /D      Creates a directory symbolic link.  Default is a file
                symbolic link.
        /H      Creates a hard link instead of a symbolic link.
        /J      Creates a Directory Junction.
        Link    Specifies the new symbolic link name.
        Target  Specifies the path (relative or absolute) that the new link
                refers to.

相关内容