如果我有一个文件或目录是一个符号链接,并将其提交到Git存储库,会发生什么?
我假设它将其作为一个符号链接,直到文件被删除,然后如果您将文件从旧版本中拉回来,它只会创建一个普通文件。
当我删除它引用的文件时,它会做什么?它只是提交悬空链接吗?
如果我有一个文件或目录是一个符号链接,并将其提交到Git存储库,会发生什么?
我假设它将其作为一个符号链接,直到文件被删除,然后如果您将文件从旧版本中拉回来,它只会创建一个普通文件。
当我删除它引用的文件时,它会做什么?它只是提交悬空链接吗?
当前回答
通过将符号链接添加到索引中,您可以看到Git对符号链接的作用。索引类似于预提交。提交索引后,可以使用gitcheckout将索引中的所有内容带回工作目录。
那么,当您向索引添加符号链接时,Git会做什么?
首先,创建一个符号链接:
$ ln -s /path/referenced/by/symlink symlink
Git还不知道这个文件。gitls文件允许您检查索引(-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存储在存储库中的文件,您可以稍后查看。如果你检查这个文件,你会发现它很小。它不存储链接文件的内容。要确认这一点,请使用gitcat文件打印打包的存储库对象的内容:
$ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c
/path/referenced/by/symlink
(注意120000是ls文件输出中列出的模式。对于常规文件,它类似于100644。)
但是,当您将这个对象从存储库签出并放入文件系统时,Git会如何处理它呢?这取决于core.symlinks配置。从man git配置:
core.symlinks如果为false,符号链接将作为包含链接文本的小纯文件检出。
因此,使用存储库中的符号链接,在签出时,根据core.symlinks配置的值,您可以获得一个包含对完整文件系统路径的引用的文本文件,也可以得到一个适当的符号链接。
无论哪种方式,符号链接引用的路径的内容都不会存储在存储库中(当然,除非引用的路径也在存储库内)。
其他回答
特例:当“git-checkout”(man)删除了一个提交中不存在的路径时,它没有注意到不遵循符号链接,这已经用git 2.32(2021第二季度)进行了更正。
参见Matheus Tavares(matheustavares)的commit fab78a0,commit 462b4e8(2021 3月18日)。(由Junio C Hamano——gitster——于2021 3月30日提交9210c68合并)
签出:删除条目时不遵循符号链接签字人:Matheus Tavares
在1d718a5(“不要覆盖未跟踪的符号链接”,2011-02-20,Git v1.75-rc0-merge),符号链接.c:check_leading_path()开始返回FL_ENOENT和FL_symlink的不同代码。但它的一个调用方unlink_entry()没有针对此更改进行调整,因此它开始在要删除的条目的前导路径上遵循符号链接。修复该问题并添加回归测试。因为我们不再尝试取消链接这些路径,所以我们也不会从remove_or_warn()得到警告。对于常规文件和符号链接的情况,警告一开始是否有用是值得怀疑的:unlink_entry()删除了不应再出现在我们签出的状态中的跟踪路径。如果路径的前导目录被另一个文件替换,这意味着基本名称已经不存在,因此不需要警告。当然,我们将在路径的目录名处留下一个常规文件或符号链接,但该文件要么现在未被跟踪(因此,无需警告),要么在下一阶段签出时被跟踪的文件替换
从linux symlink手册(假设您在linux中):
符号链接是一种特殊类型的文件,其内容是一个字符串,该字符串是链接所指的另一个文件的路径名。(可以使用readlink(2)读取符号链接的内容。)
因此,符号链接是另一个文件,就像README.md或Makefile一样。Git只是将链接的内容(即它链接到的文件系统对象的前面提到的路径)存储在一个“blob”中,就像其他文件一样。然后,它将名称、模式和类型(包括它是符号链接的事实)存储在表示其包含目录的树对象中。
签出包含链接的树时,无论目标文件系统对象是否存在,它都会将对象恢复为符号链接。
如果删除符号链接引用的文件,则不会以任何方式影响Git控制的符号链接。您将有一个悬挂的引用。如果需要,用户可以删除或更改链接以指向有效的内容。
“编辑”注意:此帖子可能包含过时的信息。请参阅有关Git自1.6.1以来的更改的评论和此问题。
符号链接目录:
重要的是要注意当有一个目录是软链接时会发生什么。任何带有更新的Git拉取都会删除链接并使其成为普通目录。这是我从中学到的。这里和这里的一些见解。
实例
之前
ls -l
lrwxrwxrwx 1 admin adm 29 Sep 30 15:28 src/somedir -> /mnt/somedir
git添加/提交/推送
It remains the same
git pull后,发现一些更新
drwxrwsr-x 2 admin adm 4096 Oct 2 05:54 src/somedir
通过将符号链接添加到索引中,您可以看到Git对符号链接的作用。索引类似于预提交。提交索引后,可以使用gitcheckout将索引中的所有内容带回工作目录。
那么,当您向索引添加符号链接时,Git会做什么?
首先,创建一个符号链接:
$ ln -s /path/referenced/by/symlink symlink
Git还不知道这个文件。gitls文件允许您检查索引(-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存储在存储库中的文件,您可以稍后查看。如果你检查这个文件,你会发现它很小。它不存储链接文件的内容。要确认这一点,请使用gitcat文件打印打包的存储库对象的内容:
$ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c
/path/referenced/by/symlink
(注意120000是ls文件输出中列出的模式。对于常规文件,它类似于100644。)
但是,当您将这个对象从存储库签出并放入文件系统时,Git会如何处理它呢?这取决于core.symlinks配置。从man git配置:
core.symlinks如果为false,符号链接将作为包含链接文本的小纯文件检出。
因此,使用存储库中的符号链接,在签出时,根据core.symlinks配置的值,您可以获得一个包含对完整文件系统路径的引用的文本文件,也可以得到一个适当的符号链接。
无论哪种方式,符号链接引用的路径的内容都不会存储在存储库中(当然,除非引用的路径也在存储库内)。