web-dev-qa-db-ja.com

Gitにシンボリックリンクをフォローさせるにはどうすればよいですか?

私のベストはシンボリックリンクをコピーに置き換えるシェルスクリプトになるのでしょうか、それともGitにシンボリックリンクに従うように指示する別の方法がありますか?

PS:あまり安全ではないことは知っていますが、いくつかの特定のケースでのみそれをしたいと思っています。

189
Matt

注:このアドバイスは、Git 1.6.1以降、コメントごとに古くなっています。 Gitは以前はこのように動作していましたが、もう動作しません。


Gitはデフォルトで、シンボリックリンクを追跡する代わりに格納することを試みます(コンパクトさのために、一般に人々が望むものです)。

ただし、シンボリックリンクがディレクトリである場合、誤ってシンボリックリンクを超えてファイルを追加することができました。

つまり:

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

することによって

 git add /bar/foo/baz

私がそれを試してみたところ、動作するように見えました。しかし、その行動は当時私には望ましくなかったので、それ以上の情報を提供することはできません。

42
Kent Fredric

シンボリックリンク内のファイルをGitに追加するために追加したこと(シンボリックリンクは使用しませんでしたが)。

Sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

Gitが管理するディレクトリでこのコマンドを実行します。 TARGETDIRECTORYをマウントする前に、SOURCEDIRECTORYを作成する必要があります。

Linuxでは正常に動作しますが、OS Xでは動作しません!このトリックはSubversionでも役立ちました。私はこれを使用して、Webデザイナーが自分の仕事をするDropboxアカウントのファイルを含めます。

131
user252400

他の方法でシンボリックリンクを作成してみませんか? Gitリポジトリからアプリケーションディレクトリにリンクする代わりに、逆方向にリンクするだけです。

たとえば、構成ファイル~/applicationを必要とするconfig.confにインストールされているアプリケーションをセットアップするとします。

  • config.confをGitリポジトリに追加します(例:~/repos/application/config.conf)。
  • 次に、~/applicationを実行して、ln -s ~/repos/application/config.confからシンボリックリンクを作成します。

このアプローチは必ずしもうまくいくとは限りませんが、これまでのところうまくいきました。

70
spier

代わりにハードリンクを使用してください。これは、ソフト(シンボリック)リンクとは異なります。 gitを含むすべてのプログラムは、ファイルを通常のファイルとして扱います。内容を変更するには、ソースまたは宛先をeitherに変更します。

MacOS(10.13 High Sierraより前)

すでにgitとXcodeがインストールされている場合、 install hardlink 。それは微視的な ハードリンクを作成するツール です。

ハードリンクを作成するには、次のようにします。

hln source destination

macOS High Sierraアップデート

Apple File Systemはディレクトリのハードリンクをサポートしていますか?

ディレクトリのハードリンクは、Apple File Systemではサポートされていません。 macOSでHFS +からAPFSボリューム形式に変換すると、すべてのディレクトリハードリンクがシンボリックリンクまたはエイリアスに変換されます。

From APFS FAQ on developer.Apple.com

今後の代替案については、 https://github.com/selkhateeb/hardlink/issues/31 に従ってください。

Linuxおよびその他のUnixフレーバー

lnコマンドはハードリンクを作成できます。

ln source destination

Windowsの場合(Vista、7、8、…)

誰かが mklink を使用してWindowsでジャンクションを作成することを提案しましたが、私は試していません:

mklink /j "source" "destination"
43
fregante

これは 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に準拠していません。

このコードには多少のテストが行​​われていますが、いくつかの間違い/エラーがある可能性があります。

19
Abbafei

かなり長い間、私はシンボリックリンクを超えてファイルを追加していました。これは、特別な準備をすることなく、正常に機能していました。 Git 1.6.1に更新したので、これはもう機能しません。

この作業を行うためにGit 1.6.0に切り替えることができる場合があります。 Gitの将来のバージョンにgit-addのフラグがあり、再びシンボリックリンクをたどることができるようになることを願っています。

12
Erik Schnetter

私はここのすべてのソリューションが時代遅れであるか、rootを必要とすることにうんざりしたので、 LD_PRELOADベースのソリューションを作成しました (Linuxのみ)。

Gitの内部にフックし、「これはシンボリックリンクですか?」をオーバーライドします。関数。シンボリックリンクをコンテンツとして扱うことができます。デフォルトでは、リポジトリの外部へのすべてのリンクはインライン化されます。詳細については、リンクを参照してください。

7
Alcaro

Git 2.3.2+(2015年第1四半期)では、Gitがnotシンボリックリンクをもうたどらない場合がもう1つあります:参照 コミットe0d201b by Junio C Hamano(gitster (メインGitメンテナー)

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
6
VonC

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

他のコメントで示唆されていますが、他の回答では明確に提供されていません。うまくいけば、誰かが時間を節約できます。

4
ijoseph

うーん、mount --bindはダーウィンでは動作しないようです。

誰もが行うトリックを持っていますか?

[編集]

OK、Mac OS Xでの答えはハードリンクを作成することだとわかりました。そのAPIがlnを介して公開されていないことを除いて、これを行うには独自の小さなプログラムを使用する必要があります。そのプログラムへのリンクは次のとおりです。

Mac OS Xでのディレクトリハードリンクの作成

楽しい!

4
J Chris A

Git 1.5.4.3を使用していますが、末尾のスラッシュがある場合、渡されたシンボリックリンクをたどっています。例えば。

# Adds the symlink itself
$ git add symlink

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

シンボリックリンクからの変換が役立つ場合があります。シンボリックリンクではなくGitフォルダーにリンクします スクリプトによる

0
Yurij73