250

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

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

4

14 回答 14

164

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

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

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

它在 Linux 上运行良好,但在 OS X 上不行!这个技巧也帮助了我使用 Subversion。我用它来包含来自 Dropbox 帐户的文件,网页设计师在那里做他/她的工作。

如果要使此绑定永久化,请将以下行添加到/etc/fstab

/sourcedir /targetdir none bind
于 2010-01-16T23:31:39.860 回答
81

为什么不反过来创建符号链接呢?这意味着不是从 Git 存储库链接到应用程序目录,而是以相反的方式链接。

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

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

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

于 2011-04-26T07:33:43.017 回答
55

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

在 macOS 上(10.13 High Sierra 之前)

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

要创建硬链接,只需:

hln source destination

macOS High Sierra 更新

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

Apple 文件系统不支持目录硬链接。当您在 macOS 上从 HFS+ 转换为 APFS 宗卷格式时,所有目录硬链接都会转换为符号链接或别名。

来自developer.apple.com 上的 APFS 常见问题解答

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

在 Linux 和其他 Unix 风格上

ln命令可以建立硬链接:

ln source destination

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

使用mklink在 Windows 上创建联结:

mklink /j "source" "destination"
于 2014-06-18T00:38:15.727 回答
45

注意:根据 Git 1.6.1 以来的评论,此建议现已过时。Git 曾经以这种方式行事,现在不再如此。


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

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

IE:

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

通过做

 git add /bar/foo/baz

当我尝试它时,它似乎有效。然而,这种行为当时是我不想要的,所以我不能给你更多信息。

于 2008-09-17T19:03:00.607 回答
29

这是一个预提交挂钩,它用这些符号链接的内容替换索引中的符号链接 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 标准。

这段代码中可能有一些错误/错误,即使它经过了一些测试。

于 2013-09-09T06:30:49.530 回答
19

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

brew install bindfs

cd /path/to/git_controlled_dir

mkdir local_copy_dir

bindfs </full/path/to/source_dir> </full/path/to/local_copy_dir>

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

于 2019-01-10T02:14:59.473 回答
16

我厌倦了这里的每个解决方案都过时或需要 root,所以我制作了一个基于 LD_PRELOAD 的解决方案(仅限 Linux)。

它连接到 Git 的内部,覆盖“这是一个符号链接吗?” 函数,允许将符号链接视为其内容。默认情况下,所有指向 repo 外部的链接都是内联的;有关详细信息,请参阅链接。

于 2018-03-06T19:27:37.500 回答
14

很长一段时间以来,我曾经在符号链接之外添加文件。这过去工作得很好,没有做任何特殊安排。由于我更新到 Git 1.6.1,这不再起作用。

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

于 2009-01-01T20:31:34.163 回答
7

对于 Git 2.3.2+(2015 年第一季度),还有另一种情况是 Git不再遵循符号链接:参见Junio C Hamano ( )(主要 Git 维护者)的commit e0d201bgitster

apply:不要触摸超出符号链接的文件

因为 Git 将符号链接作为符号链接进行跟踪,所以在其前导部分具有符号链接的路径(例如path/to/dir/filepath/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
于 2015-03-04T06:39:40.157 回答
4

嗯,mount --bind似乎对达尔文不起作用。

有没有人有这样的技巧?

[编辑]

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

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

享受!

于 2010-02-18T22:21:45.053 回答
1

@user252400建议的另一种实现是使用bwrap,一个可以在所有主要发行版中找到的小型 setuid 沙箱 - 通常默认安装。bwrap允许您绑定挂载目录而不 sudo绑定它们,并在 git 或您的 shell 退出时自动取消绑定它们。

假设你的开发过程不是太疯狂(见下文),在私有命名空间中启动 bash 并将外部目录绑定到 git 目录下:

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

然后做你通常会做的所有事情,比如git add,git commit等等。完成后,只需退出 bash。干净简单。

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

于 2020-08-29T09:31:19.793 回答
1

1.您应该使用硬链接,因为硬链接中所做的更改是由 git 暂存的。

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

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

4.我希望这会有所帮助。

于 2021-05-08T06:22:58.477 回答
0

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

# Adds the symlink itself
$ git add symlink

# Follows symlink and adds the denoted directory's contents
$ git add symlink/
于 2009-07-29T12:29:46.250 回答
0

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

于 2012-08-19T19:37:54.463 回答