Close

Submodule: Kernkonzept, Workflows und Tipps

Porträtfoto von Nicola Paolucci
Nicola Paolucci

Developer Advocate


Durch die Arbeit mit Untermodulen in deiner Git-Entwicklung kannst du andere Projekte in deine Codebasis einschließen. Dabei werden deren Verläufe separat gehalten, aber gleichzeitig mit deinem synchronisiert. Dies ist eine praktische Methode zum Lösen der Probleme durch Fremdbibliotheken und Abhängigkeiten. Wie bei allem rund um Git ist die Vorgehensweise eigenwillig und erfordert ein wenig Lernaufwand, bevor sie kompetent angewendet werden kann. Es gibt bereits gute und detaillierte Informationen zu den Untermodulen, diese werde ich hier nicht wiederholen. Stattdessen werde ich ein paar interessante Punkte erläutern, mit denen du das Optimum aus dem Feature herausholen kannst.

Datenbanken
Zugehöriges Material

Verschieben eines vollständigen Git-Repositorys

Bitbucket-Logo
Lösung anzeigen

Git kennenlernen mit Bitbucket Cloud

Kernkonzept


Zuerst möchte ich kurz ein Kernkonzept der Untermodule erklären, dessen Verständnis die Arbeit mit ihnen erleichtern wird.

Untermodule werden nach dem genauen Commit verfolgt, der im übergeordneten Projekt angegeben ist, nicht nach einem Branch, einer Referenz oder einer anderen symbolischen Referenz.

Sie werden niemals automatisch aktualisiert, wenn das vom Untermodul angegebene Repository aktualisiert wird – nur wenn das übergeordnete Projekt aktualisiert wird. Wie im bereits erwähnten Kapitel Pro Git sehr deutlich zum Ausdruck gebracht:

Wenn du Änderungen vornimmst und einen Commit in dieses [submodule]-Unterverzeichnis durchführst, bemerkt das Superprojekt, dass sich der HEAD dort geändert hat, und zeichnet den genauen Commit auf, an dem du gerade arbeitest. Auf diese Weise können andere beim Klonen dieses Projekts die Umgebung genau nachbilden.

[...] Git-Untermodule [...] sind statisch. Sehr statisch. Mit Git-Untermodulen kannst du bestimmte Commits nachverfolgen – keine Branches, keine Referenzen, sondern einzelne Commits. Wenn du Commits zu einem Untermodul hinzufügst, ist das für das Superprojekt nicht nachvollziehbar. Wenn ein Modul oft geforkt wurde, wird das in den Git-Untermodulen nicht berücksichtigt. Es gibt ein Remote-Repository und der Verweis bezieht sich auf einen einzigen Commit. Alles bleibt unverändert, solange du das Superprojekt nicht aktualisierst.

Mögliche Workflows


Vor dem Hintergrund dieses Kernkonzepts wirst du verstehen, dass submodule einige Workflows gut und andere weniger optimal unterstützen. Es gibt mindestens drei Szenarien, in denen Untermodule eine gute Wahl sind:

  • Wenn eine Komponente oder ein Unterprojekt sich zu schnell ändert oder bevorstehende Änderungen nicht mit der API kompatibel sind, kannst du zur eigenen Sicherheit den Code in einen bestimmten Commit sperren.

  • Wenn eine Komponente nicht sehr oft aktualisiert wird und du sie als Anbieterabhängigkeit verfolgen möchtest. Ich mache das zum Beispiel bei meinen Vim-Plugins.

  • Wenn du einen Teil des Projekts an eine Drittpartei delegierst und deren Arbeitsergebnisse zu einem bestimmten Zeitpunkt oder beim Release integrieren möchtest. Dies funktioniert bei nicht zu häufigen Updates.

Danke an Finch für die gut erklärten Szenarien.

Einige nützliche Tipps


Mit der leistungsstarken Infrastruktur von Untermodulen kannst du nützliche Aufteilungen und Integrationen von Codebasen durchführen. Allerdings gibt es auch einfache Vorgänge ohne optimierte Verfahren oder umfangreichen Support der Befehlszeilenoberfläche.

Wenn du Git-Untermodule in deinem Projekt verwendest, bist du entweder bereits darauf gestoßen oder wirst es bald. Wenn dies geschieht, musst du die Lösung hierfür nachlesen. Immer wieder. Um dir Recherchezeit zu sparen: Instapaper, Evernote oder Old School setzen ein Lesezeichen für diese Seite (:D:D) und du bist für eine Weile versorgt.

Also, los geht's:

Wie ersetze ich ein Git-Untermodul mit meiner eigenen Fork?


Dies ist ein sehr häufiger Workflow: Du nutzt das Projekt von jemand anderem als Untermodul, aber nach einer Weile stellst du fest, dass du es anpassen musst, deshalb möchtest du das Projekt forken und das Untermodul durch deine eigene Fork ersetzen. Wie geht das?

Die Untermodule werden in .gitmodules gespeichert:

$ cat .gitmodules [submodule "ext/google-maps"] path = ext/google-maps url = git://git.naquadah.org/google-maps.git

Du kannst die URL einfach mit einem Texteditor bearbeiten und dann Folgendes ausführen:

$ git submodule sync

Dadurch wird .git/config aktualisiert, welches eine Kopie dieser Untermodul-Liste enthält. (Du könntest auch einfach den entsprechenden Abschnitt [submodule] von .git/config manuell bearbeiten.)

Referenz: Stack Overflow

Wie entferne ich ein Untermodul?


Dies ist relativ häufig notwendig, die Prozedur ist jedoch etwas kompliziert. So entfernst du ein Untermodul:

1. Lösche die entsprechende Zeile aus der .gitmodules-Datei.

2. Lösche den entsprechenden Abschnitt aus .git/config.

3. Führe git rm --cached path_to_submodule aus (kein Schrägstrich am Ende).

4. Committe und lösche die nun unverfolgten Untermoduldateien.

Referenz: Stack Overflow

Wie integriere ich ein Untermodul zurück in mein Projekt?


Oder mit anderen Worten: Wie hört ein Git-Untermodul auf, Untermodul zu sein? Wenn du lediglich den Code aus deinem Untermodul in das Haupt-Repository integrieren möchtest, musst du nur das Untermodul entfernen und die Dateien wieder dem Haupt-Repository hinzufügen:

1. Lösche die Referenz zu dem Untermodul aus dem Index, behalte aber die Dateien:

git rm --cached submodule_path (no trailing slash)

2. Lösche die Datei .gitmodules oder, wenn du mehr als ein Untermodul hast, bearbeite diese Datei und entferne das Untermodul aus der Liste:

git rm .gitmodules

3. Entferne den .git-Metadatenordner (und vergewissere dich, dass du ein Backup davon erstellt hast):

rm -rf submodule_path/.git

4. Füge das submodule zum Index des Haupt-Repositorys hinzu:

git add submodule_path git commit -m "remove submodule"

HINWEIS: Die obige Vorgehensweise führt zum Löschen des Untermodul-Verlaufs. Falls du also einen übereinstimmenden Verlauf deiner Untermodule beibehalten willst, musst du einen "Merge" durchführen. Wenn du mehr erfahren willst, verweise ich dich auf die sehr umfangreichen Informationen auf Stack Overflow.

Wie ignoriere ich Änderungen in Untermodulen?


Manchmal können deine submodules von selbst dirty werden. Wenn du beispielsweise git submodules verwendest, um deine Vim-Plugins zu verfolgen, können diese lokale Dateien wie helptags generieren oder ändern. Leider wird dich git status wegen dieser Änderungen nerven, auch wenn du überhaupt nicht an ihnen interessiert bist und sie auch gar nicht committen möchtest.

Die Lösung ist sehr einfach. Öffne die Datei .gitmodules im Stammverzeichnis deines Repositorys und füge für jedes Untermodul ignore = dirty hinzu, wie in diesem Beispiel:

[submodule ".vim/bundle/msanders-snipmate"] path = .vim/bundle/msanders-snipmate url = git://github.com/msanders/snipmate.vim.git ignore = dirty

Achtung! Fallstricke bei der Interaktion mit Remote-Repositorys


Wie wir auch im Git-Tutorial zu Untermodulen auf kernel.org erfahren, gilt es bei der Interaktion mit deinen Remote-Repositorys ein paar Dinge zu beachten.

Zunächst solltest du darauf achten, die Änderung am Untermodul immer vor den Änderungen am darauf verweisenden Superprojekt zu veröffentlichen. Das ist äußerst wichtig, denn ansonsten werden andere Entwicklern womöglich daran gehindert, das Repository zu klonen.

Außerdem solltest du immer alle deine Änderungen committen, bevor du git submodule update ausführst, denn andernfalls werden diese Änderungen überschrieben.

Fazit


Anhand dieser Erläuterungen solltest du nun in der Lage sein, viele der häufig genutzten, wiederkehrenden Workflows bei Untermodulen bewältigen zu können. In künftigen Blogposts werde ich Alternativen zu git submodule vorstellen.

Folge mir @durdn und dem großartigen Bitbucket-Team, wenn du mehr über DVCS erfahren willst.

Nicola Paolucci

Nicola is an all-round hacker who loves exploring and teaching bleeding edge technologies. He writes and talks about Git, development workflows, code collaboration and more recently about Docker. Prior to his current role as Developer Instigator at Atlassian he led software teams, built crowd sourcing applications for geo-spacial data, worked on huge e-commerce deployments. Little known facts about Nicola: he gesticulates a lot while speaking (being Italian), lives in Amsterdam and rides a Ducati.


Diesen Artikel teilen
Nächstes Thema

Lesenswert

Füge diese Ressourcen deinen Lesezeichen hinzu, um mehr über DevOps-Teams und fortlaufende Updates zu DevOps bei Atlassian zu erfahren.

Mitarbeiter arbeiten mit unzähligen Tools zusammen

Bitbucket-Blog

Abbildung: DevOps

DevOps-Lernpfad

Demo Den: Feature-Demos mit Atlassian-Experten

So funktioniert Bitbucket Cloud mit Atlassian Open DevOps

Melde dich für unseren DevOps-Newsletter an

Thank you for signing up