如果我有一个文件或目录,它是一个符号链接,我将它提交到一个Git存储库,它会发生什么?
我假设在文件被删除之前它将作为一个符号链接离开,然后如果从旧版本中拉回来文件,它只会创建一个普通文件。
当我删除它引用的文件时,它会做什么?它只是提交悬空链接吗?
- .gitignore将symlink视为文件而不是文件夹。
- 显然,这个问题比答案所暗示的要多。例如,我想知道以下几点:如果我在我的存储库中创建了一个sym链接,指向该存储库中的某个大型文件,推送更改,然后将这些更改拉到另一台计算机,会发生什么?大型文件将在两个位置都存储为大型文件,还是将保留sym链接,以便在新机器上,链接文件指向原始大型文件?
- 这是一个旧线程,但此注释可能仍然有用。作为对jviesem的响应,软链接基本上是具有另一个文件名的文件。所以一旦你把它拉到另一台机器上,链接就会被下载,并且在原始的文件系统中有大文件的名称。如果在新计算机上,名称无效,则链接将具有无效的名称。大文件不会下载到新机器上。
- @lasaro,在git repo中避免断开链接的方法是在制作符号链接时始终使用相对路径,根据需要使用../..。
- 添加到git的git add -f filename
- 请注意,在大多数Windows版本中,您需要提升权限才能创建符号链接。如果您在Windows上,并且git pull创建了一个文件而不是symlink,请尝试以管理员身份运行git客户机。
- 关于git在windows;stackoverflow.com/questions/11662868/…上的作用的信息
Git只是将链接的内容(即链接到的文件系统对象的路径)存储在一个"blob"中,就像普通文件一样。然后,它将名称、模式和类型(包括它是一个符号链接的事实)存储在表示其包含目录的树对象中。
当签出包含链接的树时,不管目标文件系统对象是否存在,它都会将对象还原为符号链接。
如果删除symlink引用的文件,它不会以任何方式影响git控制的symlink。你会得到一份悬而未决的推荐信。如果需要,用户可以删除或更改链接以指向有效的内容。
- 顺便说一句,如果您像FAT那样使用不支持符号链接的文件系统,并且您的存储库使用它们,那么您可以将core.symlinks配置变量设置为false,并且符号链接将作为包含链接文本的小型纯文本文件签出。
- @ JakubNar?我以前见过这个。在我们的报告中有一个文本文件,只有一行,这是我们使用的库的路径。不知道它的目的是什么。我现在知道发生了什么。
- 我不愿对高调的回答发表评论,但我认为"就像普通文件一样"的措辞可能会误导新来者。
- (编辑时间用完)这就像一个普通文件,只是内容在一个blob中。关键区别在于,对于普通文件,blob是文件内容,但对于symlink,blob具有链接到的文件的路径名。@ JakubNar?关于"小纯文本文件"的BSKI。您希望它们是小的和文本的,但是当然,一个blob是一个blob,并且可能是巨大的和二进制的。请参阅stackoverflow.com/questions/18411200/…,了解文件被错误地输入为符号链接的时间。
- 确保检查符号链接的全局设置和符号链接的本地设置。如果设置是从Tortisegit或Windows复制过来的,那么您可以让symlinks = false处理它们。
tl;dr:符号链接引用的数据不存储在存储库中。
通过将文件添加到索引中,可以了解Git对文件的作用。索引就像预提交。提交索引后,可以使用git checkout将索引中的所有内容带回工作目录。那么,当您向索引添加符号链接时,Git会做什么?
首先,要找出一个符号链接:
1
| $ ln -s /path/referenced/by/symlink symlink |
Git还不知道这个文件。git ls-files允许您检查索引(-s打印stat样输出):
1 2
| $ git ls-files -s ./symlink
[nothing] |
现在,将符号链接的内容添加到git对象存储区,方法是将其添加到索引中。向索引中添加文件时,Git将其内容存储在Git对象存储中。
那么,添加了什么?
1 2
| $ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0 symlink |
哈希是对在Git对象存储区中创建的压缩对象的引用。如果您查看存储库根目录中的.git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c,就可以检查这个对象。这个文件是Git存储的,当您添加和提交一个symlink时,您可以从存储库中签出它。如果您检查这个文件,您会发现它非常小。它不存储链接文件的内容。
(注:120000是ls-files输出中列出的模式。对于常规文件来说,它类似于100644。
但是,当您将这个对象从存储库签出到文件系统中时,Git会对它做什么呢?这取决于core.symlinks配置。来自man git-config:
core.symlinks
If false, symbolic links are checked out as small plain files that contain the link text.
因此,对于存储库中的符号链接,在签出时,根据core.symlinks配置的值,您可以获得一个引用完整文件系统路径的文本文件,或者一个适当的符号链接。
不管怎样,symlink引用的数据都不会存储在存储库中。
"Editor's" note: This post may contain outdated information. Please see comments and this question regarding changes in Git since 1.6.1.
符号链接目录:
重要的是要注意当有一个软链接目录时会发生什么。任何带有更新的git pull都会删除链接并使其成为普通目录。这是我学到的最难的方法。这里和这里都有一些见解。
例子
以前
1 2
| ls -l
lrwxrwxrwx 1 admin adm 29 Sep 30 15:28 src/somedir -> /mnt/somedir |
git add/commit/push
在发现git pull和一些更新之后
1
| drwxrwsr-x 2 admin adm 4096 Oct 2 05:54 src/somedir |
- 值得注意的是,这些关于符号链接目录的警告不适用于版本化的符号链接。问题的主要边缘案例是人们将部分或所有工作树符号化链接到不同的路径(比如在具有更多磁盘空间的不同分区上),并期望Git通过现有的符号链接签出代码。也就是说,如果您有一个项目包含指向文件或目录的版本化符号链接,正常的符号链接为blob行为将保留符号链接,正确地更改这些符号链接的版本,否则将按预期工作。
- 上面的行为用git 1.6.5.6进行了测试;但是我强烈怀疑在git中版本化的行为已经有相当长的一段时间是正确的。
- 我也一直在努力解决这个问题。似乎是一个bug与git pull出于某种原因转换结果。
- 此行为是在所有版本的Git上都存在,还是已用修复?
- 这种行为现在似乎已经被纠正了,请参见:stackoverflow.com/a/1943656/1334781
- 谢卡尔:你会把你的答案编辑成反映近年来吉特的变化吗?