Gitはシンボリックリンクをどのように処理しますか?


1607

シンボリックリンクのファイルまたはディレクトリがあり、それをGitリポジトリにコミットすると、どうなりますか?

私はそれがファイルが削除されるまでそれをシンボリックリンクとして残し、それからあなたが古いバージョンからファイルを取り戻すならそれは通常のファイルを作成するだけだと思います。

参照しているファイルを削除するとどうなりますか?ぶら下がりリンクをコミットするだけですか?


19
.gitignoreシンボリックリンクをフォルダーではなくファイルとして認識します。
0xcaff 2014

6
まあ、明らかにその質問には、その答えが意味する以上のものがあります。たとえば、私は次のことを考えています:リポジトリに、そのリポジトリの大きなファイルへのシンボリックリンクを作成し、変更をプッシュしてから、それらの変更を別のマシンにプルすると、どうなりますか?大きなファイルは両方の場所に大きなファイルとして保存されますか、それともシンボリックリンクが保持され、新しいマシンでリンクファイルが元の大きなファイルを指すようになりますか?
jvriesem 2014年

7
これは古いスレッドですが、このコメントはまだ役に立つかもしれません。jviesemに対応して、ソフトリンクは基本的に別のファイルの名前を持つファイルです。したがって、別のマシンにプルすると、リンクがダウンロードされ、元のファイルシステム上の大きなファイルの名前が付けられます。新しいマシンで名前が有効でない場合、リンクの名前は無効になります。大きなファイルは新しいマシンにダウンロードされません。
ラサロ2015年

6
@ lasaro、gitリポジトリでリンク切れを回避する方法は、シンボリックリンクを作成するときに、../..必要に応じて常に相対パスを使用することです。
ワイルドカード

8
Windowsのほとんどのバージョンでは、シンボリックリンクを作成するために昇格されたアクセス許可が必要です。Windows git pullでsymlinkの代わりにファイルを作成する場合は、管理者としてGitクライアントを実行してみてください。
axmrnv 2017年

回答:


1348

Gitは、通常のファイルと同じように、リンクの内容(つまり、リンク先のファイルシステムオブジェクトのパス)を「blob」に格納するだけです。次に、名前、モード、およびタイプ(シンボリックリンクであることを含む)を、それが含まれているディレクトリを表すツリーオブジェクトに格納します。

リンクを含むツリーをチェックアウトすると、ターゲットファイルシステムオブジェクトが存在するかどうかに関係なく、オブジェクトはシンボリックリンクとして復元されます。

シンボリックリンクが参照するファイルを削除しても、Gitが制御するシンボリックリンクには何の影響もありません。ぶら下がり参照があります。リンクを削除または変更して、必要に応じて有効なものを指すようにするのは、ユーザーの責任です。


328
ところで。FATのようなシンボリックリンクをサポートしていないファイルシステムを使用していて、リポジトリがシンボリックリンクを使用している場合は、core.symlinks構成変数をfalseに設定すると、シンボリックリンクがリンクテキストを含む小さなプレーンテキストファイルとしてチェックアウトされます。
JakubNarębski、2009年

14
@JakubNarębski以前これを見た。リポジトリには、使用するライブラリへのパスが1行のテキストファイルがありました。それの目的が何であるか理解できませんでした。私は今何が起こったのか知っています。
Matt K

25
私は非常に賛成の回答についてコメントするのをためらっていますが、「通常のファイルの場合と同じように」という言い回しは、新規参入者を誤解させる可能性があると思います。
マシュー・ハニガン、2014年

10
(編集時間を使い果たしました)コンテンツがblob内にあるという点のみが通常のファイルのようです。重要な違いは、通常のファイルの場合、BLOBはファイルのコンテンツですが、シンボリックリンクの場合、BLOBはリンク先のファイルのパス名を持っているということです。@JakubNarębski「小さなプレーンテキストファイル」について..それらが小さくテキストであることを望みますが、もちろんblobはblobであり、巨大でバイナリである可能性があります。ファイルがシンボリックリンクとして誤って入力された場合は、stackoverflow.com / questions / 18411200 /…を参照してください。
マシュー・ハニガン、2014年

2
シンボリックリンクのグローバル設定とシンボリックリンクのローカル設定を必ず確認してください。設定がTortiseGitまたはウィンドウからコピーされた場合、それらをいじる可能性がsymlinks = falseあります。
フィアット

250

インデックスにファイルを追加したときにGitが何をするかを確認することで、Gitがファイルをどのように処理するかを確認できます。インデックスはプリコミットのようなものです。インデックスがコミットされると、を使用git checkoutして、インデックス内にあったすべてのものを作業ディレクトリに戻すことができます。では、シンボリックリンクをインデックスに追加すると、Gitは何をしますか?

調べるには、まずシンボリックリンクを作成します。

$ ln -s /path/referenced/by/symlink symlink

Gitはこのファイルをまだ認識していません。git ls-filesインデックスを検査できます(-s出力のstatような出力):

$ git ls-files -s ./symlink
[nothing]

次に、シンボリックリンクのコンテンツをインデックスに追加して、Gitオブジェクトストアに追加します。ファイルをインデックスに追加すると、Gitはその内容をGitオブジェクトストアに保存します。

$ git add ./symlink

それで、何が追加されましたか?

$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink

ハッシュは、Gitオブジェクトストアで作成されたパックされたオブジェクトへの参照です。.git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15cリポジトリのルートを調べれば、このオブジェクトを調べることができます。これはGitがリポジトリに保存するファイルで、後でチェックアウトできます。このファイルを調べると、非常に小さいことがわかります。リンクされたファイルの内容は保存されません。

(出力に120000リストされているモードです。通常のファイルのls-filesよう100644になります。)

しかし、リポジトリからファイルシステムにチェックアウトすると、Gitはこのオブジェクトをどのように処理しますか?core.symlinks設定によって異なります。からman git-config

core.symlinks

falseの場合、シンボリックリンクは、リンクテキストを含む小さなプレーンファイルとしてチェックアウトされます。

そのため、リポジトリにシンボリックリンクがある場合、チェックアウト時に、構成の値に応じて、完全なファイルシステムパスへの参照を含むテキストファイル、または適切なシンボリックリンクを取得しますcore.symlinks

どちらの方法でも、symlinkによって参照されるデータはリポジトリに保存されません。


1
すばらしい答え
CervEd

147

「編集者のメモ」:この投稿には古い情報が含まれている可能性があります。1.6.1以降のGitの変更に関するコメントとこの質問をご覧ください。

シンボリックリンクされたディレクトリ:

ソフトリンクであるディレクトリがある場合に何が起きるかに注意することが重要です。更新を伴うGitプルはリンクを削除し、通常のディレクトリにします。これは私が一生懸命学んだことです。ここここでいくつかの洞察

 ls -l
 lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir

git add/commit/push

It remains the same

あと、git pullいくつかの更新が見つかりました

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir

4
シンボリックリンクされたディレクトリに関するこれらの警告は、バージョン対応のシンボリックリンクに適用されないことに注意してください。問題となっている主なエッジケースは、作業ツリーの一部またはすべてを別のパス(たとえば、ディスクスペースの多い別のパーティション)にシンボリックリンクし、gitが既存のシンボリックリンクを介してコードをチェックアウトすることを期待しているケースでした。つまり、ファイルまたはディレクトリへのバージョン管理されたシンボリックリンクを含むプロジェクトがある場合、通常のsymlink-as-blob動作はシンボリックリンクを保持し、それらのシンボリックリンクのバージョン変更を正しく行い、それ以外の場合は期待どおりに機能します。
John Whitley、

上記の動作はgit 1.6.5.6でテストされました。しかし、かなり長い間、バージョン管理された動作がgitで適切であったと強く思います。
John Whitley、

22
この動作はすべてのバージョンのgitに存在しますか、それとも修正されましたか?
jbotnik

24
それは、この動作は修正されましたように思える、以下を参照してくださいstackoverflow.com/a/1943656/1334781
ロンWertlen

2
Shekar:回答を編集して、近年のgitの変化を反映させますか?
アインポクルム2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.