从 Git 推送和拉取后,目录符号链接更改为文件符号链接
Directory symlinks change to file symlinks after pushing and pulling from Git
目录 symlinks 在 Windows 的 Git 回购中创建,出于某种原因更改为文件 symlinks 一旦推送到 Git 和重新克隆。这会导致 "The directory name is invalid" 错误。
然而,只有当 symlink 在其路径中包含多个子目录时才会发生这种情况。如果只有一个子目录,它们将继续正常工作。此外,它们在 Bash shell.
中仍然可以正常工作
这是原始仓库中的列表:
05/01/2019 07:50 AM <SYMLINKD> ACN [..\..\acn\Installed]
05/01/2019 08:00 AM <SYMLINKD> ACNProxy [..\..\acnproxy\bin]
04/30/2019 01:29 PM <SYMLINKD> API [..\swupdate-2\bin]
05/01/2019 08:24 AM <SYMLINKD> AnalyticsPlugin [..\..\..\analyticsinstallerplugin]
05/01/2019 08:08 AM <SYMLINKD> Encryption [..\protocols\trunk\Encryption]
05/01/2019 08:17 AM <SYMLINKD> HelpFiles [..\helpwwb6]
05/01/2019 08:34 AM <SYMLINKD> PrePackagedDatabase [..\wwb6database]
05/01/2019 09:34 AM <SYMLINKD> ToastNotifications [..\toastnotifications]
05/01/2019 08:01 AM <SYMLINKD> acnComponent [..\..\..\acn_component]
05/01/2019 07:45 AM <SYMLINKD> dante_lic_mac [..\dante_mac_fix\WWB_compressed_lic_info_files]
05/01/2019 08:05 AM <SYMLINKD> devCategory [..\..\..\devicedescriptionfiles\devCategory]
05/01/2019 08:10 AM <SYMLINKD> shared [..\..\frequencycompat\FrequencyCompatibilityCalculator]
05/01/2019 09:26 AM <SYMLINKD> shared [..\..\swupdate\src\shared]
05/01/2019 08:06 AM <SYMLINKD> skuConversion [..\..\..\skuconversion\src]
在将 symlinks 推送到远程 Git 服务器并重新克隆 repo 之后,那些指向包含多个子目录的路径的 symlinks已更改为文件 symlinks:
05/01/2019 09:28 PM <SYMLINK> ACN [..\..\acn\Installed]
05/01/2019 09:28 PM <SYMLINK> ACNProxy [..\..\acnproxy\bin]
05/01/2019 09:28 PM <SYMLINK> API [..\swupdate-2\bin]
05/01/2019 09:28 PM <SYMLINKD> AnalyticsPlugin [..\..\..\analyticsinstallerplugin]
05/01/2019 09:28 PM <SYMLINK> Encryption [..\protocols\trunk\Encryption]
05/01/2019 09:28 PM <SYMLINKD> HelpFiles [..\helpwwb6]
05/01/2019 09:29 PM <SYMLINKD> PrePackagedDatabase [..\wwb6database]
05/01/2019 09:28 PM <SYMLINKD> ToastNotifications [..\toastnotifications]
05/01/2019 09:28 PM <SYMLINKD> acnComponent [..\..\..\acn_component]
05/01/2019 09:28 PM <SYMLINK> dante_lic_mac [..\dante_mac_fix\WWB_compressed_lic_info_files]
05/01/2019 09:28 PM <SYMLINK> devCategory [..\..\..\devicedescriptionfiles\devCategory]
05/01/2019 09:28 PM <SYMLINK> shared [..\..\frequencycompat\FrequencyCompatibilityCalculator]
05/01/2019 09:28 PM <SYMLINK> shared [..\..\swupdate\src\shared]
05/01/2019 09:28 PM <SYMLINK> skuConversion [..\..\..\skuconversion\src]
谁能解释这种行为?
在 Bash shell 中,所有 symlink 在原始和克隆的 repo 中看起来(和功能)相同:
lrwxrwxrwx 1 ******* 1049089 17 May 1 21:28 ./wwb6/API -> ../swupdate-2/bin
lrwxrwxrwx 1 ******* 1049089 46 May 1 21:28 ./wwb6/dante_lic_mac -> ../dante_mac_fix/WWB_compressed_lic_info_files
lrwxrwxrwx 1 ******* 1049089 19 May 1 21:28 ./wwb6/datastorage/ACN -> ../../acn/Installed
lrwxrwxrwx 1 ******* 1049089 18 May 1 21:28 ./wwb6/datastorage/ACNProxy -> ../../acnproxy/bin
lrwxrwxrwx 1 ******* 1049089 22 May 1 21:28 ./wwb6/datastorage/libdatastorage/acnComponent -> ../../../acn_component
lrwxrwxrwx 1 ******* 1049089 43 May 1 21:28 ./wwb6/datastorage/libdatastorage/devCategory -> ../../../devicedescriptionfiles/devCategory
lrwxrwxrwx 1 ******* 1049089 26 May 1 21:28 ./wwb6/datastorage/libdatastorage/skuConversion -> ../../../skuconversion/src
lrwxrwxrwx 1 ******* 1049089 29 May 1 21:28 ./wwb6/Encryption -> ../protocols/trunk/Encryption
lrwxrwxrwx 1 ******* 1049089 54 May 1 21:28 ./wwb6/FrequencyCompatibility/shared -> ../../frequencycompat/FrequencyCompatibilityCalculator
lrwxrwxrwx 1 ******* 1049089 11 May 1 21:28 ./wwb6/HelpFiles -> ../helpwwb6
lrwxrwxrwx 1 ******* 1049089 33 May 1 21:28 ./wwb6/Installation/Mac/AnalyticsPlugin -> ../../../analyticsinstallerplugin
lrwxrwxrwx 1 ******* 1049089 15 May 1 21:29 ./wwb6/PrePackagedDatabase -> ../wwb6database
lrwxrwxrwx 1 ******* 1049089 25 May 1 21:28 ./wwb6/SWUpdate/shared -> ../../swupdate/src/shared
lrwxrwxrwx 1 ******* 1049089 21 May 1 21:28 ./wwb6/ToastNotifications -> ../toastnotifications
请注意,所有这些都是在 Windows 10 机器上完成的。但是,远程存储库位于 Linux 服务器上。我故意在 Windows 机器上没有管理员权限,因为开发人员也没有这些权限,symlinks 应该为他们工作。
为了让 symlinks 在 Windows 中工作,我做了以下工作:
- 安装时启用符号 link 支持 Git Bash;
将以下条目添加到用户的 .bash_profile:
export MSYS=winsymlinks:nativestrict
export CYGWIN=winsymlinks:nativestrict
在 Git:
中启用符号 link 支持
git config --global core.symlinks true
通过使用组策略编辑器将用户添加到“创建符号链接”策略来分配 SeCreateSymbolicLinkPrivilege 权限;
确保允许用户计算本地到本地符号 links:
fsutil behavior query symlinkevaluation
...和 运行 如果不是这种情况,则以管理员身份执行以下命令:
fsutil behavior set symlinkevaluation L2L:1
为了更好的衡量,将 -c core.symlinks=true 切换到 git 克隆命令。
进行所有这些更改后,创建和遍历目录 symlinks 在 Windows 中工作正常,而用户不必在本地管理员组中。直到它们被推送到 Linux 并重新下载。
更新:
在克隆指向子模块内的目录后,将类型从 SYMLINKD 更改为 SYMLINK 的 symlinks。子模块的根目录是在克隆容器项目时创建的,但是直到容器项目(symlinks 所在的位置)的克隆完成后才会下拉内容:
git clone --recursive -c core.symlinks=true ssh://<server>:7999/<repo>
当目标尚不存在时,Windows 似乎不会重新创建目录 symlinks。它改为创建 File symlink 类型的文件。这确实在 Windows 命令行中起作用(就像在 Linux 中一样):
mklink /d symlink ..\<some non-existing directory>\<another non-existing directory>
...工作正常。
我目前的解决方法是简单地删除并恢复它们:
$ find . -type l -delete
$ git checkout .
Updated 14 paths from the index
虽然希望对此进行修复。
这似乎是一个悬而未决的问题,已在 git-for-windows/git issue 1027
中报告
Unusable SYMLINK is created.
Even if I create the target directory later, the symlink is unusable from the Windows explorer.
一个更准确的问题,git-for-windows/git issue 1646 应该会在 2.17+ 中修复。
尽管如此,OP Jozef 还是创建了一个新问题:git-for-windows/git issue 2177.
维护者 Johannes Schindelin (github.com/dscho
) 刚刚添加:
Git's internal data model unfortunately has a very Unix-centric view of symbolic links.
In Git for Windows, we work around that by trying to determine the type from the target (if it exists). That heuristic breaks in your case.
However, we recently introduced the feature where you can declare the symlink type in the .gitattributes
: simply add a line to that file (or create that file with this line as contents if it does not yet exist):
my_symlink_name symlink=dir
Of course, you will want to add and commit this file.
I was modeling the .gitattributes
line after this information:
mklink /d symlink ..<some non-existing directory><another non-existing directory>
The first column in .gitattributes
is always a file name or file name pattern
OP 确认:
That works great on a Windows 10 box running Git 2.21 (had to create 5 .gitattributes
files)
It does not work on a Windows 7 box running Git 2.17.
约翰内斯指出 Git for Windows v2.19.1 (Oct 5th 2018)
The type of symlinks to create (directory or file) can now be specified via the .gitattributes
.
参见 commit 25a7f44。
Symlinks:
On Windows, symbolic links have a type: a "file symlink" must point at
a file, and a "directory symlink" must point at a directory. If the
type of symlink does not match its target, it doesn't work.
Git does not record the type of symlink in the index or in a tree.
On checkout it'll guess the type, which only works if the target exists
at the time the symlink is created. This may often not be the case,
for example when the link points at a directory inside a submodule.
The symlink
attribute allows you to explicitly set the type of symlink
to file
or dir
, so Git doesn't have to guess.
If you have a set of symlinks that point at other files, you can do:
------------------------
*.gif symlink=file
------------------------
To tell Git that a symlink points at a directory, use:
------------------------
tools_folder symlink=dir
------------------------
The symlink
attribute is ignored on platforms other than Windows,
since they don't distinguish between different types of symlinks.
目录 symlinks 在 Windows 的 Git 回购中创建,出于某种原因更改为文件 symlinks 一旦推送到 Git 和重新克隆。这会导致 "The directory name is invalid" 错误。
然而,只有当 symlink 在其路径中包含多个子目录时才会发生这种情况。如果只有一个子目录,它们将继续正常工作。此外,它们在 Bash shell.
中仍然可以正常工作这是原始仓库中的列表:
05/01/2019 07:50 AM <SYMLINKD> ACN [..\..\acn\Installed]
05/01/2019 08:00 AM <SYMLINKD> ACNProxy [..\..\acnproxy\bin]
04/30/2019 01:29 PM <SYMLINKD> API [..\swupdate-2\bin]
05/01/2019 08:24 AM <SYMLINKD> AnalyticsPlugin [..\..\..\analyticsinstallerplugin]
05/01/2019 08:08 AM <SYMLINKD> Encryption [..\protocols\trunk\Encryption]
05/01/2019 08:17 AM <SYMLINKD> HelpFiles [..\helpwwb6]
05/01/2019 08:34 AM <SYMLINKD> PrePackagedDatabase [..\wwb6database]
05/01/2019 09:34 AM <SYMLINKD> ToastNotifications [..\toastnotifications]
05/01/2019 08:01 AM <SYMLINKD> acnComponent [..\..\..\acn_component]
05/01/2019 07:45 AM <SYMLINKD> dante_lic_mac [..\dante_mac_fix\WWB_compressed_lic_info_files]
05/01/2019 08:05 AM <SYMLINKD> devCategory [..\..\..\devicedescriptionfiles\devCategory]
05/01/2019 08:10 AM <SYMLINKD> shared [..\..\frequencycompat\FrequencyCompatibilityCalculator]
05/01/2019 09:26 AM <SYMLINKD> shared [..\..\swupdate\src\shared]
05/01/2019 08:06 AM <SYMLINKD> skuConversion [..\..\..\skuconversion\src]
在将 symlinks 推送到远程 Git 服务器并重新克隆 repo 之后,那些指向包含多个子目录的路径的 symlinks已更改为文件 symlinks:
05/01/2019 09:28 PM <SYMLINK> ACN [..\..\acn\Installed]
05/01/2019 09:28 PM <SYMLINK> ACNProxy [..\..\acnproxy\bin]
05/01/2019 09:28 PM <SYMLINK> API [..\swupdate-2\bin]
05/01/2019 09:28 PM <SYMLINKD> AnalyticsPlugin [..\..\..\analyticsinstallerplugin]
05/01/2019 09:28 PM <SYMLINK> Encryption [..\protocols\trunk\Encryption]
05/01/2019 09:28 PM <SYMLINKD> HelpFiles [..\helpwwb6]
05/01/2019 09:29 PM <SYMLINKD> PrePackagedDatabase [..\wwb6database]
05/01/2019 09:28 PM <SYMLINKD> ToastNotifications [..\toastnotifications]
05/01/2019 09:28 PM <SYMLINKD> acnComponent [..\..\..\acn_component]
05/01/2019 09:28 PM <SYMLINK> dante_lic_mac [..\dante_mac_fix\WWB_compressed_lic_info_files]
05/01/2019 09:28 PM <SYMLINK> devCategory [..\..\..\devicedescriptionfiles\devCategory]
05/01/2019 09:28 PM <SYMLINK> shared [..\..\frequencycompat\FrequencyCompatibilityCalculator]
05/01/2019 09:28 PM <SYMLINK> shared [..\..\swupdate\src\shared]
05/01/2019 09:28 PM <SYMLINK> skuConversion [..\..\..\skuconversion\src]
谁能解释这种行为?
在 Bash shell 中,所有 symlink 在原始和克隆的 repo 中看起来(和功能)相同:
lrwxrwxrwx 1 ******* 1049089 17 May 1 21:28 ./wwb6/API -> ../swupdate-2/bin
lrwxrwxrwx 1 ******* 1049089 46 May 1 21:28 ./wwb6/dante_lic_mac -> ../dante_mac_fix/WWB_compressed_lic_info_files
lrwxrwxrwx 1 ******* 1049089 19 May 1 21:28 ./wwb6/datastorage/ACN -> ../../acn/Installed
lrwxrwxrwx 1 ******* 1049089 18 May 1 21:28 ./wwb6/datastorage/ACNProxy -> ../../acnproxy/bin
lrwxrwxrwx 1 ******* 1049089 22 May 1 21:28 ./wwb6/datastorage/libdatastorage/acnComponent -> ../../../acn_component
lrwxrwxrwx 1 ******* 1049089 43 May 1 21:28 ./wwb6/datastorage/libdatastorage/devCategory -> ../../../devicedescriptionfiles/devCategory
lrwxrwxrwx 1 ******* 1049089 26 May 1 21:28 ./wwb6/datastorage/libdatastorage/skuConversion -> ../../../skuconversion/src
lrwxrwxrwx 1 ******* 1049089 29 May 1 21:28 ./wwb6/Encryption -> ../protocols/trunk/Encryption
lrwxrwxrwx 1 ******* 1049089 54 May 1 21:28 ./wwb6/FrequencyCompatibility/shared -> ../../frequencycompat/FrequencyCompatibilityCalculator
lrwxrwxrwx 1 ******* 1049089 11 May 1 21:28 ./wwb6/HelpFiles -> ../helpwwb6
lrwxrwxrwx 1 ******* 1049089 33 May 1 21:28 ./wwb6/Installation/Mac/AnalyticsPlugin -> ../../../analyticsinstallerplugin
lrwxrwxrwx 1 ******* 1049089 15 May 1 21:29 ./wwb6/PrePackagedDatabase -> ../wwb6database
lrwxrwxrwx 1 ******* 1049089 25 May 1 21:28 ./wwb6/SWUpdate/shared -> ../../swupdate/src/shared
lrwxrwxrwx 1 ******* 1049089 21 May 1 21:28 ./wwb6/ToastNotifications -> ../toastnotifications
请注意,所有这些都是在 Windows 10 机器上完成的。但是,远程存储库位于 Linux 服务器上。我故意在 Windows 机器上没有管理员权限,因为开发人员也没有这些权限,symlinks 应该为他们工作。
为了让 symlinks 在 Windows 中工作,我做了以下工作:
- 安装时启用符号 link 支持 Git Bash;
将以下条目添加到用户的 .bash_profile:
export MSYS=winsymlinks:nativestrict
export CYGWIN=winsymlinks:nativestrict
在 Git:
中启用符号 link 支持git config --global core.symlinks true
通过使用组策略编辑器将用户添加到“创建符号链接”策略来分配 SeCreateSymbolicLinkPrivilege 权限;
确保允许用户计算本地到本地符号 links:
fsutil behavior query symlinkevaluation
...和 运行 如果不是这种情况,则以管理员身份执行以下命令:
fsutil behavior set symlinkevaluation L2L:1
为了更好的衡量,将 -c core.symlinks=true 切换到 git 克隆命令。
进行所有这些更改后,创建和遍历目录 symlinks 在 Windows 中工作正常,而用户不必在本地管理员组中。直到它们被推送到 Linux 并重新下载。
更新: 在克隆指向子模块内的目录后,将类型从 SYMLINKD 更改为 SYMLINK 的 symlinks。子模块的根目录是在克隆容器项目时创建的,但是直到容器项目(symlinks 所在的位置)的克隆完成后才会下拉内容:
git clone --recursive -c core.symlinks=true ssh://<server>:7999/<repo>
当目标尚不存在时,Windows 似乎不会重新创建目录 symlinks。它改为创建 File symlink 类型的文件。这确实在 Windows 命令行中起作用(就像在 Linux 中一样):
mklink /d symlink ..\<some non-existing directory>\<another non-existing directory>
...工作正常。
我目前的解决方法是简单地删除并恢复它们:
$ find . -type l -delete
$ git checkout .
Updated 14 paths from the index
虽然希望对此进行修复。
这似乎是一个悬而未决的问题,已在 git-for-windows/git issue 1027
中报告Unusable SYMLINK is created.
Even if I create the target directory later, the symlink is unusable from the Windows explorer.
一个更准确的问题,git-for-windows/git issue 1646 应该会在 2.17+ 中修复。
尽管如此,OP Jozef 还是创建了一个新问题:git-for-windows/git issue 2177.
维护者 Johannes Schindelin (github.com/dscho
) 刚刚添加:
Git's internal data model unfortunately has a very Unix-centric view of symbolic links.
In Git for Windows, we work around that by trying to determine the type from the target (if it exists). That heuristic breaks in your case.However, we recently introduced the feature where you can declare the symlink type in the
.gitattributes
: simply add a line to that file (or create that file with this line as contents if it does not yet exist):my_symlink_name symlink=dir
Of course, you will want to add and commit this file.
I was modeling the
.gitattributes
line after this information:mklink /d symlink ..<some non-existing directory><another non-existing directory>
The first column in
.gitattributes
is always a file name or file name pattern
OP 确认:
That works great on a Windows 10 box running Git 2.21 (had to create 5
.gitattributes
files)
It does not work on a Windows 7 box running Git 2.17.
约翰内斯指出 Git for Windows v2.19.1 (Oct 5th 2018)
The type of symlinks to create (directory or file) can now be specified via the
.gitattributes
.
参见 commit 25a7f44。
Symlinks:
On Windows, symbolic links have a type: a "file symlink" must point at a file, and a "directory symlink" must point at a directory. If the type of symlink does not match its target, it doesn't work.
Git does not record the type of symlink in the index or in a tree.
On checkout it'll guess the type, which only works if the target exists at the time the symlink is created. This may often not be the case, for example when the link points at a directory inside a submodule.The
symlink
attribute allows you to explicitly set the type of symlink tofile
ordir
, so Git doesn't have to guess.If you have a set of symlinks that point at other files, you can do:
------------------------ *.gif symlink=file ------------------------
To tell Git that a symlink points at a directory, use:
------------------------ tools_folder symlink=dir ------------------------
The
symlink
attribute is ignored on platforms other than Windows, since they don't distinguish between different types of symlinks.