Git将目录符号链接创建为文件

4

给定一个仓库中的两个普通文件夹:

drwx------ dir_a/
drwx------ dir_b/

我将dir_b转换为一个指向dir_a的相对符号链接(即rm -rf dir_bln -s dir_a dir_b),现在它看起来像这样:

drwx------ dir_a/
lrwxrwxrwx dir_b -> dir_a/

在提交、推送和拉取到另一台机器上后,我发现dir_b显示为普通文件而不是文件夹的符号链接。

$ ls -al
drwx------ dir_a/
-rw------- dir_b

尝试使用git checkout dir_b 移除dir_b并将其还原,但它仍然被重新创建为文件,而不是文件夹符号链接。文件系统是支持符号链接的ext4。事实上,在同一分区上进行全新的git clone确实会像预期的那样创建dir_b作为符号链接。
如果可能有影响,我会提到实际名称dir_b以一个点开头(例如.dir_b)。 git clone 正常工作,所以我可以将其用作解决方法,但我想知道发生了什么以及还原符号链接文件夹的正确方法,因为显然git checkout symlinked_folder 不会像在原始repo中那样重新创建文件夹。

如果 git clone 正常工作且您没有在出现问题的存储库中禁用符号链接,那么这似乎是一个明显的错误。如果您已经禁用了符号链接(通过将 core.symlinks 设置为 false),请重新启用它们。 - torek
@torek:git config -l | grep symlinks 返回 core.symlinks=false - ccpizza
1
那么问题就在这里了。将其配置回“true”,所有东西都应该能正常工作。请注意,“git config”文档声称(引用):“默认值为true,除非在创建存储库时git-clone(1)或git-init(1)会探测并设置core.symlinks为false。” - torek
执行了 git config --global core.symlinks true 命令,并在没有 --global 的情况下重复了一次,只针对该仓库进行设置,然后 git checkout dir_b 就正常工作了。现在我意识到发生了什么:最初克隆到了手机的 SD 卡上,而该卡是 FAT 格式,所以符号链接被设置为 false,然后我将仓库移动到了内部的 EXT4 分区。请在答案中添加您的评论,以便我可以接受它。 - ccpizza
1
顺便提一下,你根本不应该使用 --global 来设置它,因为它是针对每个仓库的(就像 core.barecore.repositoryformatversion 一样)。 - torek
1个回答

7
在这种情况下的修复方法是运行以下命令:
git config core.symlinks true

(It may be wise to check for other non-default settings, especially if the SD-card repository was created by a different OS.)
(如果SD卡存储库是由不同的操作系统创建的,特别是检查其他非默认设置可能是明智的。)
As discussed in comments, the key element here was that the repository was originally created on a non-symlink-supporting file system, and then moved (copied manually) to a symlink-supporting file system. 在评论中讨论过,关键要素是该存储库最初是在不支持符号链接的文件系统上创建的,然后手动移动(复制)到支持符号链接的文件系统上。 git config文档,在描述core.symlinks部分中说:
如果为false,则将符号链接检出为包含链接文本的小型普通文件。 git-update-index(1)git-add(1)不会更改记录的类型为常规文件。在不支持符号链接的文件系统(如FAT)上非常有用。
默认值为true,除了当创建存储库时适当时,git-clone(1)git-init(1)将探测并设置core.symlinks false。
一般来说,当移动存储库时,最好使用git clone命令,因为新的克隆将探测新文件系统的设置,这样会更安全一些。Git在自动检测其他更改方面相当不错(例如,索引编码了工作树路径),而且大多数这些设置是特定于操作系统而不是特定于文件系统的。但是,如果您跨越不同的操作系统引导(或在虚拟机监视器下运行它们)并共享某些介质,则这些附加的core.*设置可能会引起问题。例如,查看core.fileModecore.protectNTFS

谢谢你提供关于filemode的提示!我确实注意到了从另一个克隆中拉取时可执行标志未被设置的不一致性,现在我知道原因了。顺便说一下,在我的.git/config文件中,它被列为core.filemode(全小写),但我认为配置选项可能是不区分大小写的。 - ccpizza
1
是的,在进行比较之前,它们都被转换为小写字母。(在某些语言中,这种转换方向非常关键,尽管德语最近要求一个大写的ß; 参见https://en.wikipedia.org/wiki/Capital_%E1%BA%9E。同时,所有Git内置的配置变量都是ASCII编码的,因此大写字母实际上已经足够了...) - torek

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