如果我有一个符号链接的文件或目录,并将其提交到Git仓库中,会发生什么?
我认为它会保留符号链接状态,直到该文件被删除,如果您从旧版本中拉取该文件,则会创建一个普通文件。
当我删除它所引用的文件时,会发生什么?它会提交悬空的链接吗?
如果我有一个符号链接的文件或目录,并将其提交到Git仓库中,会发生什么?
我认为它会保留符号链接状态,直到该文件被删除,如果您从旧版本中拉取该文件,则会创建一个普通文件。
当我删除它所引用的文件时,会发生什么?它会提交悬空的链接吗?
来自Linux符号链接手册(假设您在Linux中):
符号链接是一种特殊类型的文件,其内容是另一个文件的路径名字符串,即链接引用的文件。 (可以使用readlink(2)读取符号链接的内容。)
因此,符号链接就像README.md
或Makefile
一样,是一个文件。Git只需将链接的内容(即它链接到的文件系统对象的路径)存储在“blob”中,就像对于任何其他文件一样。然后,在表示其包含目录的树对象中存储名称、模式和类型(包括它是符号链接的事实)。
当您检出包含链接的树时,它会将该对象作为符号链接还原,而不管目标文件系统对象是否存在。
如果您删除符号链接引用的文件,则不会以任何方式影响Git控制的符号链接。您将具有悬空引用。如果需要,用户可以将其删除或更改为指向有效内容。
core.symlinks
配置选项设为 false,这样在检出时就会将符号链接作为包含链接文本的小普通文本文件处理。 - Jakub Narębskisymlinks = false
干扰它们。请注意,不要改变原文的意思。 - phyatt将符号链接添加到索引中,您可以看到Git如何处理它。 索引类似于预提交。 当提交索引时,您可以使用git checkout
将索引中的所有内容带回工作目录。
那么,当您向索引中添加符号链接时,Git会怎么做呢?
首先,创建一个符号链接:
$ ln -s /path/referenced/by/symlink symlink
Git还不知道这个文件。 git ls-files
命令可以查看你的索引(-s
选项会打印类似于 stat
的输出):
$ git ls-files -s ./symlink
[nothing]
现在,将符号链接添加到索引中。当您向索引中添加文件时,Git会将其内容复制到对象存储中。
$ git add ./symlink
新增了什么内容?
$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0 symlink
哈希是对在对象存储中创建的打包对象的引用。如果您查看存储库根目录中的 .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c
,可以检查此对象。这是 Git 存储在存储库中,以便稍后检出的文件。 如果您检查此文件,您会发现它非常小。它不存储链接文件的内容。要确认这一点,请使用 git cat-file
打印打包存储库对象的内容:
$ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c
/path/referenced/by/symlink
120000
是在 ls-files
输出中列出的模式。 对于普通文件,它会是类似于 100644
的东西。)core.symlinks
配置。来自man git-config
:
因此,在存储库中有一个符号链接时,当您检出时,根据core.symlinks
如果为 false,则将符号链接检出为包含链接文本的小型普通文件。
core.symlinks
配置的值,您可能会得到一个带有完整文件系统路径引用的文本文件或一个适当的符号链接。
无论哪种方式,符号链接引用的路径内容都不会存储在存储库中(当然,除非引用的路径也在存储库中)。
git cat-file -p
查看 git 存储对象的内容,因此如果您的符号链接哈希值为 c6e5580589892eb40407c74a825afaa6c9315787
,则可以执行 git cat-file -p c6e5580589892eb40407c74a825afaa6c9315787
并查看该打包文件的内容,这只是一个符号链接。 - Dmitry Minkovsky ls -l
lrwxrwxrwx 1 admin adm 29 Sep 30 15:28 src/somedir -> /mnt/somedir
git add/commit/push
It remains the same
drwxrwsr-x 2 admin adm 4096 Oct 2 05:54 src/somedir
git checkout
"(man) 移除一个在其检出的提交中不存在的路径时,它没有足够小心地避免跟随符号链接,这已在 Git 2.32(2021 年第二季度)中得到了纠正。
请查看由Matheus Tavares (matheustavares
)于2021年3月18日提交的提交fab78a0,提交462b4e8。
(在2021年3月30日由Junio C Hamano -- gitster
--合并到提交9210c68)
在1d718a5(“不要覆盖未跟踪的符号链接”,2011年2月20日,Git v1.7.5-rc0 -- 合并)中,
结帐
:在删除条目时不要跟随符号链接签名作者:Matheus Tavares
symlink.c
:check_leading_path()开始返回FL_ENOENT
和FL_SYMLINK
的不同代码。unlink_entry()
没有调整这个变化,所以它开始遵循即将被删除的条目的前导路径上的符号链接。因为我们不再尝试取消链接这些路径,所以我们也不会收到remove_or_warn()
的警告。
对于常规文件和符号链接情况,值得怀疑的是,首先是否有用的警告:unlink_entry()
删除了应该不存在于我们正在检出的状态中的已跟踪路径。
如果该路径的前导目录被另一个文件替换,这意味着基本名称已经不存在,因此不需要警告。
当然,我们在路径的dirname处留下了一个常规文件或符号链接,但是这个文件现在要么未跟踪(因此,无需警告),要么在此检出的下一阶段将被跟踪文件替换。
.gitignore
把符号链接视为文件而不是文件夹。 - 0xcaffgit pull
创建文件而不是符号链接,请尝试以管理员身份运行Git客户端。 - axmrnv