git submodule init: Submodule richtig initialisieren
Sie klonen ein Repository, das externe Bibliotheken als Submodule einbindet – doch die entsprechenden Ordner sind leer. Der Grund: Git lädt Submodule beim Klonen standardmäßig nicht mit herunter. git submodule init ist der erste von zwei Schritten, um das zu ändern. Nach diesem Text wissen Sie genau, was der Befehl tut, wo der Unterschied zu git submodule update liegt und wie Sie die häufigsten Stolperfallen vermeiden.
Was git submodule init genau macht
Ein Submodul ist ein Git-Repository innerhalb eines anderen Repositorys (dem sogenannten Superprojekt). Welche Submodule ein Projekt hat, steht in der versionierten Datei .gitmodules im Wurzelverzeichnis. Ein Eintrag sieht so aus:
[submodule "libs/vendor"]
path = libs/vendor
url = https://github.com/beispiel/vendor.git
git submodule init liest diese Einträge und kopiert sie in Ihre lokale Konfiguration .git/config. Erst dadurch ist das Submodul auf Ihrem Rechner „registriert”. Wichtig: Der Befehl lädt keinerlei Code herunter. Er trägt lediglich Namen und URL des Submoduls in .git/config ein – zum Beispiel als Schlüssel submodule.libs/vendor.url.
Dieser Zwischenschritt ist Absicht. Weil die URL nun in Ihrer lokalen Config steht, können Sie sie vor dem eigentlichen Download noch anpassen – etwa auf einen internen Mirror oder eine SSH-Adresse. Das ist der eigentliche Sinn der Trennung von „init” und „update”.
Der komplette Ablauf: init und update
Das Einbinden eines Submoduls besteht immer aus zwei Phasen: registrieren (init) und herunterladen (update).
Bei einem bereits geklonten Repository
Sie haben ein Repo geklont und stellen fest, dass die Submodul-Ordner leer sind:
git submodule init
git submodule update
git submodule update liest die in Phase 1 hinterlegte URL aus .git/config, klont das Submodul in den vorgesehenen Pfad und checkt exakt den Commit aus, den das Superprojekt gespeichert hat. Deshalb landet das Submodul anschließend in einem sogenannten detached HEAD – es zeigt auf einen festen Commit, nicht auf einen Branch. Das ist normal und beabsichtigt: So bleibt reproduzierbar, welcher Stand der Abhängigkeit zu Ihrem Projektstand gehört.
Beide Schritte lassen sich zusammenfassen:
git submodule update --init
Bei verschachtelten Submodulen (Submodule, die selbst Submodule enthalten) ergänzen Sie --recursive:
git submodule update --init --recursive
Beim Klonen alles in einem Schritt
Am bequemsten ist es, Submodule direkt beim Klonen mitzunehmen. Dann entfällt init als separater Aufruf:
git clone --recurse-submodules https://github.com/beispiel/projekt.git
Die Option --recurse-submodules steht in allen aktuellen Git-Versionen zur Verfügung; die Kurzform --recursive funktioniert weiterhin als Alias. Verwandtes zum Klonen und Aktualisieren finden Sie unter Was macht git fetch genau? und Ist git fetch und merge dasselbe wie pull?.
Nur bestimmte Submodule initialisieren
Sie müssen nicht alle Submodule aktivieren. Übergeben Sie einen Pfad, um gezielt einzelne zu registrieren:
git submodule init libs/vendor
git submodule update libs/vendor
Das ist praktisch bei großen Monorepos, in denen Sie nur einen Teil der Abhängigkeiten benötigen.
Wie sich .gitmodules und .git/config unterscheiden
Diese beiden Dateien werden oft verwechselt, obwohl der Unterschied zentral ist:
.gitmodulesliegt im Projekt und wird versioniert. Sie ist für alle Beteiligten identisch und definiert, welche Submodule existieren..git/configist rein lokal und wird nie eingecheckt. Erstgit submodule initschreibt die Submodul-URLs dorthin.
Daraus folgt eine typische Falle: Ändert jemand die URL in .gitmodules (etwa bei einem Umzug von GitHub zu GitLab), übernimmt git submodule init diese Änderung nicht, wenn der Eintrag in Ihrer .git/config bereits existiert. Dafür gibt es einen eigenen Befehl:
git submodule sync
git submodule sync überträgt die aktuelle URL aus .gitmodules in Ihre lokale Config. Danach greift git submodule update wieder auf die richtige Quelle zu.
Nützliche Befehle rund um Submodule
git submodule status– zeigt Commit-Hash und Zustand jedes Submoduls. Ein-am Zeilenanfang bedeutet „nicht initialisiert”, ein+„ausgecheckter Commit weicht vom gespeicherten ab”. Siehe auch Wie überprüfe ich den aktuellen Git-Status?.git submodule update --remote– holt den neuesten Commit des in.gitmoduleshinterlegten Branches, statt am fest gespeicherten Commit zu bleiben.git submodule deinit <pfad>– machtinitrückgängig: entfernt den Eintrag aus.git/configund leert das Arbeitsverzeichnis des Submoduls. Mit--allfür alle Submodule.git config submodule.recurse true– sorgt dafür, dass Befehle wiegit pullundgit checkoutautomatisch in Submodule hineinlaufen. Das erspart viele vergessene Updates.
Typische Fehler und ihre Lösung
„Submodule … not initialized. Maybe you want to use ‘update —init’?”
Sie haben git submodule update ohne vorheriges init ausgeführt. Lösung: git submodule update --init verwenden.
Submodul-Ordner bleibt nach dem Klonen leer.
--recurse-submodules wurde beim Klonen vergessen. Holen Sie es nach mit git submodule update --init --recursive.
URL-Änderung in .gitmodules wird ignoriert.
Ihre lokale .git/config enthält noch die alte URL. Führen Sie git submodule sync aus und danach erneut git submodule update.
Nach einem git pull zeigt das Submodul auf den alten Stand.
Das Superprojekt speichert nur einen Zeiger auf einen Commit; ein pull im Hauptprojekt aktualisiert das Submodul nicht automatisch. Führen Sie anschließend git submodule update aus – oder aktivieren Sie submodule.recurse (siehe oben).
FAQ
Muss ich git submodule init bei jedem Klonen ausführen?
Nein. Wenn Sie mit git clone --recurse-submodules klonen, erledigt Git init und update automatisch. Der separate Aufruf ist nur nötig, wenn Sie ein bereits geklontes Repo nachträglich um Submodule ergänzen oder gezielt einzelne aktivieren wollen.
Was ist der Unterschied zwischen git submodule init und git submodule update?
init registriert die Submodule lokal, indem es die URLs aus .gitmodules in .git/config kopiert – ohne Download. update klont dann den Code und checkt den vom Superprojekt gespeicherten Commit aus. Ohne init weiß update nicht, woher es das Submodul beziehen soll.
Warum befindet sich mein Submodul in einem „detached HEAD”?
Weil das Superprojekt einen exakten Commit referenziert, nicht einen Branch. git submodule update checkt genau diesen Commit aus. Wollen Sie im Submodul weiterarbeiten, wechseln Sie mit git checkout <branch> auf einen Branch. Mehr dazu unter Wie checke ich einen Commit in Git aus?.