如何让Git遵循符号链接?

时间:2008-09-17 18:57:36

标签: git symlink

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

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

14 个答案:

答案 0 :(得分:128)

我要添加的内容是为了将符号链接中的文件导入Git(我没有使用符号链接但是):

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

在Git托管目录中执行此命令。必须在TARGETDIRECTORY加载到SOURCEDIRECTORY之前创建{{1}}。

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

答案 1 :(得分:67)

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

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

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

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

答案 2 :(得分:43)

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

在macOS上(10.13 High Sierra之前)

如果您已经安装了git和Xcode,install hardlink。它是一个微观的tool to create hard links

要创建硬链接,只需:

hln source destination

macOS High Sierra更新

  

Apple文件系统是否支持目录硬链接?

     

Apple File System不支持目录硬链接。在macOS上从HFS +转换为APFS卷格式时,所有目录硬链接都将转换为符号链接或别名。

     

来自APFS FAQ on developer.apple.com

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

在Linux和其他Unix版本

ln命令可以建立硬链接:

ln source destination

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

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

mklink /j "source" "destination"

答案 3 :(得分:39)

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


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

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

即:

  /foo/
  /foo/baz
  /bar/foo --> /foo
  /bar/foo/baz

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

答案 4 :(得分:19)

这是一个pre-commit hook,用这些符号链接的内容替换索引中的符号链接blob。

将其放在.git/hooks/pre-commit中,并将其设为可执行文件:

#!/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,可能还有其他内容。

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

答案 5 :(得分:12)

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

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

答案 6 :(得分:7)

我厌倦了这里的每个解决方案要么已经过时,要么已经过时,所以I made an LD_PRELOAD-based solution(仅限Linux)。

它与Git的内部结合,超越了这是一个符号链接?&#39;函数,允许将符号链接视为其内容。默认情况下,所有指向repo外部的链接都是内联的;请参阅链接了解详情。

答案 7 :(得分:6)

使用Git 2.3.2 +(2015年第1季度),还有另外一个案例,Git将再遵循符号链接:commit e0d201bJunio C Hamano (gitster)(主要Git维护者) )

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

  

因为Git将符号链接跟踪为符号链接,所以在其前导部分中具有符号链接的路径(例如path/to/dir/file,其中path/to/dir是到其他地方的符号链接,无论是内部还是外部工作树)永远不会出现在有效应用的补丁中,除非相同的补丁首先删除符号链接以允许在那里创建目录。

     

检测并拒绝此类补丁。

     

类似地,当输入创建符号链接path/to/dir然后创建文件path/to/dir/file时,我们需要将其标记为错误,而不在文件系统中实际创建path/to/dir符号链接。

     

相反,对于输入中在结果中留下路径(即非删除)的任何补丁,我们通过检查输入中的所有补丁然后检查补丁将创建的结果树的所有前导路径补丁应用程序的目标(索引或工作树)。

     

这样,我们:

     
      
  • 抓住恶作剧或错误,同时添加符号链接path/to/dir和文件path/to/dir/file
  •   
  • 同时允许删除符号link path/to/dir的有效补丁,然后添加文件path/to/dir/file
  •   

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

affected file '%s' is beyond a symbolic link

答案 8 :(得分:4)

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

有没有人有诀窍呢?

[编辑]

好的,我发现Mac OS X上的答案是制作硬链接。除了该API未通过ln公开,因此您必须使用自己的小程序来执行此操作。以下是该计划的链接:

Creating directory hard links in Mac OS X

享受!

答案 9 :(得分:3)

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

brew install bindfs

cd /path/to/git_controlled_dir

mkdir local_copy_dir

bindfs <source_dir> local_copy_dir

其他评论暗示了这一点,但其他答案中并未明确提供。希望这可以节省一些时间。

答案 10 :(得分:1)

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

# Adds the symlink itself
$ git add symlink

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

答案 11 :(得分:0)

从符号链接转换可能很有用。链接到Git文件夹而不是符号链接by a script

答案 12 :(得分:0)

@user252400提出的另一种实现方式是使用bwrap,这是一个小的setuid沙箱,可以在所有主要发行版中找到-通常默认情况下安装。 bwrap允许您绑定装载目录而没有 sudo,并在git或您的shell退出时自动解除绑定。

假设您的开发过程不太疯狂(请参见下面的内容),请在私有名称空间中启动bash并在git目录下绑定外部目录:

bwrap --ro-bind / / \
      --bind {EXTERNAL-DIR} {MOUNTPOINT-IN-GIT-DIR} \
      --dev /dev \
      bash

然后执行您通常会做的所有事情,例如git addgit commit等。完成后,只需退出bash即可。干净简单。

注意事项:为防止沙箱逸出,不允许bwrap执行其他setuid二进制文件。有关更多详细信息,请参见man bwrap

答案 13 :(得分:0)

1.您应该使用硬链接,因为在硬链接中所做的更改 由 git 上演。

2.创建硬链接的语法是ln file1 file2

3.这里file1是硬链接所在文件的位置 您要创建,file2 是硬链接的位置。

4.希望对您有所帮助。