如何让 Git 遵循符号链接?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/86402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 05:47:09  来源:igfitidea点击:

How can I get Git to follow symlinks?

gitsymlink

提问by Matt

Is my best be going to be a shell script which replaces symlinks with copies, or is there another way of telling Git to follow symlinks?

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

PS: I know it's not very secure, but I only want to do it in a few specific cases.

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

采纳答案by Kent Fredric

NOTE:This advice is now out-dated as per comment since Git 1.6.1. Git used to behave this way, and no longer does.

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



Git by default attempts to store symlinks instead of following them (for compactness, and it's generally what people want).

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

However, I accidentally managed to get it to add files beyond the symlink when the symlink is a directory.

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

I.e.:

IE:

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

by doing

通过做

 git add /bar/foo/baz

it appeared to work when I tried it. That behavior was however unwanted by me at the time, so I can't give you information beyond that.

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

回答by user252400

What I did to add to get the files within a symlink into Git (I didn't use a symlink but):

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

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

Do this command in the Git-managed directory. TARGETDIRECTORYhas to be created before the SOURCEDIRECTORYis mounted into it.

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

It works fine on Linux, but not on OS X! That trick helped me with Subversion too. I use it to include files from an Dropbox account, where a webdesigner does his/her stuff.

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

回答by spier

Why not create symlinks the other way around? Meaning instead of linking from the Git repository to the application directory, just link the other way around.

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

For example, let's say I am setting up an application installed in ~/applicationthat needs a configuration file config.conf:

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

  • I add config.confto my Git repository, for example, at ~/repos/application/config.conf.
  • Then I create a symlink from ~/applicationby running ln -s ~/repos/application/config.conf.
  • 我添加config.conf到我的 Git 存储库,例如,在~/repos/application/config.conf.
  • 然后我~/application通过运行 创建一个符号链接ln -s ~/repos/application/config.conf

This approach might not always work, but it worked well for me so far.

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

回答by fregante

Use hard links instead. This differs from a soft (symbolic) link. All programs, including gitwill treat the file as a regular file. Note that the contents can be modified by changing eitherthe source or the destination.

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

On macOS (before 10.13 High Sierra)

在 macOS 上(10.13 High Sierra 之前)

If you already have git and Xcode installed, install hardlink. It's a microscopic tool to create hard links.

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

To create the hard link, simply:

要创建硬链接,只需:

hln source destination

macOS High Sierra update

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

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

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

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

Follow https://github.com/selkhateeb/hardlink/issues/31for future alternatives.

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

On Linux and other Unix flavors

在 Linux 和其他 Unix 版本上

The lncommand can make hard links:

ln命令可以建立硬链接:

ln source destination

On Windows (Vista, 7, 8, …)

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

Someone suggested to use mklinkcreate a junction on Windows, but I haven't tried it:

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

mklink /j "source" "destination"

回答by Abbafei

This is a pre-commit hookwhich replaces the symlink blobs in the index, with the content of those symlinks.

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

Put this in .git/hooks/pre-commit, and make it executable:

将其放入.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 ""; diff -au /dev/null "" | git apply --cached -p1 -' \
# ...and call out to "sh".
    "process_links_to_nondir" {} ';'

# the end

Notes

笔记

We use POSIX compliant functionality as much as possible; however, diff -ais not POSIX compliant, possibly among other things.

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

There may be some mistakes/errors in this code, even though it was tested somewhat.

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

回答by ijoseph

On MacOS(I have Mojave/ 10.14, gitversion 2.7.1), use bindfs.

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

brew install bindfs

brew install bindfs

cd /path/to/git_controlled_dir

cd /path/to/git_controlled_dir

mkdir local_copy_dir

mkdir local_copy_dir

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

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

It's been hinted by other comments, but not clearly provided in other answers. Hopefully this saves someone some time.

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

回答by Erik Schnetter

I used to add files beyond symlinks for quite some time now. This used to work just fine, without making any special arrangements. Since I updated to Git 1.6.1, this does not work any more.

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

You may be able to switch to Git 1.6.0 to make this work. I hope that a future version of Git will have a flag to git-addallowing it to follow symlinks again.

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

回答by Alcaro

I got tired of every solution in here either being outdated or requiring root, so I made an LD_PRELOAD-based solution(Linux only).

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

It hooks into Git's internals, overriding the 'is this a symlink?' function, allowing symlinks to be treated as their contents. By default, all links to outside the repo are inlined; see the link for details.

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

回答by VonC

With Git 2.3.2+ (Q1 2015), there is one other case where Git will notfollow symlink anymore: see commit e0d201bby Junio C Hamano (gitster)(main Git maintainer)

使用Git 2.3.2+(Q1 2015年),有一个其他情况下的Git将不会跟随符号链接了:见犯e0d201b通过JUNIOÇ滨野(gitster(主Git的维护者)

apply: do not touch a file beyond a symbolic link

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/diris 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/dirand then creates a file path/to/dir/file, we need to flag it as an error without actually creating path/to/dirsymbolic 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/dirand a file path/to/dir/fileat the same time,
  • while allowing a valid patch that removes a symbolic link path/to/dirand then adds a file path/to/dir/file.

由于 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

That means, in that case, the error message won't be a generic one like "%s: patch does not apply", but a more specific one:

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

affected file '%s' is beyond a symbolic link

回答by J Chris A

Hmmm, mount --binddoesn't seem to work on Darwin.

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

Does anyone have a trick that does?

有没有人有这样做的技巧?

[edited]

[编辑]

OK, I found the answer on Mac OS X is to make a hardlink. Except that that API is not exposed via ln, so you have to use your own tiny program to do this. Here is a link to that program:

好的,我发现在 Mac OS X 上的答案是建立硬链接。除了那个 API 没有通过 公开ln,所以你必须使用你自己的小程序来做到这一点。这是该程序的链接:

Creating directory hard links in Mac OS X

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

Enjoy!

享受!