从Git推入和拉出后,目录符号链接更改为文件符号链接

时间:2019-05-02 04:55:02

标签: windows git symlink

由于某种原因,在Windows上的Git存储库中创建的目录符号链接一旦推送到Git并重新克隆,便会变为文件符号链接。这将导致“目录名称无效”错误。

但是,仅当符号链接在其路径中包含多个子目录时,才会发生这种情况。如果只有一个子目录,它们将继续正常工作。而且,它们在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]

将符号链接推送到远程Git服务器并重新克隆存储库后,那些指向具有列出的多个子目录的路径的符号链接被更改为文件符号链接:

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中,所有符号链接在原始和克隆存储库中看起来都是相同的(和功能):

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计算机上没有管理员权限,因为开发人员也没有这些权限,符号链接也应适用于他们。

要使符号链接在Windows中工作,我做了以下工作:

  • 在安装Git Bash时启用符号链接支持;
  • 将以下条目添加到用户的.bash_profile中:

      

    export MSYS=winsymlinks:nativestrict

         

    export CYGWIN=winsymlinks:nativestrict

  • 在Git中启用了符号链接支持:

      

    git config --global core.symlinks true

  • 通过使用组策略编辑器将用户添加到“创建符号链接”策略中,来分配SeCreateSymbolicLinkPrivilege权限;

  • 确保允许用户评估“本地到本地”符号链接:

      

    fsutil behavior query symlinkevaluation

    ...,如果不是这种情况,请以管理员身份运行以下命令:

      

    fsutil behavior set symlinkevaluation L2L:1

  • 出于良好的考虑,请包括-c core.symlinks = true切换至git clone命令。

进行所有这些更改之后,在Windows中创建和遍历目录符号链接可以很好地进行,而无需将该用户置于Local Admin组中。直到将它们推送到Linux并重新下载。

更新: 克隆后将类型从SYMLINKD更改为SYMLINK的符号链接指向子模块内的目录。克隆容器项目时会创建子模块的根目录,但是直到容器项目(符号链接所在的位置)的克隆完成后,内容才被下拉:

git clone --recursive -c core.symlinks=true ssh://<server>:7999/<repo>

当目标尚不存在时,Windows似乎不会重新创建目录符号链接。它改为创建文件符号链接类型的文件。不过,这确实可以从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

但是更愿意对此进行修复。

1 个答案:

答案 0 :(得分:2)

这似乎是一个悬而未决的问题,已在git-for-windows/git issue 1027

中报告
  

创建了不可用的SYMLINK。
  即使稍后创建目标目录,该符号链接也无法在Windows资源管理器中使用。

更准确的问题,git-for-windows/git issue 1646应该在2.17+中得到解决。
尽管如此,OP Jozef还是创造了一个新问题:git-for-windows/git issue 2177

维护者Johannes Schindelin(github.com/dscho)刚刚添加:

  

不幸的是,Git的内部数据模型具有非常以Unix为中心的符号链接视图。
  在Windows版Git中,我们通过尝试从目标中确定类型(如果存在)来解决该问题。这种启发式方法会破坏您的情况。

     

但是,我们最近引入了可以在.gitattributes中声明符号链接类型的功能:只需在该文件中添加一行(或者如果该文件尚不存在,则以该行作为内容创建该文件):

my_symlink_name symlink=dir
     

当然,您将要添加并提交此文件。

     

我正在根据以下信息对.gitattributes行进行建模:

mklink /d symlink ..<some non-existing directory><another non-existing directory>
     

第一列in .gitattributes始终是文件名或文件名模式

OP确认:

  

这在运行Git 2.21(必须创建5个.gitattributes文件)的Windows 10盒子上效果很好
  在运行Git 2.17的Windows 7机器上,它不起作用。

约翰尼斯指出Git for Windows v2.19.1 (Oct 5th 2018)

  

要创建的符号链接的类型(目录或文件)可以为now be specified via the .gitattributes

请参见commit 25a7f44

  

符号链接:

     

在Windows上,符号链接的类型为:“文件符号链接”必须指向   文件,并且“目录符号链接”必须指向目录。如果   符号链接的类型与目标不符,无法正常工作。

     

Git不在索引或树中记录符号链接的类型。
  结帐时会猜测类型,仅当目标存在时才起作用   在创建符号链接时。情况往往并非如此,   例如,当链接指向子模块内的目录时。

     

symlink属性可让您显式设置符号链接的类型   到filedir,因此Git不必猜测。

     

如果您有一组指向其他文件的符号链接,则可以执行以下操作:

------------------------
*.gif   symlink=file
------------------------
     

要告诉Git符号链接指向目录,请使用:

------------------------
tools_folder    symlink=dir
------------------------
     

在Windows以外的平台上,symlink属性将被忽略,   因为它们无法区分不同类型的符号链接。