Git - wie man mit Symlinks umgeht

71

Was ist der richtige Weg, um mit Symlinks in Git umzugehen?

Ich habe folgende Struktur:

Vendors
  Module A
  Module B
  Module C
App
 Code
   Modules
     Core Module 1
     Core Module 2
     Module A (symlinked to vendors)
     Module B (symlinked to vendors)
     Module C (symlinked to vendors)

Es gibt ein Haupt-App-Verzeichnis, das den gesamten Kerncode der Anwendung enthält. Zusätzlich gibt es ein Herstellerverzeichnis, das Module enthält, die mit dem Haupt-App-Verzeichnis verknüpft und daher integriert werden.

Wichtig ist, dass sowohl das Herstellerverzeichnis als auch das Haupt-App-Verzeichnis im selben Repository versioniert sind.

Sollte ich git daher weiterhin die Symlinks speichern lassen oder einen Weg finden, Symlinks ignorieren zu lassen?

Marty Wallace
quelle
hm ich habe es relativ gemacht und es funktioniert nicht auf github :( kannst du mir bitte helfen? github.com/lingohub/Example-Resource-Files/blob/master/…
Betty St
Ihre Anfrage ist völlig vernünftig und Sie haben einen Verstoß gegen die Kapselung von GitHub aufgedeckt. Symlinks sind ein Detail der Speicherebene. Wo möchte ich verschiedene Ordner physisch auf verschiedenen Volumes aufbewahren? GitHub sollte sich nur mit der Navigationsschicht des Dateisystems befassen: Wenn etwas wie ein Unterverzeichnis aussieht und sich so verhält, behandeln Sie es wie eines (Ententypisierung), ohne den Benutzer zu überfordern, indem Sie nach unten schauen, um festzustellen, ob es sich um einen Symlink zu einem anderen Volume handelt oder nicht.
Canuck

Antworten:

136

Git kann mit Symlinks gut umgehen, solange das von allen Entwicklern verwendete Betriebssystem sie unterstützt. Da Sie darauf angewiesen sind, dass diese Symlinks vorhanden sind, gehe ich davon aus, dass Ihre Entwicklungsumgebungen alle Symlinks unterstützen.

Beachten Sie Folgendes, um zu entscheiden, ob etwas in Ihr Git-Repository aufgenommen werden soll oder nicht (Symlink oder auf andere Weise):

  • Handelt es sich um eine Datei, die von einem Tool oder einem anderen Prozess im Repository generiert wurde? Wenn ja, ignorieren Sie es am besten und lassen Sie jeden Benutzer die Datei generieren, damit er immer die neueste Version hat.
  • Ist die Datei spezifisch für die Entwicklungsumgebung eines bestimmten Benutzers oder wird sie in allen Umgebungen verwendet? Wenn es sich um eine Eigenart der Umgebung eines bestimmten Benutzers handelt, beispielsweise um eine Konfiguration zum Ignorieren von Emacs-Sicherungsdateien, gehört sie nicht zum Repo. Wenn es etwas ist, das alle Entwickler benötigen und / oder etwas, das zum Erstellen der Anwendung für die Produktion benötigt wird, sollte es im Repository gespeichert werden.

In Ihrem Fall scheinen die Symlinks nicht generiert zu werden und werden in allen Umgebungen benötigt. Daher sollte es in Ordnung sein, sie in das Repository zu stellen.

Wenn Sie sie erstellen, müssen Sie sie jedoch als relative Symlinks und nicht als absolute Symlinks erstellen, damit sie unabhängig davon funktionieren, wo das Repository geklont wird. Der einfachste Weg, dies zu tun, besteht darin, das Verzeichnis in das Modulverzeichnis zu ändern und von dort aus den Symlink zu erstellen:

cd App/Code/Modules
ln -s "../../../Vendors/Module A" "Module A"
Martin Atkins
quelle
hm ich habe es relativ gemacht und es funktioniert nicht auf Github :( Kannst du mir bitte helfen? github.com/lingohub/Example-Resource-Files/blob/master/…
Betty St
Bedeutet dies, dass Git den Inhalt von App / Code / Modulen / Modul A automatisch aktualisiert, wenn ich Änderungen an Anbietern / Modul A vornehme und diese an Git weitergebe?
HasnainMamdani
3
Verwenden Sie die -rOption, um relative Symlinks zu erstellenln -r -s /path/to/target
Fred Schoen
1
Stellen Sie sicher, dass Ihre Git-Konfiguration nicht hat symlinks = false. Dies kann passieren, wenn Sie ein Repository von Windows oder mit TortiseGit kopiert haben.
Phyatt
11

Git speichert den Symlink wie jede andere Datei in seiner Versionskontrolle - mit Ausnahme eines Symlinks werden nur die Informationen über den Pfad, mit dem die Symlinks verknüpft sind, und der Dateityp als Symlink anstelle einer regulären Datei gespeichert.

Wenn der Symlink auf ein Verzeichnis verweist, speichert git den Inhalt nicht unter dem Symlink-Verzeichnis.

Es sollte also nicht schaden, Symlinks zu speichern, die für Ihren Fall unter git versioniert wurden.

Eine weitere Sache, die Sie bei Symlinks beachten müssen, ist, dass git nur die Symlinks auf einem neuen Klon neu erstellt, nicht die Datei oder das Verzeichnis, auf die es verweist. Es besteht die Möglichkeit, dass der symlinked Pfad nicht vorhanden ist (z. B. bei Verwendung absoluter Pfade).

Tuxdude
quelle
1
Gibt es eine Möglichkeit, Dateien hinzuzufügen, die sich in einem Symlink-Verzeichnis befinden?
Kraftydevil
2
Mit @kraftydevil - git können Sie nur Dateien unter dem Symlink-Verzeichnis hinzufügen, solange das Zielverzeichnis des Symlinks selbst unter der Git-Versionskontrolle steht. Andernfalls wird (und sollte) git den Inhalt des Symlink-Verzeichnisses nicht versionieren. Wenn Sie versuchen, Dateien im Symlink-Verzeichnis außerhalb des Haupt-Git-Repository-Verzeichnisses zu versionieren, machen Sie etwas falsch. Vielleicht möchten Sie auschecken git submodules(oder besser git subtrees).
Tuxdude
Ich stelle meine Jenkins-Instanz unter Quellcodeverwaltung. Ich möchte den Inhalt des lastSuccessful-Builds für jeden Job behalten. Ich werde es mir etwas später ansehen, um weitere Erklärungen zu erhalten.
Kraftydevil
@Tuxdude Siehe stackoverflow.com/questions/15465436/git-how-to-handle-symlinks/… (konnte wegen zu vieler Zeichen nicht als Kommentar gepostet werden ).
IoCron
1

@Tuxdude Kann dir überhaupt nicht zustimmen mit "... dann machst du etwas falsch". Wenn Sie beispielsweise einen Medienordner auf einem anderen Laufwerk auf dem Webserver oder sogar auf einem NFS ablegen müssen, müssen Sie ihn außerhalb der Versionskontrolle ablegen. Daher ist der Inhalt des Ordners für verknüpfte Medien nicht wie von Ihnen erläutert durch Versionsverwaltung zugänglich. Aber das ist ein Szenario, in dem man es so machen muss. Und es ist wirklich ein Schmerz in der b ... Mein Szenario ist noch komplexer (ich werde nicht ins Detail gehen), was ich eigentlich suche, ist, die Unterordner des verknüpften Ordners zur Versionierung hinzuzufügen, aber nicht dessen Inhalt, aber Ich brauche eine Option, bei der ich alle Änderungen des Unterordnertyps selbst in Git ignorieren kann. Als Beispiel die Grundstruktur:

  • app / media / bla
  • app / media / blubb

Ich brauche diese Ordner in der Git-Versionierung ohne deren Inhalt.

Auf dem Webserver (gleiche Versionierung) sehen diese Ordner folgendermaßen aus (Symlinks):

  • app / media / bla => irgendwo anders
  • app / media / blubb => wieder ganz woanders

Die Entwickler sollten in ihrer lokalen Umgebung nur die ursprünglich versionierte Struktur haben, wie im ersten Schritt erläutert (keine Symlinks). Der Webserver verfügt jedoch über Symlinks zu verschiedenen NFS-Systemen.

Wenn jemand eine Idee hat, wie man das löst, würde ich es wirklich schätzen, weil ich noch keine Lösung dafür gefunden habe.

Die einzige Möglichkeit, die ich jetzt mache, besteht darin, einen Builder zu haben, der die richtige / unterschiedliche Struktur für lokale Umgebungen erstellt, und die Server und Medienunterordner werden derzeit von gitignore vollständig ignoriert. Aber das kann manchmal schwierig / schwer zu pflegen sein.

ioCron
quelle
1
Dies ist ein häufiges Problem, und wie ich bereits sagte, hängt es nicht mit der Versionskontrolle zusammen. Eine Lösung besteht darin, ein Initialisierungsskript zu haben, um die Symlinks basierend auf der Zielumgebung einzurichten. Das Initialisierungsskript sollte ausgeführt werden, um Ihr Setup direkt nach a zu booten git clone. Fügen Sie das Initialisierungsskript zur Versionskontrolle von git hinzu. BTW gitwird keine leeren Verzeichnisse versionieren, git nur Versionsdateien und kennt den Pfad. Dies wird verwendet, um die Verzeichnisstruktur neu zu erstellen, wenn Sie einen der gitBefehle ausführen.
Tuxdude
Vielen Dank für Ihre Erklärung, das ist eigentlich fast genau so, wie ich es bei meinen aktuellen Setups mache. Ich dachte nur, es hätte einen "bequemeren" Weg geben können. Wenn git eine Art Flag zur Unterscheidung zwischen normalen Dateien und Symlinks in den Gitignore-Regeln usw. haben würde, wären einige Dinge zumindest ein bisschen einfacher. Aus diesem Grund denke ich, dass es eine Beziehung zur "Versionskontrolle" gibt, sie könnte als "neue Funktion" implementiert werden / durch eine Funktionsanforderung gibt es akut auch einige andere Dinge, die mir in git fehlen, wenn es um komplexere geht Szenarien.
IoCron
1
Ich kann tatsächlich sagen, warum Git Symlinks so behandelt. Für git entspricht symlink einer Textdatei, deren Inhalt das Ziel des Symlinks darstellt. Dieses Ziel wird als Teil des Git-Verlaufs hinzugefügt, wenn Sie den Symlink zu Git hinzufügen.
Tuxdude