协慌网

登录 贡献 社区

Git 如何处理符号链接?

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

我会假设它将它作为符号链接留下,直到文件被删除,然后如果你从旧版本拉回文件它只是创建一个普通文件。

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

答案

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

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

如果删除符号链接引用的文件,则不会以任何方式影响 Git 控制的符号链接。你将有一个悬空参考。如果需要,用户可以删除或更改链接以指向有效的内容。

TL; DR:符号链接引用的数据不存储在存储库中。


您可以通过查看将文件添加到索引时的功能来了解 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 将其内容存储在 Git 对象库中。

$ git add ./symlink

那么,添加了什么?

$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink

哈希是对在 Git 对象库中创建的压缩对象的引用。如果查看存储库根目录中的.git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c ,则可以检查此对象。 这个文件是 Git 存储的,以及在添加和提交符号链接时可以从存储库中检出的内容。如果你检查这个文件,你会发现它非常小。它不存储链接文件的内容。

(注意120000ls-files输出中列出的模式。对于常规文件,它将类似于100644

但是当你从存储库和文件系统中检查出来时,Git 会对这个对象做些什么呢?这取决于core.symlinks配置。来自man git-config

core.symlinks

如果为 false,则将符号链接签出为包含链接文本的小型纯文本。

因此,通过存储库中的符号链接,在结帐时,您可以获得一个文本文件,其中包含对完整文件系统路径的引用,或者是一个正确的符号链接,具体取决于core.symlinks配置的值。

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

“编辑” 注:此帖可能包含过时的信息。请参阅自 1.6.1 以来关于 Git 变化的评论和这个问题

符号链接目录:

重要的是要注意当存在软链接的目录时会发生什么。任何带有更新的 Git pull 都会删除链接并使其成为普通目录。这就是我学到的难点。 这里这里的一些见解

之前

ls -l
 lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir

git add/commit/push

It remains the same

git pull之后发现了一些更新

drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir