Articles

Mastering Git Submodule

Submodule, Schritt für Schritt

Wir werden nun jeden Schritt der Verwendung von Submodulen in einem Kooperationsprojekt untersuchen und sicherstellen, dass wir Standardverhalten, Traps und verfügbare Verbesserungen hervorheben.

Um Ihnen das Folgen zu erleichtern, habe ich einige Beispiel-Repos mit ihren „Fernbedienungen“ zusammengestellt (eigentlich nur Verzeichnisse)., Sie können das Archiv dekomprimieren, wo immer Sie möchten, und dann eine Shell (oder Git Bash, wenn Sie unter Windows sind) in dem von ihm erstellten git-Subs-Verzeichnis öffnen:

Laden Sie das Beispiel-Repos herunter

Dort finden Sie drei Verzeichnisse:

  • main fungiert als Container-Repo, lokal für den ersten Mitarbeiter,
  • Plugin fungiert als zentrales Wartungs-Repo für das Modul und
  • remotes enthält das Dateisystem fernbedienungen für die beiden vorherigen Repos.

In den folgenden Beispielbefehlen zeigt die Eingabeaufforderung immer an, in welchem Repo wir uns befinden.,

Hinzufügen eines Submoduls

Beginnen wir mit dem Hinzufügen unseres Plugins als Submodul in unserem Container (der sich in main befindet). Das Plugin selbst hat eine einfache Struktur:

.
├── README.md
├── lib
│ └── index.js
└── plugin-config.json

Also gehen wir in main und verwenden den Befehl git submodule add. Es werden die URL der Fernbedienung und ein Unterverzeichnis verwendet, in dem das Submodul „instanziiert“ werden kann.

Da wir hier Pfade anstelle von URLs für unsere Fernbedienungen verwenden, stoßen wir auf einen seltsamen, wenn auch bekannten Haken: Relative Pfade für Fernbedienungen werden relativ zu unserer Hauptfernbedienung interpretiert, nicht zum Stammverzeichnis unseres Repos., Das ist super komisch, nirgendwo beschrieben, aber ich habe es jedes Mal gesehen. Also statt zu sagen ../ Fernbedienungen / Plugin, sagen wir einfach ../Plugin.

main (master u=) $ git submodule add ../plugin vendor/plugins/demo
Cloning into 'vendor/plugins/demo'…
done.
main (master + u=) $

Dies hat einige Einstellungen in unserer lokalen Konfiguration hinzugefügt:

main (master + u=) $ cat .git/config


url = ../remotes/plugin

Und dies hat auch zwei Dateien inszeniert:

Huh?! Was ist das .gitmodules-Datei? Schauen wir uns es an:

main (master + u=) $ cat .gitmodules

path = vendor/plugins/demo
url = ../plugin

Dies ähnelt wütend unserer lokalen Konfiguration… Warum also die Duplizierung? Nun, gerade weil unsere lokale Konfiguration … lokal ist., Unsere Mitarbeiter werden es nicht sehen (was völlig normal ist), daher benötigen sie einen Mechanismus, um die Definitionen aller Submodule abzurufen, die sie in ihren eigenen Repos einrichten müssen. Das ist was .gitmodules ist für; es wird später vom Befehl git submodule init gelesen, wie wir in einem Moment sehen werden.

Beachten Sie, wie minimalistisch es in Bezug auf unser Submodul ist: Es enthält nur eine übermäßig generische neue Datei, anstatt uns mehr darüber zu erzählen, was darin vor sich geht., Unser Submodul wurde tatsächlich in das Unterverzeichnis eingefügt:


└── vendor
└── plugins
└── demo
├── .git
├── README.md
├── lib
│ └── index.js
└── plugin-config.json

Der Status ist wie Logs und Diffs auf das aktive Repo (im Moment der Container) beschränkt, nicht auf Submodule, die verschachtelte Repos sind. Dies ist oft problematisch (es ist super einfach, eine Regression zu verpassen, wenn sie auf diese Ansicht beschränkt ist), daher empfehle ich Ihnen, ein für alle Mal einen Submodul-fähigen Status einzurichten:

git config --global status.submoduleSummary true

Und jetzt:

Aaaah, das ist viel besser., Der Status erweitert seine Basisinformationen, um hinzuzufügen, dass das Untermodul, das bei vendor/plugins/demo vorhanden ist, 3 Nachrichten-Commits erhalten hat (wie wir es gerade erstellt haben, bedeutet dies, dass der Remote-Zweig nur drei Commits hatte), wobei der letzte eine Addition ist (beachten Sie die rechtwinklige Klammer >) mit einer ersten Commit-Nachrichtzeile mit der Aufschrift „Fix repo name…“.

Um wirklich nach Hause zu bringen, dass wir uns hier mit zwei separaten Repos befassen, gehen wir in das Verzeichnis des Submoduls:

Das aktive Repo hat sich geändert, weil ein neues .,git übernimmt: im aktuellen Verzeichnis (Demo, das Verzeichnis des Submoduls), a.git existiert in der Tat auch eine einzelne Datei, kein Verzeichnis. Schauen wir uns an:

demo (master u=) $ cat .git
gitdir: ../../../.git/modules/vendor/plugins/demo

Seit Git 1.7.8 hinterlässt Git keine Repo-Verzeichnisse im Arbeitsverzeichnis des Containers, sondern zentralisiert diese in den Containern .git-Verzeichnis (im inneren .git / modules) und verwendet eine gitdir-Referenz in Submodulen.,

Der Grund dafür ist einfach: Es ermöglicht dem Container-Repo, submodullose Zweige zu haben, ohne das Repo des Submoduls aus dem Arbeitsverzeichnis entfernen und später wiederherstellen zu müssen.

Wenn Sie das Submodul hinzufügen, können Sie natürlich einen bestimmten Zweig oder sogar ein bestimmtes Commit mit der CLI-b verwenden (wie üblich ist der Standardwert Master). Beachten Sie, dass wir uns im Moment nicht auf einem losgelösten Kopf befinden, im Gegensatz zu dem, was später passieren wird: Dies liegt daran, dass Git Master ausgecheckt hat, keinen bestimmten SHA1. Wir hätten einen SHA1 to-b angeben müssen, um einen losgelösten Kopf vom Start zu bekommen.,

Also, zurück zum Container-Repo, und lassen Sie uns den Zusatz des Submoduls abschließen und auf die Fernbedienung übertragen:

demo (master u=) $ cd -
main (master + u=) $ git commit -m "Ajout submodule plugin demo"
main (master u+1) $ git push

Wenn wir ein Repo abrufen, das Submodule verwendet

Um die Probleme bei der Zusammenarbeit an einem Repo zu veranschaulichen, das Submodule verwendet, teilen wir Persönlichkeiten auf und fungieren als unser Kollege, der die Fernbedienung des Containers klont, um mit uns zu arbeiten. Wir klonen das in ein Kollege-Verzeichnis, damit wir sofort erkennen können, welche Persönlichkeitsgrenze wir zu einem bestimmten Zeitpunkt haben.,

Als erstes fällt auf, dass unser Submodul im Arbeitsverzeichnis fehlt; nur sein Basisverzeichnis ist hier:

vendor
└── plugins
└── demo

Wie ist das passiert? Dies liegt einfach daran, dass unser neues Repo (Kollege) unser Submodul bisher noch nicht kennt: Die Informationen dazu befinden sich nirgends in seiner lokalen Konfiguration (überprüfen Sie es .git/config “ wenn Sie mir nicht glauben). Wir müssen das ausfüllen, je nachdem, was .gitmodules muss sagen, genau das macht git submodule init:

Our .git / config kennt jetzt unser Submodul., Wir haben es jedoch immer noch nicht von seiner Fernbedienung abgerufen, um nichts davon zu sagen, dass es in unserem Arbeitsverzeichnis vorhanden ist. Und doch zeigt sich unser Status als sauber!

Siehe, wir müssen die relevanten Commits manuell abrufen. Es ist nicht etwas, was unser anfänglicher Klon getan hat, wir müssen es bei jedem Zug tun. Wir werden in einer Minute darauf zurückkommen, da dies ein Verhalten ist, das Clone tatsächlich automatisieren kann, wenn es richtig aufgerufen wird.,

In der Praxis gruppieren wir beim Umgang mit Repos, die Submodule verwenden, normalerweise die beiden Befehle (init und update) in einem:

colleague (master u=) $ git submodule update --init

Es ist immer noch eine Schande, dass Sie mit Git all das selbst tun müssen. Stellen Sie sich vor, bei größeren FLOSS-Projekten, wenn Submodule ihre eigenen Submodule haben und so weiter und so weiter… würde dies schnell zu einem Albtraum werden.

Es kommt also vor, dass Git eine CLI — Option für clone bereitstellt, um das Git-Submodul update — init direkt nach dem Klonen automatisch rekursiv zu aktualisieren: die ziemlich treffend benannte rekursive Option.,

Also lasst uns das Ganze noch einmal versuchen:

Jetzt ist das besser! Beachten Sie, dass wir uns jetzt auf einem abgetrennten Kopf innerhalb des Submoduls befinden (wie wir es von nun an sein werden):

git-subs $ cd colleague/vendor/plugins/demo
demo ((master)) $

Siehe den doppelten Satz Klammern in meiner Eingabeaufforderung anstelle eines einzelnen Satzes?, Wenn Ihre Eingabeaufforderung nicht wie meine konfiguriert ist, um den Kopf wie beschrieben anzuzeigen (mit dem integrierten Eingabeaufforderungsskript von Git müssten Sie die Umgebungsvariable GIT_PS1_DESCRIBE_STYLE=branch definieren), sehen Sie lieber so etwas:

demo ((fe64799...)) $

Auf jeden Fall bestätigt der Status, wo wir uns befinden:

demo ((master)) $ git status
HEAD detached at fe64799
nothing to commit, working directory clean

Um ein Update von der Remote-

demo ((master)) $ git status
HEAD detached at fe64799
nothing to commit, working directory clean

h2 >

OK, jetzt, da wir unser eigenes Repo (main) und unser „Kollege“ (Kollege) für die Zusammenarbeit eingerichtet haben, treten wir in die Fußstapfen einer dritten Person: derjenigen, die das Plugin verwaltet., Hier gehen wir weiter:

Fügen wir nun zwei Pseudo-Commits hinzu und veröffentlichen diese auf der Fernbedienung:

Schließlich setzen wir unsere „first developer“ – Obergrenze erneut ein:

plugin (master u=) $ cd ../main
main (master u=) $

Angenommen, wir möchten diese beiden Commits jetzt in unserem Submodul abrufen. Um dies zu erreichen, müssen wir sein lokales Repo aktualisieren, indem wir es in sein Arbeitsverzeichnis verschieben, damit es zu unserem aktiven Repo wird.

Nebenbei bemerkt, würde ich nicht empfehlen, Pull für diese Art von Update zu verwenden., Um die Updates ordnungsgemäß im Arbeitsverzeichnis abzurufen, erfordert dieser Befehl, dass Sie sich im richtigen aktiven Zweig befinden, was Sie normalerweise nicht tun (Sie befinden sich die meiste Zeit auf einem getrennten Kopf). Sie müssten mit einer Kasse dieser Filiale beginnen. Aber noch wichtiger ist, dass der Remote-Zweig seit dem Commit, das Sie festlegen möchten, sehr gut weiter vorangekommen sein könnte, und ein Pull würde Commits injizieren, die Sie möglicherweise nicht in Ihre lokale Codebasis einfügen möchten.,

Daher empfehle ich, den Prozess manuell aufzuteilen: Zuerst git fetch, um alle neuen Daten von der Fernbedienung im lokalen Cache abzurufen, dann loggen Sie sich ein, um zu überprüfen, was Sie haben, und überprüfen Sie die gewünschte SHA1. Zusätzlich zur feinkörnigen Steuerung bietet dieser Ansatz den zusätzlichen Vorteil, unabhängig von Ihrem aktuellen Status (aktiver Zweig oder abgetrennter Kopf) zu arbeiten.

OK, also sind wir gut, kein fremdes Commit., Wie dem auch sei, lassen Sie uns explizit auf die setzen, an der wir interessiert sind (offensichtlich haben Sie eine andere SHA1):

demo (master u-2) $ git checkout -q 0e90143

(Das-q ist nur da, um uns Git-Blabbering darüber zu ersparen, wie wir auf einem losgelösten Kopf landen. Normalerweise wäre dies eine gesunde Erinnerung, aber bei diesem wissen wir, was wir tun.)

Nachdem unser Submodul aktualisiert wurde, können wir das Ergebnis im Status des Container-Repos sehen:

Im „klassischen“ Teil des Status sehen wir einen neuen Commit-Änderungstyp, dh das referenzierte Commit wurde geändert., Eine andere Möglichkeit (die zu diesem zusammengesetzt werden könnte) sind neue Inhalte, was bedeuten würde, dass wir lokale Änderungen am Arbeitsverzeichnis des Submoduls vorgenommen haben.

Der untere Teil, aktiviert durch unseren status.submoduleSummary = true Einstellung Früher wurden die eingeführten Commits explizit angegeben (da sie eine rechtwinklige Klammer >), da unser letzter Container-Commit das Submodul berührt hatte.

In der Familie“ terrible default behaviors “ lässt git diff viel zu wünschen übrig:

Was zum -?, Es gibt eine CLI-Option, mit der wir etwas Nützlicheres sehen können:

main (master * u=) $ git diff --submodule=log
Submodule vendor/plugins/demo fe64799..0e90143:
> Pseudo-commit #2
> Pseudo-commit #1

Es gibt derzeit außer dem referenzierten Commit des Submoduls keine weiteren lokalen Änderungen… Beachten Sie, dass dies fast genau mit dem unteren Teil unserer erweiterten Git-Statusanzeige übereinstimmt.

Es ist ziemlich unhandlich, diese Art von CLI-Option jedes Mal eingeben zu müssen (was übrigens nicht in den aktuellen Abschlussangeboten von Git angezeigt wird). Glücklicherweise gibt es eine übereinstimmende Konfigurationseinstellung:

Wir müssen jetzt nur noch das Container-Commit ausführen, das das Update unseres Submoduls abschließt., Wenn Sie den Code des Containers berühren mussten, damit er mit diesem Update funktioniert, schreiben Sie ihn natürlich mit. Vermeiden Sie andererseits das Mischen von Änderungen im Zusammenhang mit Submodulen und anderen Dingen, die sich nur auf den Containercode beziehen: Durch eine saubere Trennung der beiden werden spätere Migrationen zu anderen Code-Reuse-Ansätzen erleichtert (auch wie üblich atomare Commits FTW).

Da wir dieses Submodul-Update im Repo unseres Kollegen abrufen werden, werden wir direkt nach dem Commit weitermachen (was keine allgemeine gute Praxis ist).

main (master * u=) $ git commit -am "Setting submodule on PC2"
main (master u+1) $ git push

Submodul ziehen-mit repo

Klicken!, „Kollegin“ Mütze auf!

Also ziehen wir Updates aus dem Remote-Container-Repo…

(Möglicherweise haben Sie nicht die „Erfolgreich neu gestaffelt und aktualisiert…“ und sehen stattdessen eine „Zusammenführung durch die“ rekursive „Strategie“. Wenn ja, geht mein Herz an Sie, und Sie sollten sofort lernen, warum Sie rebase sollte).

Beachten Sie die zweite Hälfte dieser Anzeige: Es geht um das Submodul, beginnend mit “ Submodul abrufen…“.

Dieses Verhalten wurde mit Git 1.7.5 mit der Konfigurationseinstellung fetch zum Standard.,recurseSubmodules jetzt standardmäßig auf On-Demand: Wenn ein Containerprojekt Updates für referenzierte Submodul-Commits erhält, werden diese Submodule automatisch abgerufen. (Denken Sie daran, Holen ist der erste Teil des Ziehens.)

immer Noch, und das ist wichtig: Git auto-holt, aber nicht auto-update. Ihr lokaler Cache ist mit der Fernbedienung des Submoduls auf dem neuesten Stand, aber das Arbeitsverzeichnis des Submoduls blieb an seinem früheren Inhalt hängen. Zumindest können Sie diesen Laptop schließen, in ein Flugzeug steigen und trotzdem einmal offline vorankommen., Obwohl dieses automatische Abrufen auf bereits bekannte Submodule beschränkt ist: Alle neuen, die noch nicht in die lokale Konfiguration kopiert wurden, werden nicht automatisch abgerufen.

Git ruft automatisch ab, wird jedoch nicht automatisch aktualisiert.

Die aktuelle Eingabeaufforderung mit ihrem Sternchen ( * ) weist auf lokale Änderungen hin, da unser WD nicht mit dem Index synchronisiert ist, wobei letzterer die neu referenzierten Submodule-Commits kennt. Überprüfen Sie den Status:

Beachten Sie, wie die eckigen Klammern nach links zeigen (<)?, Git sieht, dass die aktuelle WD diese beiden Commits nicht hat, entgegen den Erwartungen des Container-Projekts.

Dies ist die massive Gefahr: Wenn Sie das Arbeitsverzeichnis des Submoduls nicht explizit aktualisieren, wird das Submodul beim nächsten Container-Commit zurückgesetzt. Dies ist eine Falle erster Ordnung.

Ist daher zwingend erforderlich, dass Sie das Update abschließen:

Solange wir versuchen, generische gute Gewohnheiten zu bilden, wäre der bevorzugte Befehl hier ein git-Submodul update-init-recursive, um jedes neue Submodul automatisch zu init und diese bei Bedarf rekursiv zu aktualisieren.,

Es gibt einen weiteren Randfall: Wenn sich die Remote-URL des Submoduls seit der letzten Verwendung geändert hat (möglicherweise hat einer der Mitarbeiter sie in der geändert .gitmodules) müssen Sie Ihre lokale Konfiguration manuell aktualisieren, um dies zu erreichen. In einer solchen Situation müssen Sie vor dem Git-Submodul-Update eine Git-Submodul-Synchronisierung ausführen.

Der Vollständigkeit halber sollte ich erwähnen, dass selbst wenn git submodule update standardmäßig das referenzierte SHA1 auscheckt, Sie dies ändern können, um beispielsweise jede lokale Submodul-Arbeit (wir werden darüber sehr bald sprechen) darüber hinaus zu reduzieren., Sie würden dies tun, indem Sie die Update-Konfigurationseinstellung für Ihr Submodul in der lokalen Konfiguration Ihres Containers auf Rebase festlegen.

Und es tut mir leid, aber nein, es gibt keine lokale Konfigurationseinstellung oder sogar CLI-Option, die beim Ziehen automatisch aktualisiert werden kann. Um solche Dinge zu automatisieren, müssen Sie entweder Aliase, benutzerdefinierte Skripte oder sorgfältig erstellte lokale Hooks verwenden., Hier ist ein Beispiel für einen Spull-Alias (einzelne Zeile, hier zur Anzeige aufgeteilt):

git config --global alias.spull '!git pull && git submodule sync --recursive && git submodule update --init --recursive'

Wenn Sie benutzerdefinierte Argumente weiterhin an git pull übergeben möchten, können Sie entweder eine Funktion im laufenden Betrieb definieren und aufrufen oder ein benutzerdefiniertes Skript verwenden. Der erste Ansatz würde so aussehen (wieder einzelne Zeile):

Nicht sehr lesbar, oder? Ich bevorzuge den benutzerdefinierten Skript-Ansatz., Angenommen, Sie würden eine git-Spull-Skriptdatei irgendwo in Ihren PFAD einfügen (ich habe ein ~/perso/bin-Verzeichnis in meinem PFAD, nur für solche Dinge):

#! /bin/bash
git pull "$@" &&
git submodule sync --recursive &&
git submodule update --init --recursive

Wir geben ihm dann Ausführungsrechte:

chmod +x git-spull

Und jetzt können wir es genauso verwenden, wie wir den Alias verwendet hätten.

Aktualisieren eines Submoduls an Ort und Stelle im Container

Dies ist der schwierigste Anwendungsfall, und Sie sollten sich so weit wie möglich davon fernhalten und die Wartung über das zentrale, dedizierte Repo bevorzugen.,

Es kann jedoch vorkommen, dass Submodul-Code außerhalb des Containercodes nicht getestet oder sogar kompiliert werden kann. Viele Themen und Plugins haben solche Einschränkungen.

Das erste, was zu verstehen ist, ist, weil Sie Commits machen werden, müssen Sie von einer richtigen Basis ausgehen, die ein Verzweigungstipp sein wird. Sie müssen daher überprüfen, ob die neuesten Commits des Zweigs Ihr Containerprojekt nicht „unterbrechen“. Wenn dies der Fall ist, klingt das Erstellen eines eigenen containerspezifischen Zweigs im Submodul verlockend, aber dieser Pfad führt zu einer starken Kopplung zwischen Submodul und Container, was nicht ratsam ist., Möglicherweise möchten Sie das „Submodulieren“ dieses Codes in diesem bestimmten Projekt beenden und ihn stattdessen wie alle regulären Inhalte einbetten.

Lassen Sie uns zugeben, dass Sie mit gutem Gewissen den aktuellen Master-Zweig des Submoduls hinzufügen können. Beginnen wir mit der Synchronisierung unseres lokalen Status auf der Fernbedienung:

Eine andere Möglichkeit wäre, aus dem Container-Repo den lokalen Zweig des Submoduls explizit über seinen verfolgten Remote-Zweig zu synchronisieren (einzelne Zeile oben, zuletzt — gefolgt von Leerzeichen):

Wir können jetzt den Code bearbeiten, ihn zum Laufen bringen, testen usw., Sobald wir fertig sind, können wir die beiden Commits und die beiden erforderlichen Pushs ausführen (es ist super einfach und in der Praxis allzu häufig, etwas davon zu vergessen).

Fügen wir einfach gefälschte Arbeit hinzu und machen die beiden zugehörigen Commits auf Submodul-und Containerebene:

Zu diesem Zeitpunkt besteht die größte Gefahr darin, das Submodul zu pushen. Sie kehren zum Containerprojekt zurück,verpflichten es und schieben nur den Container. Es ist ein einfacher Fehler, besonders in einer IDE oder GUI. Wenn Ihre Kollegen versuchen, Updates zu erhalten, bricht die Hölle los., Schauen Sie sich den ersten Schritt an:

Es gibt absolut keinen Hinweis darauf, dass Git das referenzierte Commit nicht von der Fernbedienung des Submoduls abrufen konnte. Der erste Hinweis darauf liegt im Status:

Beachten Sie die Warnung: Anscheinend ist das neu referenzierte Commit für das Submodul nirgends zu finden. In der Tat, wenn wir versuchen, das Arbeitsverzeichnis des Submoduls zu aktualisieren, erhalten wir:

main (master * u=) $ git submodule update
fatal: reference is not a tree: 12e3a529698c519b2fab790630f71bd531c45727
Unable to checkout '12e3a529698c519b2fab790630f71bd531c45727' in submodule path 'vendor/plugins/demo'

Sie können deutlich sehen, wie wichtig es ist, sich daran zu erinnern, das Submodul auch zu schieben, idealerweise bevor Sie den Container schieben., Lassen Sie uns das im Voraus tun und das Update erneut versuchen:

Ich sollte beachten, dass es eine CLI — Option gibt, mit der überprüft wird, ob derzeit referenzierte Submodul-Commits ebenfalls verschoben werden müssen, und wenn ja, werden sie gedrückt: Es ist git push-recurse-submodule=on-demand (zugegebenermaßen ein Bissen). Es muss jedoch etwas Container-Level haben, um es zum Laufen zu bringen: Nur Submodule schneiden es nicht.

Darüber hinaus (es gibt keine Konfigurationseinstellung dafür, sodass Sie Prozeduren um einen Alias standardisieren müssen, z. B. spush:) — ab Git 2.7.0 gibt es jetzt einen Push.,recurseSubmodules Konfigurationen Einstellung, die Sie definieren können (auf On-Demand oder Check).

git config --global alias.spush 'push --recurse-submodules=on-demand'

Entfernen eines Submoduls

Es gibt zwei Situationen, in denen Sie ein Submodul „entfernen“ möchten:

  • Sie möchten nur das Arbeitsverzeichnis löschen (möglicherweise vor dem Archivieren des Containers WD), möchten aber die Möglichkeit behalten, es später wiederherzustellen (es muss also darin bleiben .gitmodules und .git / modules);
  • Sie möchten es endgültig aus dem aktuellen Zweig entfernen.

Lassen Sie uns jeden Fall der Reihe nach sehen.,

Temporäres Entfernen eines Submoduls

Die erste Situation wird leicht von git submodule deinit behandelt. Überzeugen Sie sich selbst:

Dies hat keinerlei Auswirkungen auf den Containerstatus. Das Submodul ist nicht mehr lokal bekannt (es ist weg .git / config), so dass seine Abwesenheit aus dem Arbeitsverzeichnis unbemerkt bleibt. Wir haben immer noch das Verzeichnis vendor/plugins/demo, aber es ist leer; Wir könnten es ohne Konsequenzen entfernen.

Das Submodul darf dabei keine lokalen Änderungen haben, sonst müssten Sie den Aufruf erzwingen.,

Jeder spätere Unterbefehl des Git-Submoduls ignoriert dieses Submodul glückselig, bis Sie es erneut inittieren, da sich das Submodul nicht einmal in der lokalen Konfiguration befindet. Solche Befehle umfassen update, foreach und sync.

Andererseits bleibt das Submodul definiert in .gitmodules: Ein Init gefolgt von einem Update (oder einem einzelnen Update-init) wird es als neu wiederherstellen:

Ein Submodul dauerhaft entfernen

Dies bedeutet, dass Sie das Submodul endgültig entfernen möchten: Ein reguläres git rm reicht aus, genau wie für jeden anderen Teil des Arbeitsverzeichnisses., Dies funktioniert nur, wenn Ihr Submodul eine gitfile (a.git which is a file, not a directory), was ab Git 1.7.8 der Fall ist. Andernfalls müssen Sie dies von Hand handhaben (ich werde Ihnen sagen, wie am Ende).

Zusätzlich zum Entfernen des Submoduls aus dem Arbeitsverzeichnis, der Befehl aktualisiert die .gitmodules Datei, so dass es nicht mehr auf das Submodul verweist. Hier gehts:

Natürlich stolpern hier erweiterte Statusinformationen über sich selbst, weil die gitfile für das Submodul weg ist (eigentlich ist das gesamte Demo-Verzeichnis verschwunden).,

Was jedoch seltsam ist, ist, dass die lokale Konfiguration Submodulinformationen beibehält, im Gegensatz zu dem, was passiert, wenn Sie deinit. Für eine umfassende Entfernung empfehle ich Ihnen, beide nacheinander auszuführen, um sie ordnungsgemäß zu bereinigen (dies würde nach unserem vorherigen Befehl nicht funktionieren, da es gelöscht wurde .gitmodules ():

git submodule deinit path/to/module # ensure local config cleanup
git rm path/to/module # clean WD and .gitmodules

Unabhängig von Ihrem Ansatz bleibt das Repo des Submoduls in .git/modules/vendor/plugins / demo, aber Sie können das jederzeit beenden.

Wenn Sie jemals ein Submodul entfernen müssen, das vor Git 1.7 eingerichtet wurde.,8, und bettet daher seine .git-Verzeichnis direkt im Arbeitsverzeichnis des Containers (anstatt sich auf eine gitfile zu verlassen), müssen Sie den Bulldozer ausbrechen: Den beiden vorherigen Befehlen muss eine manuelle Ordnerentfernung vorausgehen, z. B. rm-fr vendor/plugins/demo, da diese Befehle immer das Löschen eines tatsächlichen Repositorys ablehnen.