当前位置:首页> 正文

如何让Git遵循符号链接?

如何让Git遵循符号链接?

How can I get Git to follow symlinks?

我最好是一个shell脚本用副本替换符号链接,还是有另一种方式告诉Git遵循符号链接?

PS:我知道它不是很安全,但我只想在一些特定情况下这样做。


我做了什么来添加到符号链接中的文件到Git(我没有使用符号链接但是):

1
sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

在Git托管目录中执行此命令。必须在SOURCEDIRECTORY安装到TARGETDIRECTORY之前创建TARGETDIRECTORY

它适用于Linux,但不适用于OSX!这个技巧也帮助了Subversion。我使用它来包含来自Dropbox帐户的文件,其中webdesigner执行他/她的东西。


为什么不以相反的方式创建符号链接?意思是代替从Git存储库到应用程序目录的链接,只需链接另一种方式。

例如,假设我正在设置安装在~/application中的需要配置文件config.conf的应用程序:

  • 我将config.conf添加到我的Git存储库,例如,在~/repos/application/config.conf
  • 然后我通过运行ln -s ~/repos/application/config.conf~/application创建一个符号链接。

这种方法可能并不总是有效,但到目前为止它对我来说效果很好。


请改用硬链接。这与软(符号)链接不同。所有程序(包括git)都会将该文件视为常规文件。请注意,可以通过更改源或目标来修改内容。

在macOS上(10.13 High Sierra之前)

如果您已经安装了git和Xcode,请安装hardlink。它是创建硬链接的微观工具。

要创建硬链接,只需:

1
hln source destination

macOS High Sierra更新

Does Apple File System support directory hard links?

Directory hard links are not supported by Apple File System. All directory hard links are converted to symbolic links or aliases when you convert from HFS+ to APFS volume formats on macOS.

From APFS FAQ on developer.apple.com

关注https://github.com/selkhateeb/hardlink/issues/31以了解未来的替代方案。

在Linux和其他Unix风格

ln命令可以生成硬链接:

1
ln source destination

在Windows上(Vista,7,8,...)

有人建议在Windows上使用mklink创建一个联结,但我还没有尝试过:

1
mklink /j"source""destination"

注意:自Git 1.6.1起,此建议现已根据评论过时。 Git曾经以这种方式行事,而不再这样做。

Git默认尝试存储符号链接而不是跟随它们(对于紧凑性,它通常是人们想要的)。

但是,当符号链接是目录时,我偶然设法让它在符号链接之外添加文件。

即:

1
2
3
4
  /foo/
  /foo/baz
  /bar/foo --> /foo
  /bar/foo/baz

通过做

1
 git add /bar/foo/baz

当我尝试它时,它似乎工作。然而,当时我的这种行为是不受欢迎的,所以我无法向你提供除此之外的信息。


这是一个预提交钩子,用这些符号链接的内容替换索引中的符号链接blob。

把它放在.git/hooks/pre-commit中,并使其可执行:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh
# (replace"find ." with"find ./<path>" below, to work with only specific paths)

# (these lines are really all one line, on multiple lines for clarity)
# ...find symlinks which do not dereference to directories...
find . -type l -exec test '!' -d {} ';' -print -exec sh -c \
# ...remove the symlink blob, and add the content diff, to the index/cache
    'git rm --cached"$1"; diff -au /dev/null"$1" | git apply --cached -p1 -' \
# ...and call out to"sh".
   "process_links_to_nondir" {} ';'

# the end

笔记

我们尽可能使用符合POSIX标准的功能;但是,diff -a不符合POSIX,可能还有其他内容。

此代码中可能存在一些错误/错误,即使它已经过一些测试。


我过去常常在符号链接之外添加文件已有一段时间了。过去工作得很好,没有做任何特殊安排。自从我更新到Git 1.6.1后,这不再适用了。

您可以切换到Git 1.6.0来完成这项工作。我希望Git的未来版本会有一个git-add的标志,允许它再次遵循符号链接。


我厌倦了这里的每个解决方案要么已经过时,要么需要root,所以我做了一个基于LD_PRELOAD的解决方案(仅限Linux)。

它与Git的内部结构挂钩,覆盖了'这是一个符号链接吗?'函数,允许将符号链接视为其内容。默认情况下,所有指向repo外部的链接都是内联的;请参阅链接了解详情。


使用Git 2.3.2 +(2015年第1季度),还有另一个案例,Git将不再遵循符号链接:请参阅Junio C Hamano(gitster)(主要的Git维护者)提交e0d201b

apply:请勿触摸符号链接之外的文件

Because Git tracks symbolic links as symbolic links, a path that has a symbolic link in its leading part (e.g. path/to/dir/file, where path/to/dir is a symbolic link to somewhere else, be it inside or outside the working tree) can never appear in a patch that validly applies, unless the same patch first removes the symbolic link to allow a directory to be created there.

Detect and reject such a patch.

Similarly, when an input creates a symbolic link path/to/dir and then creates a file path/to/dir/file, we need to flag it as an error without actually creating path/to/dir symbolic link in the filesystem.

Instead, for any patch in the input that leaves a path (i.e. a non deletion) in the result, we check all leading paths against the resulting tree that the patch would create by inspecting all the patches in the input and then the target of patch application (either the index or the working tree).

This way, we:

  • catch a mischief or a mistake to add a symbolic link path/to/dir and a file path/to/dir/file at the same time,
  • while allowing a valid patch that removes a symbolic link path/to/dir and then adds a file path/to/dir/file.

这意味着,在这种情况下,错误消息将不是像"%s: patch does not apply"那样的通用消息,而是更具体的消息:

1
affected file '%s' is beyond a symbolic link

MacOS(我有Mojave / 10.14,git版本2.7.1)上,使用bindfs

<5233>

cd /path/to/git_controlled_dir

mkdir local_copy_dir

bindfslocal_copy_dir

它已被其他评论暗示,但在其他答案中没有明确提供。希望这能节省一些时间。


嗯,mount --bind似乎不适用于达尔文。

有人有诀窍吗?

[编辑]

好的,我发现MacOSX的答案是建立一个硬链接。除非该API未通过ln公开,因此您必须使用自己的小程序来执行此操作。这是该程序的链接:

在Mac OS X中创建目录硬链接

请享用!


我正在使用Git 1.5.4.3,如果它有一个尾部斜杠,它会跟随传递的符号链接。例如。

1
2
3
4
5
# Adds the symlink itself
$ git add symlink

# Follows symlink and adds the denoted directory's contents
$ git add symlink/


从符号链接转换可能很有用。通过脚本链接Git文件夹而不是符号链接。


展开全文阅读

相关内容