Close

Git subtree: die Alternative zum Git-Submodul

Porträtfoto von Nicola Paolucci
NICOLA PAOLUCCI

Developer Advocate


Im Internet finden sich unzählige Artikel dazu, warum du keine Git-Submodule verwenden solltest. Submodule sind zwar für einige Anwendungsfälle nützlich, haben aber mehrere Nachteile.

Gibt es Alternativen? Allerdings! Zwei (wenn nicht mehr) Tools helfen dir, den Verlauf von Software-Abhängigkeiten in deinem Projekt nachzuverfolgen, während du deine Arbeit mit Git fortsetzt:

  • git subtree
  • Google Repo

In diesem Blogpost werfen wir einen Blick auf git subtree und erklären, warum es zwar nicht perfekt, aber immerhin viel besser als git submodule ist.

Was ist git subtree und warum sollte ich es nutzen?


Mit git subtree kannst du ein Repository als Unterverzeichnis in einem anderen verschachteln. Dies ist eine von mehreren Möglichkeiten, wie Git-Projekte Projektabhängigkeiten verwalten können.

Vorher/Nachher-Diagramm von git subtree

Warum du vielleicht git subtree in Betracht ziehen solltest:

  • Das Management eines einfachen Workflows ist kinderleicht.
  • Ältere Git-Versionen werden unterstützt (sogar Versionen vor 1.5.2).
  • Der Code des Unterprojekts steht bereit, sobald der Klon des Superprojekts erstellt worden ist.
  • Mit git subtree müssen Benutzer deines Repositorys nichts Neues dazulernen. Sie können Abhängigkeiten verwalten, ohne überhaupt zu wissen, dass du git subtree verwendest.
  • Mit git subtree werden anders als bei Git-Submodulen (d. h. .gitmodule) keine neuen Dateien mit Metadaten hinzugefügt.
  • Inhalte des Moduls können bearbeitet werden, ohne dass eine separate Repository-Kopie der Abhängigkeit an einem anderen Ort benötigt wird.

Nachteile (aber unserer Meinung nach sind sie weitgehend akzeptabel):

  • Du musst eine neue Merge-Strategie lernen (nämlich git subtree).
  • Codebeiträge zum Upstream für Unterprojekte sind ein bisschen komplizierter.
  • Die Verantwortung, Code von über- und untergeordneten Projekten in Commits nicht zu vermischen, liegt bei dir.
Datenbanken
Zugehöriges Material

Verschieben eines vollständigen Git-Repositorys

Bitbucket-Logo
Lösung anzeigen

Git kennenlernen mit Bitbucket Cloud

Wie wird git subtree verwendet?


git subtree ist in verfügbaren Git-Versionen ab 1.7.11 seit Mai 2012 integriert. Subtree wird in der von Homebrew installierten Version auf OS X bereits richtig eingepasst. Bei einigen anderen Plattformen musst du die Installationsanweisungen beachten.

Hier ist ein klassisches Beispiel für die Nachverfolgung eines Vim-Plug-ins mit git subtree.

Die schnelle Lösung ohne Remote-Verfolgung

Wenn du nur ein paar Einzeiler zum Kopieren und Einfügen brauchst, lies einfach diesen Abschnitt. Füge git subtree zu einem bestimmten prefix-Ordner hinzu:

git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash

(Üblicherweise speichert man nicht den gesamten Verlauf des Unterprojekts im Haupt-Repository (main). Wenn du das aber tun willst, musst du nur den Flag --squash auslassen.)

Der obige Befehl führt zu dieser Ausgabe:

git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git main
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 338 (delta 101), reused 323 (delta 89)
Receiving objects: 100% (338/338), 71.46 KiB, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround.git
* branch main -} FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'

Wie du siehst, wird hier ein Merge-Commit dokumentiert, wobei der gesamte Verlauf des vim-surround-Repositorys in einen einzigen Commit gesquasht wird:

1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]
ca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]

Wenn du den Plug-in-Code später vom Upstream-Repository aktualisieren willst, geht das nur mit einem git subtree-Pull:

git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash

Dies ist sehr kurz und schmerzlos, aber die Befehle sind relativ lang und schwer zu merken. Wir können die Befehle verkürzen, indem wir das Unterprojekt als Remote hinzufügen.

Hinzufügen des Unterprojekts als Remote

Wenn wir den Unterbaum als Remote hinzufügen, können wir in verkürzter Form auf ihn verweisen:

git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git

Jetzt können wir den Unterbaum (wie vorhin auch) hinzufügen, aber wir verweisen auf den Remote in Kurzform.

git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash

Der Befehl zur Aktualisierung des Unterprojekts zu einem späteren Zeitpunkt lautet dann folgendermaßen:

git fetch tpope-vim-surround main
git subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash

Beitragen zum Upstream

Wir können nun uneingeschränkt unsere Korrekturen an das Unterprojekt in unserem lokalen Arbeitsverzeichnis committen. Wenn dein Code soweit ist, zurück in das Upstream-Projekt gepusht zu werden, müssen wir das Projekt zunächst abspalten und dann als weiteren Remote hinzufügen:

git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git

Jetzt können wir den Befehl subtree push wie hier ausführen:

git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround main
git push using: durdn-vim-surround main
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/durdn/vim-surround.git
02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} main

Anschließend können wir eine Pull-Anfrage an den Maintainer des Pakets senden.

Kann ich das tun, ohne den git subtree-Befehl zu verwenden?

Ja, das kannst du! git subtree gehört nicht zur Subtree-Merge-Strategie. Du kannst die Merge-Strategie auch dann anwenden, wenn git subtree aus irgendeinem Grund nicht verfügbar ist. So gehst du dabei vor:

Füge die Abhängigkeit einfach mit git remote hinzu:

git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git

Bevor die Inhalte der Abhängigkeit in das Repository eingelesen werden, muss der Merge unbedingt dokumentiert werden, damit wir den gesamten Baumverlauf des Plug-ins bis zu diesem Punkt verfolgen können:

git merge -s ours --no-commit tpope-vim-surround/main

Die daraus resultierende Ausgabe lautet:

Automatic merge went well; stopped before committing as requested

Daraufhin lesen wir den Inhalt des neuesten Baumobjekts in das Plug-in-Repository in unserem Arbeitsverzeichnis ein, das bereit für einen Commit ist:

git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/main

Jetzt können wir den Commit durchführen (dabei handelt es sich um einen Merge-Commit, bei dem der Verlauf des eingelesenen Baums erhalten bleibt).

git ci -m"[subtree] adding tpope-vim-surround"
[stree 779b094] [subtree] adding tpope-vim-surround

Zum Aktualisieren des Projekts können wir nun einen Pull unter Verwendung der git subtree-Merge-Strategie durchführen:

git pull -s subtree tpope-vim-surround main

git subtree ist eine großartige Alternative


Wenn du Git-Submodule eine Weile verwendet hast, wirst du feststellen, dass git subtree viele Probleme mit dem Git-Submodul löst. Wie immer muss man bei Git eine Lernkurve durchlaufen, um die Funktion bestmöglich nutzen zu können.

Folge mir auf Twitter @durdn, wenn du mehr über Git erfahren möchtest. Und sieh dir Atlassian Bitbucket an, wenn du nach einem guten Tool zur Verwaltung deiner Git-Repositorys suchst.

Update: Nach Veröffentlichung dieses Beitrags habe ich auch einen Artikel über die Vorteile von git subtree geschrieben.

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