it-swarm.com.de

Wie wird ein vorhandenes Verzeichnis in einem Git-Repository zu einem Git-Submodul?

Ich bin sehr verwirrt über Git-Submodule.

Grundsätzlich besteht mein Problem darin, dass ich git nicht verstehen kann, dass ~/main-project/submodule ein Submodul ist.


Ich habe gute Erfahrungen mit Git-Submodulen:
in meinem dotfiles-Repository Ich habe die .gitmodules-Datei in ~/dotfiles-repo erstellt und dort Pfade und URLs hinzugefügt. Wenn ich dann Änderungen an den Dateien innerhalb der Submodule vornehme und git status ausführte, würde ich Folgendes erhalten: .vim/bundle/auto-complete (new commits) # in red

Ich habe die .gitmodules-Datei in ~/main-project erstellt, aber:

  • Wenn ich ~/main-project/submodule und sogar Push-Änderungen ändere, erhalte ich keine ähnliche Antwort wie <submodule> (new commits) # in red, wenn git status in ~/main-project ausgeführt wird. Ich bekomme nur die Änderungen, die in diesen Verzeichnissen vorgenommen wurden
  • Wenn ich für diese Verzeichnisse auf die Ordner-Links auf github klicke, leite ich nicht zu den Repositorys selbst, aber ich bleibe im selben Repository.

    1. Vielleicht fehlt mir der ganze Punkt. Was sind die Hauptmerkmale von Submodulen?
    2. Warum versteht git die Submodule in the dotfiles repo aber nicht in meinem anderen Repo ?
    3. Liegt es daran, dass ich git bereits angewiesen habe, die Dateien in ~/main-project/submodule zum Index hinzuzufügen?

Ich habe diese Frage die mich zu diese Antwort geführt hat/gelesen Aber ich bin mir nicht sicher, ob ich git-subtree brauche. Ich möchte keine Dinge tun, bei denen sich Änderungen möglicherweise schwer ändern lassen.

Edit: Diese vorgeschlagene Duplikat-Lösung hat auch nicht funktioniert, ich habe einen Fehler mit dem Updates were rejected because the remote contains work that you do not have locally erhalten. Es scheint, dass @GabLeRoux mir praktisch gesagt hat, <repo-A> an die URL von <repo-B> zu drücken.

20
Doron Behar

Die Lösung ist ganz einfach. Es wurde aus hier extrahiert.

  1. git rm submodule-dir
    Dadurch werden alle Dateien gelöscht, nach denen git in submodule-dir verfolgt wurde.
  2. rm -rf submoduledir
    Dadurch werden alle anderen Dateien gelöscht, die möglicherweise in submodule-dir verbleiben, da git sie ignoriert hat.
  3. Nun müssen wir ein Commit ausführen, um die Dateien aus dem Index zu entfernen:
    git commit
    Nach dem Commit haben wir die Dateien gesäubert, denen git folgte und nicht in submodul-dir..__ folgte. Jetzt ist es Zeit zu tun:
  4. git submodule add <remote-path-to-submodule>
    Dadurch wird das Submodul erneut als echtes Submodul hinzugefügt.
  5. An diesem Punkt kann es sinnvoll sein, .gitmodules zu überprüfen und zu prüfen, ob die Submodule erfolgreich hinzugefügt wurden. In meinem Fall hatte ich bereits eine .gitmodules-Datei, so dass ich sie ändern musste.

BEARBEITEN

Seit v2.12.0-rc0 und nach dieses Commit , erhielten wir git submodule absorbgitdirs und es war genau das, was ich zum Zeitpunkt der Veröffentlichung dieser Frage brauchte.

Dies ist, was der Befehl docs state dieses Befehls ausführt:

Wenn sich ein Git-Verzeichnis eines Submoduls im Submodul befindet, Verschieben Sie das Git-Verzeichnis des Submoduls in seine Superprojekte $GIT_DIR/modules Pfad und verbinden Sie dann das Git-Verzeichnis und sein Arbeitsverzeichnis durch Setzen von core.worktree und Hinzufügen von Eine .git-Datei, die auf das in .__ eingebettete git-Verzeichnis verweist. SuperProjekte Git-Verzeichnis.

Anstatt wie in den vorherigen Antworten von @DomQ und mir selbst alles von vorn zu beginnen, kann man einfach Folgendes hinzufügen:

  1. Fügen Sie ohne Entfernen des Submoduls aus dem Index die URL des Submoduls zu .gitmodules und zu .git/config mit hinzu
    git submodule add <url> <path>
  2. Verschieben Sie das $GIT_DIR-Verzeichnis des Submoduls (.git in regulären Repositorys) mit .git/modules/<path>
    git submodule absorbgitdirs <path>
21
Doron Behar

Es gibt grundsätzlich keinen besseren Weg, als von vorne zu beginnen:

  1. stellen Sie sicher, dass alles überall eingesetzt wird
  2. bewegen Sie Ihr Sub-Repository aus dem Weg
  3. git submodule add von der Remote des Sub-Repositorys
  4. cd mysubmodule
  5. git fetch ../wherever/you/stashed/the/sub-repository/in/step-1
  6. git merge FETCH_HEAD

Um zu erklären, warum dies so ist, scheint mir ein tieferes Verständnis darüber, welche Submodule sind erforderlich sind, als das, was man der git-submodule(1) / manuellen Seite (oder sogar dem relevanten Kapitel der Git Buch ). Ich habe einige ausführlichere Erklärungen zu diesem Blogbeitrag gefunden, aber da dieser Beitrag etwas langwierig ist, erlaube ich mir, sie hier zusammenzufassen.

Auf einem niedrigen Niveau besteht ein Git-Submodul aus den folgenden Elementen:

  • Ein Commit-Objekt am oberen Rand des Submodulbaums
  • (In aktuellen Versionen von Git) Ein Unterverzeichnis in .git/modules zum Hosten der Git-Objekte für das Submodul.
  • Ein Eintrag in der Konfigurationsdatei .gitmodules.

Das Commit-Objekt ist (oder genauer von SHA1 referenziert) im übergeordneten Baumobjekt enthalten. Dies ist ungewöhnlich, da Dinge normalerweise - umgekehrt laufen, aber dies erklärt, warum ein Verzeichnis im git status des Haupt-Repositorys angezeigt wird, nachdem Sie im Submodul ein Commit ausgeführt haben. Sie können auch einige Experimente mit git ls-tree machen, um dieses Commit-Objekt genauer zu betrachten.

Das Unterverzeichnis in .git/modules steht für ein .git-Unterverzeichnis im Untermodul; Tatsächlich gibt es im Submodul eine .gitfile, die mit einer gitdir:-Zeile auf das erste Modul verweist. Dies ist das Standardverhalten seit Version 1.7.8 von Git . Nicht sicher, warum alles nicht funktionieren würde, wenn Sie einfach nur ein separates .git-Verzeichnis hätten, außer wie in den Versionshinweisen angegeben, würden Sie wahrscheinlich in Schwierigkeiten geraten, wenn Sie zwischen einem Zweig mit Submodul und einem anderen wechseln.

Die .gitmodules-Datei enthält die URL, von der git submodule update --remote und Freunde abgerufen werden sollen. was sich offensichtlich von den Fernbedienungen des Haupt-Repository unterscheidet. Beachten Sie auch, dass .gitmodules durch den .git/config-Befehl und andere Befehle, die ihn im Hintergrund aufrufen, teilweise in git submodule sync kopiert wird.

Während es relativ einfach ist, die notwendigen Änderungen von Hand für .gitmodules + .git/config und auch für .git/modules + mysubmodule/.git vorzunehmen (und in der Tat gibt es sogar git submodule absorbgitdirs für Letzteres), es ist nicht wirklich nur ein Porzellan, das nur erstellt werden kann das In-Tree-Commit-Objekt. Daher die vorgeschlagene Lösung durch Verschieben + Wiederherstellen der oben dargestellten Änderungen.

3
DomQ

Um Ihre Fragen in der richtigen Reihenfolge zu beantworten:

  1. Der Zweck von Submodulen nach GitHub. Das Feature ist so konzipiert, dass es als untergeordnetes Repository konzipiert werden kann (das fast wie jede andere Datei behandelt werden kann), dh die Version wird von einem übergeordneten Repository gesteuert, wobei das übergeordnete Element die aktuelle Festschreibungs-ID des Submoduls (untergeordnetes Repository) verfolgt ) und nicht der Inhalt.
  2. Dies liegt höchstwahrscheinlich daran, dass Sie die Dateien bereits zum Index des Repositorys hinzugefügt haben. In diesem Fall ist die Lösung git rm --cached submodule-name/. Erstellen Sie anschließend ein Intermediate-Commit und fügen Sie anschließend den Ordner als Repository hinzu: git add submodule-name (beachten Sie, dass bei Submodulen kein nachstehender Schrägstrich hinter dem Submodulnamen steht).
  3. Ja :)

Die Antwort , die Sie erwähnt haben, kann auch die Historie Ihrer Commits korrigieren:

  1. Vorteile:

Dieser Ordner wird in Ihrem gesamten Commit-Verlauf als Submodul behandelt, nicht nur in allen zukünftigen Commits. Dadurch werden Komplikationen vermieden, wenn Sie sich zu einer früheren Version auschecken, in der sie als Ordner behandelt wurde. Dies ist eine Komplikation, denn wenn Sie zum Tipp Ihres Zweigs zurückkehren, müssen Sie möglicherweise auch Ihr Submodul eingeben und den neuesten Befehl auschecken, um alle Dateien wiederherzustellen (die möglicherweise aus Ihrem Arbeitsverzeichnis gelöscht werden). Dies könnte vermieden werden, indem Sie bei Ihrem letzten Commit eine Art rekursives Checkout durchführen.

  1. Nachteile:

Wenn die Festschreibungshistorie geändert wird, müssten auch alle anderen Mitwirkenden das Projekt erneut klonen, da Konflikte mit der Zusammenführung auftreten oder schlimmer werden. Das Problem wird wieder in das Projekt eingefügt.

1
reubenjohn