Git如何处理符号链接?

Git如何处理符号链接?,git,version-control,symlink,Git,Version Control,Symlink,如果我有一个作为符号链接的文件或目录,并将其提交到Git存储库,它会发生什么 我假设它将其作为符号链接保留,直到文件被删除,然后如果您从旧版本中提取文件,它只会创建一个普通文件 当我删除它引用的文件时,它会做什么?它只是提交悬挂链接吗?Git只是将链接的内容(即它链接到的文件系统对象的路径)存储在一个“blob”中,就像普通文件一样。然后,它将名称、模式和类型(包括它是符号链接的事实)存储在表示其包含目录的树对象中 签出包含链接的树时,无论目标文件系统对象是否存在,它都会将对象还原为符号链接 如

如果我有一个作为符号链接的文件或目录,并将其提交到Git存储库,它会发生什么

我假设它将其作为符号链接保留,直到文件被删除,然后如果您从旧版本中提取文件,它只会创建一个普通文件


当我删除它引用的文件时,它会做什么?它只是提交悬挂链接吗?

Git只是将链接的内容(即它链接到的文件系统对象的路径)存储在一个“blob”中,就像普通文件一样。然后,它将名称、模式和类型(包括它是符号链接的事实)存储在表示其包含目录的树对象中

签出包含链接的树时,无论目标文件系统对象是否存在,它都会将对象还原为符号链接

如果删除符号链接引用的文件,则不会以任何方式影响Git控制的符号链接。你会有一份悬而未决的推荐信。如果需要,用户可以删除或更改链接以指向有效的内容

编者按:这篇文章可能包含过时的信息。请参阅自1.6.1以来有关Git更改的评论和建议

符号链接目录:

重要的是要注意当有一个目录是软链接时会发生什么。 任何带有更新的Git拉取都会删除链接并使其成为普通目录。这是我通过艰苦的方式学到的。一些见解和建议

示例

以前

git添加/提交/推送

git pull
之后,发现了一些更新


您可以通过查看将文件添加到索引时它所做的操作来了解Git对文件所做的操作。索引类似于预提交。提交索引后,您可以使用
git checkout
将索引中的所有内容带回工作目录。那么,当您向索引添加符号链接时,Git会做什么呢

要找到答案,首先,创建一个符号链接:

$ ln -s /path/referenced/by/symlink symlink
Git还不知道这个文件
git ls文件
允许您检查索引(
-s
打印
stat
-like输出):

现在,通过将符号链接添加到索引,将其添加到Git对象存储。将文件添加到索引时,Git会将其内容复制到对象存储中

$ git add ./symlink
那么,增加了什么

$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink
散列是对在Git对象存储中创建的打包对象的引用。如果查看存储库根目录中的
.git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c
,可以检查此对象这是Git存储在存储库中的文件,您可以稍后签出。如果检查此文件,您会发现它非常小。它不存储链接文件的内容。要确认这一点,请使用
git cat file
打印打包存储库对象的内容:

$ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c
/path/referenced/by/symlink
(注意
120000
ls files
输出中列出的模式。对于常规文件,它类似于
100644
。)

但是,当您将这个对象从存储库签出并签入文件系统时,Git对它做了什么?它取决于
core.symlinks
config。发件人:

core.symlinks

如果为false,则符号链接将作为包含链接文本的小纯文件检出

因此,使用存储库中的符号链接,在签出时,您要么得到一个包含完整文件系统路径引用的文本文件,要么得到一个正确的符号链接,具体取决于
core.symlinks
config的值

无论哪种方式,符号链接引用的数据都不会存储在存储库中。

特殊情况:当“()”删除了它正在签出的提交中不存在的路径时,它没有足够小心地不遵循符号链接,这已通过Git 2.32(2021年第2季度)进行了更正

参见(2021年3月18日)by.
(于2021年3月30日合并)

:删除条目时不遵循符号链接 签字人:Matheus Tavares

在(“不要覆盖未跟踪的符号链接”,2011-02-20,Git v1.7.5-rc0-),
symlink.c
:check_leading_path()开始为
FL\u enoint
FL\u符号链接返回不同的代码
但是它的一个调用者,
unlink_entry()
,没有对此更改进行调整,因此它开始遵循要删除的条目的前导路径上的符号链接。
修复该问题并添加回归测试

由于我们不再尝试取消这些路径的链接,因此也不会从
remove\u或
中得到警告

对于常规文件和符号链接情况,首先警告是否有用值得怀疑:
unlink_entry()
删除我们签出到的状态中不再存在的跟踪路径。
如果路径的前导目录被另一个文件替换,则表示basename已经不存在,因此不需要警告。
当然,我们将在路径的dirname处留下一个常规文件或符号链接,但该文件现在未被跟踪(因此,无需警告),或者在下一个签出阶段将被跟踪文件替换


顺便说一句。如果您在FAT这样的文件系统上,不支持符号链接,并且您的存储库使用它们,您可以将
core.symlinks
configuration变量设置为false,并且符号链接将作为包含链接文本的小纯文本文件签出。@JakubNarębski我以前见过这个。我们的回购协议中有一个文本文件,其中有一行是指向我们使用的库的路径。我想不出它的目的是什么。我现在知道发生了什么。我不太愿意对投票率很高的答案发表评论,但我认为“就像普通文件一样”这句话可能会误导新来者。(编辑时间用完了)它就像普通文件一样,只是因为内容是一团的。关键区别在于,对于普通文件,blob是
$ git ls-files -s ./symlink
[nothing]
$ git add ./symlink
$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink
$ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c
/path/referenced/by/symlink