Wie geht Git mit symbolischen Links um?

1607

Was passiert damit, wenn ich eine Datei oder ein Verzeichnis habe, bei dem es sich um einen symbolischen Link handelt, und die ich in ein Git-Repository übertrage?

Ich würde annehmen, dass es als symbolischer Link verbleibt, bis die Datei gelöscht wird. Wenn Sie die Datei dann von einer alten Version zurückziehen, wird nur eine normale Datei erstellt.

Was macht es, wenn ich die Datei lösche, auf die es verweist? Setzt es nur die baumelnde Verbindung fest?

Alex
quelle
19
.gitignoresieht den Symlink als eine Datei, nicht als einen Ordner.
0xcaff
6
Offensichtlich hat die Frage mehr zu bieten, als diese Antwort impliziert. Ich frage mich beispielsweise Folgendes: Wenn ich in meinem Repository einen Sym-Link zu einer großen Datei in diesem Repository erstelle, die Änderungen übertrage und diese Änderungen dann auf einen anderen Computer übertrage, was passiert dann? Wird die große Datei an beiden Speicherorten als große Datei gespeichert oder bleibt der Sym-Link erhalten, sodass die Link-Datei auf dem neuen Computer auf die ursprüngliche große Datei verweist?
Jvriesem
7
Dies ist ein alter Thread, aber dieser Kommentar kann immer noch nützlich sein. Als Antwort auf jviesem ist ein Softlink im Grunde eine Datei mit dem Namen einer anderen Datei. Sobald Sie es auf einen anderen Computer ziehen, wird der Link heruntergeladen und enthält den Namen der großen Datei im ursprünglichen Dateisystem. Wenn der Name auf dem neuen Computer nicht gültig ist, hat der Link einen ungültigen Namen. Die große Datei wird nicht auf den neuen Computer heruntergeladen.
Lasaro
6
@lasaro, um defekte Links in einem Git-Repo zu vermeiden, müssen beim Erstellen der Symlinks immer relative Pfade verwendet werden, die ../..nach Bedarf verwendet werden.
Wildcard
8
Beachten Sie, dass Sie in den meisten Windows-Versionen erhöhte Berechtigungen benötigen, um einen Symlink zu erstellen. Wenn Sie unter Windows arbeiten und git pullanstelle von Symlink eine Datei erstellen, versuchen Sie, Ihren Git-Client als Administrator auszuführen.
Axmrnv

Antworten:

1348

Git speichert nur den Inhalt des Links (dh den Pfad des Dateisystemobjekts, mit dem es verknüpft ist) in einem "Blob", genau wie bei einer normalen Datei. Anschließend werden Name, Modus und Typ (einschließlich der Tatsache, dass es sich um einen Symlink handelt) im Baumobjekt gespeichert, das das enthaltende Verzeichnis darstellt.

Wenn Sie einen Baum auschecken, der den Link enthält, wird das Objekt als Symlink wiederhergestellt, unabhängig davon, ob das Zieldateisystemobjekt vorhanden ist oder nicht.

Wenn Sie die Datei löschen, auf die der Symlink verweist, hat dies keinerlei Auswirkungen auf den Git-gesteuerten Symlink. Sie haben eine baumelnde Referenz. Es ist Sache des Benutzers, den Link entweder zu entfernen oder zu ändern, um bei Bedarf auf etwas Gültiges zu verweisen.

CB Bailey
quelle
328
Übrigens. Wenn Sie sich in einem Dateisystem wie FAT befinden, das keine symbolischen Links unterstützt, und Ihr Repository diese verwendet, können Sie die core.symlinksKonfigurationsvariable auf false setzen, und Symlinks werden als kleine Nur-Text-Dateien ausgecheckt, die den Link-Text enthalten.
Jakub Narębski
14
@ JakubNarębski Ich habe das schon mal gesehen. In unserem Repo befand sich eine Textdatei mit einer Zeile, einem Pfad zu einer Bibliothek, die wir verwenden. Konnte nicht herausfinden, was der Zweck davon war. Ich weiß jetzt, was passiert ist.
Matt K
25
Ich zögere, eine hoch bewertete Antwort zu kommentieren, aber ich denke, dass die Formulierung "genau wie bei einer normalen Datei" für Neulinge irreführend sein könnte.
Matthew Hannigan
10
Es ist wie bei einer normalen Datei, nur dass sich der Inhalt in einem Blob befindet. Der entscheidende Unterschied besteht darin, dass für eine normale Datei der Blob der Dateiinhalt ist, für einen Symlink jedoch der Pfadname der Datei, mit der er verknüpft ist. @ JakubNarębski In Bezug auf "kleine Nur-Text-Dateien" .. Sie würden hoffen, dass sie klein und Text sind, aber natürlich ist ein Blob ein Blob und könnte möglicherweise riesig und binär sein. Unter stackoverflow.com/questions/18411200/… erfahren Sie, wann eine Datei als Symlink falsch eingegeben wurde.
Matthew Hannigan
2
Überprüfen Sie unbedingt Ihre globalen Einstellungen für Symlinks und die lokalen Einstellungen für Symlinks. Wenn Einstellungen von TortiseGit oder Windows kopiert wurden, könnten Sie symlinks = falsemit ihnen herumspielen .
Phyatt
250

Sie können herausfinden, was Git mit einer Datei macht, indem Sie sehen, was Git macht, wenn Sie sie dem Index hinzufügen. Der Index ist wie ein Pre-Commit. Mit dem festgeschriebenen Index können Sie git checkoutalles, was sich im Index befand, wieder in das Arbeitsverzeichnis bringen. Was macht Git, wenn Sie dem Index einen symbolischen Link hinzufügen?

Um dies herauszufinden, stellen Sie zunächst einen symbolischen Link her:

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

Git weiß noch nichts über diese Datei. git ls-fileskönnen Sie Ihren Index (inspizieren -sdruckt stat-ähnlichen Ausgabe):

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

Fügen Sie nun den Inhalt des symbolischen Links zum Git-Objektspeicher hinzu, indem Sie ihn dem Index hinzufügen. Wenn Sie dem Index eine Datei hinzufügen, speichert Git deren Inhalt im Git-Objektspeicher.

$ git add ./symlink

Also, was wurde hinzugefügt?

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

Der Hash ist ein Verweis auf das gepackte Objekt, das im Git-Objektspeicher erstellt wurde. Sie können dieses Objekt untersuchen, wenn Sie .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15cim Stammverzeichnis Ihres Repositorys nachsehen . Dies ist die Datei, die Git im Repository speichert und die Sie später auschecken können. Wenn Sie diese Datei untersuchen, werden Sie feststellen, dass sie sehr klein ist. Der Inhalt der verknüpften Datei wird nicht gespeichert.

(Hinweis 120000ist der in der ls-filesAusgabe aufgeführte Modus. Dies entspricht in etwa 100644einer normalen Datei.)

Aber was macht Git mit diesem Objekt, wenn Sie es aus dem Repository in Ihr Dateisystem auschecken? Das hängt von der core.symlinksKonfiguration ab. Von man git-config:

core.symlinks

Wenn false, werden symbolische Links als kleine einfache Dateien ausgecheckt, die den Linktext enthalten.

Bei einem symbolischen Link im Repository erhalten Sie beim Auschecken entweder eine Textdatei mit einem Verweis auf einen vollständigen Dateisystempfad oder einen geeigneten symbolischen Link, abhängig vom Wert der core.symlinksKonfiguration.

In beiden Fällen werden die Daten, auf die der Symlink verweist, nicht im Repository gespeichert.

Dmitry Minkovsky
quelle
1
Tolle
147

Anmerkung des Herausgebers: Dieser Beitrag enthält möglicherweise veraltete Informationen. Bitte beachten Sie die Kommentare und diese Frage zu Änderungen in Git seit 1.6.1.

Symlinked Verzeichnisse:

Es ist wichtig zu beachten, was passiert, wenn es ein Verzeichnis gibt, bei dem es sich um einen Softlink handelt. Jeder Git-Pull mit einem Update entfernt den Link und macht ihn zu einem normalen Verzeichnis. Das habe ich auf harte Weise gelernt. Einige Einblicke hier und hier.

Beispiel

Vor

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

git add/commit/push

It remains the same

Nach git pullUND einige Updates gefunden

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir
Shekhar
quelle
4
Es ist erwähnenswert, dass diese Warnungen zu Symlink-Verzeichnissen nicht für versionierte Symlinks gelten. Der fragliche Hauptkantenfall war der von Leuten, die einen Teil oder den gesamten Arbeitsbaum in einen anderen Pfad (z. B. auf eine andere Partition mit mehr Speicherplatz) einbinden und erwarten, dass git Code über den vorhandenen Symlink auscheckt. Wenn Sie also ein Projekt haben, das versionierte Symlinks zu Dateien oder Verzeichnissen enthält, werden durch das normale Verhalten von Symlink-as-Blob Symlinks beibehalten, Versionsänderungen an diesen Symlinks korrekt vorgenommen und ansonsten wie erwartet funktioniert.
John Whitley
Das obige Verhalten wurde mit git 1.6.5.6 getestet; aber ich vermute stark, dass versioniertes Verhalten in Git seit geraumer Zeit korrekt ist.
John Whitley
22
Ist dieses Verhalten in allen Versionen von git vorhanden oder wurde dies behoben?
Jbotnik
24
Es scheint, dass dieses Verhalten jetzt behoben ist, siehe: stackoverflow.com/a/1943656/1334781
Ron Wertlen
2
Shekar: Wirst du deine Antwort so bearbeiten, dass sie die Veränderungen im Git der letzten Jahre widerspiegelt?
Einpoklum