2080 Stimmen

Wie geht Git mit symbolischen Links um?

Was passiert mit einer Datei oder einem Verzeichnis, das ein symbolischer Link ist, wenn ich es an ein Git-Repository übertrage?

Ich gehe davon aus, dass die Datei als symbolischer Link bestehen bleibt, bis sie gelöscht wird, und wenn Sie die Datei aus einer alten Version zurückholen, wird einfach eine normale Datei erstellt.

Was passiert, wenn ich die Datei, auf die sie verweist, lösche? Wird nur der "Dangling Link" übertragen?

32 Stimmen

.gitignore sieht den Symlink als Datei und nicht als Ordner.

12 Stimmen

Nun, offensichtlich steckt mehr hinter der Frage, als diese Antwort vermuten lässt. Ich frage mich zum Beispiel folgendes: Wenn ich in meinem Repository einen Sym-Link zu einer großen Datei in diesem Repository erstelle, die Änderungen veröffentliche und dann diese Änderungen auf einen anderen Rechner ziehe, was passiert dann? Wird die große Datei an beiden Orten als große Datei gespeichert, oder bleibt der Sym-Link erhalten, so dass auf dem neuen Rechner die Link-Datei auf die ursprüngliche große Datei verweist?

10 Stimmen

Dies ist ein altes Thema, aber dieser Kommentar ist vielleicht noch nützlich. Als Antwort auf jviesem: Ein Softlink ist im Grunde eine Datei mit dem Namen einer anderen Datei. Wenn Sie sie also auf einen anderen Rechner ziehen, wird der Link heruntergeladen und trägt den Namen der großen Datei auf dem ursprünglichen Dateisystem. Wenn der Name auf dem neuen Rechner nicht gültig ist, wird der Link einen ungültigen Namen haben. Die große Datei wird dann nicht auf den neuen Rechner heruntergeladen.

1651voto

CB Bailey Punkte 693084

Von linux symlink handbuch (vorausgesetzt, Sie arbeiten mit Linux):

Ein symbolischer Link ist ein spezieller Dateityp, dessen Inhalt eine Zeichenkette ist, die der Pfadname einer anderen Datei ist, der Datei, auf die der Link verweist. (Der Inhalt eines symbolischen Links kann mit readlink(2) gelesen werden).

Ein symbolischer Link ist also eine weitere Datei, genau wie ein README.md o un Makefile . Git speichert einfach den Inhalt des Links (d.h. den oben erwähnten Pfad des Dateisystemobjekts, auf das verlinkt wird) in einem "Blob", so wie es bei jeder anderen Datei der Fall wäre. Es speichert dann den Namen, den Modus und den Typ (einschließlich der Tatsache, dass es sich um einen Symlink handelt) in dem Baumobjekt, das das enthaltende Verzeichnis darstellt.

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

Wenn Sie die Datei löschen, auf die der Symlink verweist, hat dies keinerlei Auswirkungen auf den von Git kontrollierten Symlink. Sie haben dann einen baumelnden Verweis. Es ist Sache des Benutzers, den Link entweder zu entfernen oder so zu ändern, dass er auf etwas Gültiges verweist, falls erforderlich.

372 Stimmen

ÜBRIGENS. Wenn Sie ein Dateisystem wie FAT verwenden, das keine symbolischen Links unterstützt, und Ihr Repository diese verwendet, können Sie core.symlinks auf false setzen, und Symlinks würden als kleine Textdateien ausgecheckt, die den Linktext enthalten.

24 Stimmen

@JakubNarebski Ich habe das schon einmal gesehen. Es gab eine Textdatei in unserem Repo mit einer Zeile, einem Pfad zu einer Bibliothek, die wir verwenden. Ich konnte nicht herausfinden, was der Zweck dieser Datei war. Jetzt weiß ich, was passiert ist.

51 Stimmen

Ich zögere, eine hoch bewertete Antwort zu kommentieren, aber ich denke, die Formulierung "genau wie bei einer normalen Datei" könnte für Neulinge irreführend sein. Es ist wie eine normale Datei, nur dass der Inhalt in einem Blob ist. Der entscheidende Unterschied ist, dass bei einer normalen Datei der Blob der Inhalt der Datei ist, aber bei einem Symlink hat der Blob den Pfadnamen der Datei, auf die er verweist.

416voto

Dmitry Minkovsky Punkte 33223

Sie können sehen, was Git mit einem symbolischen Link macht, indem Sie ihn zum Index hinzufügen. Der Index ist wie ein Pre-Commit. Wenn der Index übertragen wird, können Sie mit git checkout um alles, was sich im Index befand, wieder in das Arbeitsverzeichnis zu bringen. Was macht Git also, wenn Sie einen symbolischen Link zum Index hinzufügen?

Erstellen Sie zunächst einen symbolischen Link:

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

Git kennt diese Datei noch nicht. git ls-files können Sie Ihren Index überprüfen ( -s druckt stat -ähnliche Ausgabe):

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

Fügen Sie nun den symbolischen Link in den Index ein. Wenn Sie eine Datei zum Index hinzufügen, kopiert Git ihren Inhalt in den Objektspeicher.

$ git add ./symlink

Was wurde also hinzugefügt?

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

Der Hash ist ein Verweis auf das gepackte Objekt, das im Objektspeicher erstellt wurde. Sie können dieses Objekt untersuchen, wenn Sie sich in .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c im Stammverzeichnis Ihres Repositorys. Dies ist die Datei, die Git im Repository speichert und die Sie später auschecken können. Wenn Sie sich diese Datei ansehen, werden Sie feststellen, dass sie sehr klein ist. Sie speichert nicht den Inhalt der verknüpften Datei. Um dies zu bestätigen, drucken Sie den Inhalt des gepackten Repository-Objekts mit git cat-file :

$ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c
/path/referenced/by/symlink

(Anmerkung 120000 ist der Modus, der in ls-files Ausgabe. Sie würde etwa so aussehen 100644 für eine normale Datei).

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

core.symlinks

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

Mit einem symbolischen Link im Repository erhalten Sie also beim Auschecken entweder eine Textdatei mit einem Verweis auf einen vollständigen Dateisystempfad oder einen richtigen symbolischen Link, je nach dem Wert der Option core.symlinks Konfiguration.

In beiden Fällen wird der Inhalt des Pfades, auf den der Symlink verweist, nicht im Repository gespeichert (es sei denn, der referenzierte Pfad ist également im Repository, natürlich).

1 Stimmen

Ist der Linkpfad, der in der Remote gespeichert ist, garantiert relativ, wenn er auf einen Pfad innerhalb des Repos verweist? Was ist mit Pfaden, die außerhalb der Projektmappe liegen? Ist er absolut oder relativ zum Root des Projekts? Hängt es davon ab, wie der Link erstellt wird?

0 Stimmen

Ja, ich denke, es hängt davon ab, wie Sie den Symlink erstellen. Wenn Sie ihn erstellen und das Ziel mit einem vorangestellten / dann ist sie absolut und kann außerhalb Ihres Repos liegen. Andernfalls wird er relativ sein. Wenn er relativ ist und in Ihr Projektarchiv zeigt, sollte er portabel sein, zumindest zwischen Unix-ähnlichen Systemen.

1 Stimmen

@geekley Ich bin mir nicht sicher, wie ich das beim Bearbeiten versehentlich vergessen habe, aber man kann den Inhalt eines Git-Speicherobjekts mit git cat-file -p Wenn der Hash Ihres Symlinks also lautet c6e5580589892eb40407c74a825afaa6c9315787 können Sie tun git cat-file -p c6e5580589892eb40407c74a825afaa6c9315787 und sehen Sie den Inhalt dieser Pack-Datei, die nur ein Symlink ist

154voto

Shekhar Punkte 6815

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

Symlinked Verzeichnisse:

Es ist wichtig zu wissen, was passiert, wenn es ein Verzeichnis gibt, das ein Softlink ist. Jeder Git-Pull mit einer Aktualisierung entfernt den Link und macht es zu einem normalen Verzeichnis. Das habe ich auf die harte Tour gelernt. Einige Einsichten ici y ici.

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 pull UND einige Aktualisierungen gefunden

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

6 Stimmen

Es ist erwähnenswert, dass diese Warnungen über symlinked Verzeichnisse nicht gelten für versionierte Symlinks. Der wichtigste Fall war der, dass Leute einen Teil oder den gesamten Arbeitsbaum in einen anderen Pfad verlinkten (z.B. auf eine andere Partition mit mehr Speicherplatz) und erwarteten, dass Git den Code über den bestehenden Symlink auscheckt. Das heißt, wenn Sie ein Projekt haben, das versionierte Symlinks zu Dateien oder Verzeichnissen enthält, wird das normale Symlink-als-Blob-Verhalten Symlinks erhalten, Änderungen an diesen Symlinks korrekt versionieren und ansonsten wie erwartet funktionieren.

0 Stimmen

Das obige Verhalten wurde mit Git 1.6.5.6 getestet, aber ich vermute stark, dass das versionierte Verhalten in Git schon seit geraumer Zeit korrekt ist.

0 Stimmen

Ich versuche, dieses Problem zu lösen, das auch bei mir aufgetaucht ist. Scheint wie ein Fehler mit git-pull übersetzen das Ergebnis aus irgendeinem Grund.

5voto

VonC Punkte 1117238

Sonderfall: Wenn " git checkout " ( man ) einen Pfad entfernt, der in dem Commit, das es auscheckt, nicht existiert, war es nicht vorsichtig genug, um symbolischen Links nicht zu folgen, was mit Git 2.32 (Q2 2021) korrigiert wurde.

Ver fab78a0 übergeben , 462b4e8 übergeben (18. März 2021) von Matheus Tavares ( matheustavares ) .
(Zusammengefasst von Junio C. Hamano -- gitster -- en Übergabe 9210c68 , 30. März 2021)

checkout : beim Entfernen von Einträgen nicht den Symlinks folgen

Abgezeichnet von: Matheus Tavares

Unter 1d718a5 ("Ungespurte Symlinks nicht überschreiben", 2011-02-20, Git v1.7.5-rc0 -- zusammenführen ), symlink.c :check_leading_path() begann, unterschiedliche Codes für FL_ENOENT y FL_SYMLINK .
Aber einer der Anrufer, unlink_entry() wurde nicht an diese Änderung angepasst, so dass es begann, Symlinks auf dem führenden Pfad der zu entfernenden Einträge zu folgen.
Beheben Sie das und fügen Sie einen Regressionstest hinzu.

Und da wir nicht mehr versuchen, solche Pfade zu entkoppeln, bekommen wir auch nicht die Warnung von remove_or_warn() .

Bei den normalen Datei- und Symlink-Fällen ist es fraglich, ob die Warnung überhaupt sinnvoll war: unlink_entry() entfernt verfolgte Pfade, die in dem Zustand, in den wir auschecken, nicht mehr vorhanden sein sollten.
Wenn das führende dir des Pfades durch eine andere Datei ersetzt wurde, bedeutet dies, dass der Basisname noch nicht existiert, so dass keine Warnung erforderlich ist.
Sicher, wir hinterlassen eine reguläre Datei oder einen Symlink im Verzeichnisnamen des Pfades, aber diese Datei ist jetzt entweder nicht verfolgt (also wieder kein Grund für eine Warnung), oder sie wird in der nächsten Phase des Checkouts durch eine verfolgte Datei ersetzt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X