Gitにシンボリックリンクを追跡させるにはどうすればよいですか?


217

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

PS:それほど安全ではないことはわかっていますが、特定の状況でのみ実行したいと思っています。


5
このようなものにハードリンクを使用することには欠点がありますか?
Ehtesh Choudhury、2011

12
Windows 7では、「mklink / d」(ディレクトリシンボリックリンク)はgitでは機能しませんが、「mklink / j」(juction)は正常に機能します。
ヨーヨー

1
ファイルを削除して新しいファイルを作成するような方法で再生成するアプリケーションによってファイルが自動生成される場合、はい、これはファイルへのハードリンクが解決しない問題です。
Martin Pecka

1
@EhteshChoudhuryでは、ディレクトリのハードリンクを作成できません
Gaurav Kansal

回答:


46

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


デフォルトでは、Gitはシンボリックリンクをたどるのではなく保存することを試みます(コンパクトにするために、そしてそれは一般的に人々が望んでいることです)。

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

すなわち:

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

することによって

 git add /bar/foo/baz

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


72
コミット725b06050a083474e240a2436121e0a80bb9f175および806d13b1ccdbdde4bbdfb96902791c4b7ed125f6により、シンボリックリンクされたディレクトリを超えてファイルを追加できなくなったため、1.6.1以降のバージョンのgitでは機能しません
Mark Longair

1
$ git add src / main / path / ConvertSymlinkToDir fatal: 'src / main / path / ConvertSymlinkToDir' is beyond a
symic

2
@ user1767316全体とコメントを読んでください。以前は機能していましたが、機能しなくなりました。ソフトウェアは変更されますが、スタックオーバーフローの受け入れられた回答は変更されません。これはまだ機能しないことを明確にしました。別の答えを見てください。
ケントフレドリック

はい@KentFredericですが、正確なエラーメッセージを送信すると、ヘルプスタックのユーザーがその問題の解決策を検索した結果、投票がキャンセルされましたが、ロックされて申し訳ありません。一方で警告が与えられれば答えは正しいですが、他方では過去ではなく現在機能している答えを優先する必要があります
user1767316

143

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

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

このコマンドは、Git管理のディレクトリで実行してください。TARGETDIRECTORYSOURCEDIRECTORYマウントする前に作成する必要があります。

Linuxでは正常に機能しますが、OS Xでは機能しません。そのトリックは、Subversionにも役立ちました。Dropboxアカウントのファイルを含めるために使用しています。ウェブデザイナーが自分の作業を行っています。


8
sudoが必要なかった場合は、非常に良い方法でしょう。
MestreLion 2011

13
このバインドを元に戻すには、を使用しますumount [mydir]。(あなたの素晴らしいヒントのために+ 1、@ user252400)
JellicleCat

10
これはセッション中にのみ機能します。それを「永遠」にする最良の方法は何ですか?
Adobe

17
@Adobe:次のように/ etc / fstabに入れます:/ sourcedir / targetdir none bind
Alexander Garden

8
ここでは、sshfsはsudoを必要とせずにこの種のトリックを実現できます。
PypeBros 2012

75

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

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

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

このアプローチは常に機能するとは限りませんが、今のところ私にはうまくいきました。


5
唯一の方法であるように思われ、それはそれほど悪いことではありません...私はあなたの方法は非常にエレガントなアプローチだと思います gitはファイルではなくコンテンツを追跡します。したがって、すべてのコンテンツをまとめてそこから他の場所に
シンボリックリンク

12
私の場合、あるGitリポジトリから別のGitリポジトリへのリンクが必要だったので、どちらの場所にあるファイルも編集して、それぞれのリモートにコミットできます。Windows 7では、ジャンクション( "mklink / j")がうまく機能しました。
ヨーヨー

3
もちろん。時々答えはそれだけです。
Windowsより前のBBW

ソースと宛先の両方をgitしたい場合はどうなりますか?(両方が異なるリポジトリに
含める

1
質問に答えません:(リポジトリの一部をiCloudに同期させたいと思っていました。残念ながら、iCloudはシンボリックリンクをたどらないので、gitにシンボリックリンクをたどり、元のファイルをiCloudに保存するかもしれません。誰もフォローしないことが判明しました。 symlinks:\
Jerry Green

49

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

macOS(10.13 High Sierraより前)

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

ハードリンクを作成するには、単純に:

hln source destination

macOS High Sierraアップデート

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

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

developer.apple.comのAPFS FAQから

今後の代替案については、https://github.com/selkhateeb/hardlink/issues/31をフォローしてください

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

lnコマンドは、ハードリンクを作ることができます。

ln source destination

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

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

mklink /j "source" "destination"

7
注:これは基本的に私が探していたものですが、Linuxではハードリンクが残念ながらファイルシステムの境界を越えることができないことを学びました(これは私の使用例です)。
sdaau 2015年

26
ディレクトリにハードリンクすることはできませんか?
Nanne、2015年

1
ln source destinationOS Xでも動作します。El Capitanでテスト済み。
Mahdi Dibaiee

7
@Nanneいいえ、しかしあなたは行うことができます:cp -al source destination。`-l 'はファイルのコピーではなくハードリンクを意味します。
Paolo

6
残念ながら、ディレクトリをハードリンクしたり、ファイルシステムの境界を越えたりすることはできません。これにより、このソリューションは2重に機能しなくなります。
Konrad Rudolph

25

これは、インデックス内のシンボリックリンク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に準拠していません。

多少テストされていますが、このコードにはいくつかの間違い/エラーがあるかもしれません。


4
ディレクトリではなく、ファイルに対する質問に実際に答えようとする試みを見るのは素晴らしいことです。ただし、上記では実際にはシンボリックリンクであるファイルが表示typechangeされることに注意してくださいgit status
David Fraser、

1
これをありがとう; 知りたかっただけなのprocess_links_to_nondir
sdaau 2015年

@sdaau プロセスのargv[0]コマンド名として使用されるのはname / shです。(それが何であるかを覚えていなかったので、それを理解するために少し私を調べましたeither)
Abbafei

3
@Abbafei Ubuntu(14.04)で動作するようにスクリプトを変更できますか?見せていfind: missing argument to -exec'ます。すべてを単一行にパイプ&結合するのではなく、ステップごとのコマンド実行が必要になる場合があります。
Khurshid Alam、

1
@KhurshidAlam私にとっては、コマンドラインの間にあるコメント行を削除するのに役立ちました。ただし、フックが期待どおりに機能しません(typechange@DavidFraser のように表示されますが、リンクされたファイルはもうステージングされていないようです)
Scz

14

オンMacOS(Iはモハーベ/ 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>

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


すべてがMac OSで実行されているチームには最適のようですが、以下に概説するハードリンクはWindowsおよびLinuxで機能するはずです。
Devin G Rhode

これは役に立ちました。MacOSで有用だが欠けている機能の最善の解決策だと思います。ただし、コマンドでフルパス名を使用しないFailed to resolve... No such file or directoryエラーが発生することに注意してください。bindfs
電磁石

@electromaggotに感謝します。フルパスが必要であるという説明を追加
ijoseph

1
macos Catalinaでうまく動作します!
ジェリーグリーン

13

私はかなり長い間、symlinksを超えてファイルを追加していた。これは、特別な調整を行うことなく、以前はうまく機能していました。Git 1.6.1にアップデートしてから、これは機能しなくなりました。

これを動作させるためにGit 1.6.0に切り替えることができる場合があります。将来のバージョンのGitには、git-addシンボリックリンクを再びたどることができるフラグが付けられることを期待しています。


12

ここにあるすべてのソリューションが古くなっている、またはルートが必要なことに飽きてきたので、LD_PRELOADベースのソリューションを作成しました(Linuxのみ)。

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


LD_PRELOADライブラリ関数をオーバーライドするために使用する非常に創造的なソリューション!
iBug 2018年

はい、しかし、ここで詳しく説明する必要があります。できますか?
Peter Mortensen

どれほどの精巧さが役立つかわかりません。ソースコード全体をコピーして貼り付けない限り、この回答は常にそのリンクに依存します。readmeもここにあります。しかし、はい、Readmeの重要な部分を再現できたと思います。
Alcaro 2018年

これはOS X(Mojave 10.14.2)ではコンパイルできません。'strchrnul'( 'strchr'を意味しましたか?)に関する4つのエラーと '__xstat64'( '__lxstat64'を意味しましたか?)に関するエラーを1つ取得します。最後に、「不完全な型 'dirent64'へのメンバーアクセス」エラーが発生します。「make」、「make OPT = 1」、「sh install.sh」のどちらを使用していても発生します。
エリックヴェランド

@ErikVeland少し試してみましたが、OSXがLD_PRELOADや類似のものをサポートしていないようです。さまざまなドキュメントがさまざまなことを示唆していますが、それらはすべて数年前のものであり、Appleは非推奨のものを好みます。どれも動作しませんでした。ごめんなさい。
Alcaro

6

Gitの2.3.2+(Q1 2015年)では、Gitはなり一つの他のケースがありませんもはやシンボリックリンクをたどるには:参照e0d201bコミットによってJunio C浜野(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

4

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

誰かがそれをするトリックを持っていますか?

[編集]

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

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

楽しい!


1
このハードリンクの宛先ディレクトリが別のgitリポジトリのサブディレクトリである場合、これは混乱になります。ハードリンクでgit操作を行うと、この他のgitリポジトリに適用されます。何をしているかを再確認してください。
yegle、

4
これは、ポートを使用してインストールできるcode.google.com/p/bindfsを介して行うことができます。
キットSunde 2013

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/

5
少なくともOSXでは、次の結果になりますfatal: 'src/' is beyond a symbolic link
Dan Rosenstark

2
@Mark Longairで説明されているように、これはgit 1.6.1までしか機能しませんでした
MestreLion 2011

それは私の問題でした、ありがとう!
マイクQ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.