Git - 如何处理符号链接

84

如何在 Git 中正确处理符号链接?

我有以下结构:

Vendors
  Module A
  Module B
  Module C
App
 Code
   Modules
     Core Module 1
     Core Module 2
     Module A (symlinked to vendors)
     Module B (symlinked to vendors)
     Module C (symlinked to vendors)

有一个主要的应用程序目录,其中包含应用程序中所有核心代码。此外,有一个供应商目录,其中包含会被符号链接到主应用程序目录中并因此集成的模块。

重要的是,供应商目录和主应用程序目录都在同一个存储库中进行版本控制。

因此,我应该让 Git 继续存储符号链接,还是找一种方式让它忽略符号链接?


嗯,我把它变成了相对路径,但在GitHub上不起作用:( 你能帮我吗?https://github.com/lingohub/Example-Resource-Files/blob/master/AngularJS/example.en.json - Betty St
你的请求是完全合理的,而且你已经揭示了GitHub的封装违规问题。符号链接是存储层的一个细节——我想在不同的卷上物理地保留各种文件夹?GitHub 只应关注文件系统导航层:如果某个东西看起来和行为像子目录一样,那么就像一个子目录一样对待它(鸭子类型),而不是通过窥探更低层次来查看它是否是指向另一个卷的符号链接。 - Canuck
3个回答

153

只要所有开发人员使用的操作系统支持符号链接,Git 就可以很好地处理它们。由于您依赖于这些符号链接,我将假设您的开发环境都支持符号链接。

要决定是否应将某个内容(包括符号链接或其他)包含在 git 存储库中,请考虑以下内容:

  • 它是否是存储库中某个工具或其他进程生成的文件?如果是,则最好忽略它,并让每个用户生成文件,以便他们始终拥有最新版本。
  • 该文件是否特定于某个用户的开发环境或在所有环境中使用?如果它是特定于特定用户环境的奇怪文件,例如用于忽略 Emacs 备份文件的配置,则不应在存储库中。如果所有开发人员都需要它和/或需要在生产中构建应用程序的东西,则它应该放入存储库中。

在您的情况下,似乎这些符号链接不是生成的,并且在所有环境中都需要它们,因此将它们放入存储库中应该没问题。

但是,在创建它们时,请确保将它们创建为相对符号链接而不是绝对符号链接,以便它们可以在克隆存储库的任何位置工作。这样做的最简单方法是更改目录进入“Modules”目录,然后从那里创建符号链接:

cd App/Code/Modules
ln -s "../../../Vendors/Module A" "Module A"

嗯,我把它变成了相对路径,但在GitHub上不起作用:( 你能帮我吗?https://github.com/lingohub/Example-Resource-Files/blob/master/AngularJS/example.en.json - Betty St
这是否意味着,如果我对Vendors/Module A进行任何更改,并将其推送到Git,则Git会自动更新App/Code/Modules/Module A的内容? - HasnainMamdani
10
使用 -r 选项创建相对符号链接:ln -r -s /path/to/target - Fred Schoen
4
确保你的git配置中没有symlinks = false。如果你从Windows或使用TortiseGit复制了一个仓库,就可能会出现这种情况。 - phyatt

14

Git存储符号链接,就像版本控制中的任何其他文件一样。对于符号链接,它只会存储有关所链接到路径和文件类型(即符号链接而不是常规文件)的信息,而不是链接下的目录内容。

因此,在您的情况下,在git版本控制下存储符号链接不会造成任何损害。

您还需要注意一个有关符号链接的问题,即git只会在新克隆的副本中重建符号链接,而不是它所指向的文件或目录。在使用绝对路径时,可能会出现符号链接路径不存在的情况。


1
有没有办法添加符号链接目录中的文件? - kraftydevil
4
只有当符号链接目录的目标目录本身受到git版本控制时,git才允许您将文件添加到该目录下。否则,git不会(也不应该)对符号链接目录的内容进行版本控制。如果您试图在主git存储库目录之外的符号链接目录下对文件进行版本控制,则说明您正在做错误的事情。您可能需要查看git submodules(或更好的git subtrees)。 - Tuxdude
我正在将我的Jenkins实例放入源代码控制下。我想保留每个作业的lastSuccessful构建内容。稍后我会查看它以获取更多解释。 - kraftydevil
@Tuxdude 请查看https://dev59.com/bmUp5IYBdhLWcg3wLVKn#37426014(由于字符太多,无法作为评论发布)。 - ioCron

1

@Tuxdude,我不同意你的论点:“……那你就做错了”。比如,如果你需要将媒体文件夹放在Web服务器或甚至NFS的不同驱动器上,那么必须将其放在版本控制之外。因此,符号链接的媒体文件夹内部的内容无法通过版本控制进行访问,如你所解释的那样。但这是必须这样做的一种情况。而且它真的很痛苦。我的情况更加复杂(我不想详细说明),实际上我正在寻找的是将符号链接文件夹的子文件夹添加到版本控制中,但不包括其中的内容,但我需要一个选项,在Git中可以忽略子文件夹本身的任何更改。例如,基本结构:

  • app/media/bla
  • app/media/blubb

我需要这些文件夹在Git版本控制中,但不包含其中的内容。

在Web服务器上(相同的版本控制)这些文件夹看起来像这样(符号链接):

  • app/media/bla => 其他地方
  • app/media/blubb => 再次某个其他地方

开发人员在他们的本地环境中应该只保留原始版本结构(没有符号链接)。但是Web服务器具有到不同NFS系统的符号链接。

如果有人有解决方法,我会非常感激,因为我还没有找到任何解决方法。

目前,我唯一的方法是使用一个构建器来创建正确/不同的本地环境和服务器结构,并通过gitignore完全忽略媒体子文件夹。但这有时可能很棘手/难以维护。


1
这是一个常见问题,正如我之前所说,它与版本控制无关。其中一种解决方案是编写一个初始化脚本,根据目标环境设置符号链接。应该在 git clone 后立即运行初始化脚本来引导您的设置。将初始化脚本添加到 git 的版本控制中。顺便提一下,git 不会对空目录进行版本控制,只会对文件进行版本控制,并知道路径。这将用于在运行任何 git 命令时重建目录结构。 - Tuxdude
谢谢您的解释,这实际上几乎与我在当前设置中所做的完全相同。我只是想可能有一种更“舒适”的方式。如果git在gitignore规则中有某种区分普通文件和符号链接的标志等,则某些事情将至少变得更容易。这就是为什么我认为它与“版本控制”有关,它可能被实现为一个“新功能”/通过一个功能请求,当涉及到更复杂的场景时,实际上还有一些其他的东西我也在git中缺失。 - ioCron
1
我可以解释为什么Git会以这种方式处理符号链接。对于Git而言,符号链接等同于内容表示符号链接目标的文本文件。当您将符号链接添加到Git时,此目标会作为Git历史记录的一部分被加入。 - Tuxdude

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接