Git Submodul Update

242

Mir ist nicht klar, was Folgendes bedeutet (aus der Dokumentation zum Git-Submodul-Update ):

... wird die Submodule HEAD abgelöst machen, es sei denn --rebaseoder --mergeangegeben ist ...

Wie funktioniert --rebase/ --mergeDinge ändern?

Mein Hauptanwendungsfall besteht darin, eine Reihe zentraler Repositorys zu haben, die ich über Submodule in andere Repositorys einbetten werde. Ich möchte in der Lage sein, diese zentralen Repositorys entweder direkt an ihrem ursprünglichen Speicherort oder innerhalb ihrer eingebetteten Repositorys (die sie über das Submodul verwenden) zu verbessern.

  • Kann ich innerhalb dieser Submodule Zweige / Änderungen erstellen und Push / Pull wie in normalen Repositorys verwenden, oder gibt es Dinge, bei denen ich vorsichtig sein muss?
  • Wie würde ich das Submodul-referenzierte Commit von beispielsweise (markiert) 1.0 auf 1.1 vorrücken (obwohl der Kopf des ursprünglichen Repositorys bereits auf 2.0 steht) oder auswählen, welches Commit des Zweigs überhaupt verwendet wird?
tiefes Blau
quelle
Zum Thema " Abgelöster Kopf" siehe auch stackoverflow.com/questions/964876/head-and-orighead-in-git und stackoverflow.com/questions/237408/… für ein praktisches Beispiel (nicht submodulbezogen, aber dennoch )
VonC
"Sie können den Inhalt des Submoduls nicht innerhalb des Hauptprojekts ändern": Ja, wahr. Und ich habe meine Antwort bearbeitet, um etwas Licht in diesen offensichtlichen Widerspruch zu bringen (nicht modifizierbares Submodul, das Sie noch aus dem Hauptprojekt-Repo modifizieren können!)
VonC

Antworten:

304

Diese GitPro-Seite fasst die Konsequenzen eines Git-Submodul-Updates gut zusammen

Wenn Sie ausführen git submodule update, wird die spezifische Version des Projekts ausgecheckt, jedoch nicht innerhalb eines Zweigs. Dies wird als abgetrennter Kopf bezeichnet. Dies bedeutet, dass die HEAD-Datei direkt auf ein Commit und nicht auf eine symbolische Referenz verweist.
Das Problem ist, dass Sie im Allgemeinen nicht in einer Umgebung mit getrenntem Kopf arbeiten möchten, da Änderungen leicht verloren gehen können .
Wenn Sie ein erstes Submodul-Update durchführen, ein Commit in diesem Submodul-Verzeichnis durchführen, ohne einen Zweig zu erstellen, in dem gearbeitet werden soll, und dann das Git-Submodul-Update erneut aus dem Superprojekt ausführen, ohne in der Zwischenzeit ein Commit durchzuführen, überschreibt Git Ihre Änderungen, ohne es Ihnen mitzuteilen. Technisch gesehen werden Sie die Arbeit nicht verlieren, aber Sie werden keinen Zweig haben, der darauf zeigt, so dass es etwas schwierig sein wird, sie abzurufen.


Anmerkung März 2013:

Wie unter " Neueste Verfolgung des Git-Submoduls " erwähnt, kann ein Submodul jetzt (git1.8.2) einen Zweig verfolgen.

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 
# or (with rebase)
git submodule update --rebase --remote

Siehe " git submodule update --remotevsgit pull ".

Die Antwort von MindTooth zeigt ein manuelles Update (ohne lokale Konfiguration):

git submodule -q foreach git pull -q origin master

In beiden Fällen werden dadurch die Submodulreferenzen (der Gitlink , ein spezieller Eintrag im übergeordneten Repo-Index ) geändert , und Sie müssen diese Referenzen aus dem Haupt-Repo hinzufügen, festschreiben und verschieben.
Wenn Sie das nächste Mal dieses übergeordnete Repo klonen, werden die Submodule gefüllt, um diese neuen SHA1-Referenzen wiederzugeben.

Der Rest dieser Antwort beschreibt die klassische Submodul-Funktion (Verweis auf ein festes Commit, das der springende Punkt hinter dem Begriff eines Submoduls ist).


Um dieses Problem zu vermeiden, erstellen Sie einen Zweig, wenn Sie in einem Submodulverzeichnis mit git checkout -b work oder etwas Ähnlichem arbeiten. Wenn Sie das Submodul-Update ein zweites Mal durchführen, wird Ihre Arbeit immer noch zurückgesetzt, aber Sie haben zumindest einen Zeiger, zu dem Sie zurückkehren können.

Das Wechseln von Zweigen mit Submodulen kann ebenfalls schwierig sein. Wenn Sie einen neuen Zweig erstellen, dort ein Submodul hinzufügen und dann zu einem Zweig ohne dieses Submodul zurückkehren, haben Sie das Submodulverzeichnis weiterhin als nicht verfolgtes Verzeichnis:


Um Ihre Fragen zu beantworten:

Kann ich Zweige / Modifikationen erstellen und Push / Pull wie in normalen Repos verwenden, oder gibt es Dinge, bei denen ich vorsichtig sein muss?

Sie können einen Zweig erstellen und Änderungen vornehmen.

WARNUNG (aus dem Git-Submodul-Tutorial ): Veröffentlichen (pushen) Sie immer die Submoduländerung, bevor Sie die Änderung in dem Superprojekt veröffentlichen (pushen), das darauf verweist. Wenn Sie vergessen, die Änderung des Submoduls zu veröffentlichen, können andere das Repository nicht klonen.

Wie würde ich das Submodul-referenzierte Commit von beispielsweise (markiert) 1.0 auf 1.1 vorrücken (obwohl der Kopf des ursprünglichen Repos bereits bei 2.0 liegt)?

Die Seite " Grundmodule verstehen " kann helfen

Git-Submodule werden mit zwei beweglichen Teilen implementiert:

  • die .gitmodulesDatei und
  • eine besondere Art von Baumobjekt.

Diese zusammen triangulieren eine bestimmte Revision eines bestimmten Repositorys, die an einem bestimmten Ort in Ihrem Projekt ausgecheckt wird.


Von der Git-Submodul-Seite

Sie können den Inhalt des Submoduls nicht im Hauptprojekt ändern

100% korrekt: Sie können ein Submodul nicht ändern, sondern nur auf einen seiner Commits verweisen.

Wenn Sie ein Submodul innerhalb des Hauptprojekts ändern, haben Sie folgende Gründe:

  • müssen innerhalb des Submoduls (zum Upstream-Modul) festschreiben und pushen , und
  • Gehen Sie dann in Ihrem Hauptprojekt nach oben und schreiben Sie es erneut fest (damit sich das Hauptprojekt auf das neue Submodul-Commit bezieht, das Sie gerade erstellt und gepusht haben).

Ein Submodul ermöglicht Ihnen eine komponentenbasierte Ansatzentwicklung , bei der sich das Hauptprojekt nur auf bestimmte Commits anderer Komponenten bezieht (hier "andere Git-Repositorys, die als Submodule deklariert sind").

Ein Submodul ist ein Marker (Commit) für ein anderes Git-Repository, das nicht an den Hauptprojektentwicklungszyklus gebunden ist: Es (das "andere" Git-Repo) kann sich unabhängig voneinander entwickeln.
Es ist Sache des Hauptprojekts, aus dem anderen Repo das Commit auszuwählen, das es benötigt.

Allerdings sollten Sie wollen, aus Bequemlichkeit , modifizieren eines dieses Submodule direkt von Ihrem Hauptprojekt ermöglicht Git Sie das zu tun, vorausgesetzt , Sie zuerst diese Submodul Änderungen an den ursprünglichen Git Repo veröffentlichen und dann Hauptprojekt übertragen beziehen zu eine neue Version des Submoduls.

Die Hauptidee bleibt jedoch: Verweisen auf bestimmte Komponenten, die:

  • haben ihren eigenen Lebenszyklus
  • haben ihre eigenen Tags
  • haben ihre eigene Entwicklung

Die Liste der spezifischen Commits, auf die Sie sich in Ihrem Hauptprojekt beziehen, definiert Ihre Konfiguration ( darum geht es bei Configuration Management, nur um das Versionskontrollsystem ).

Wenn eine Komponente wirklich zur gleichen Zeit wie Ihr Hauptprojekt entwickelt werden könnte (da jede Änderung am Hauptprojekt das Ändern des Unterverzeichnisses beinhalten würde und umgekehrt), wäre es kein "Submodul" mehr, sondern ein Teilbaumzusammenführung (auch in der Frage Übertragen der Legacy-Codebasis von Lebensläufen in ein verteiltes Repository dargestellt ), die den Verlauf der beiden Git-Repos miteinander verknüpft.

Hilft das, die wahre Natur von Git-Submodulen zu verstehen?

VonC
quelle
77
Beeindruckend. So lange sollte eine Erklärung für etwas, das hauptsächlich so einfach ist, ausreichen, um jeden Neuling dazu zu bringen, sich nur an seine svn: externals zu halten. ;-)
Conny
2
@conny: aber wie ich in " Warum sind Git-Submodule nicht mit SVN-Externals kompatibel? " ausführlich erläutere , unterscheiden sich Submodule grundlegend und sind nicht kompatibel mit svn:externals.
VonC
1
Tut mir leid, um meine eigene Frage zu beantworten, sammle ich CDs im Submodul und git checke einen sha aus, oder git pull / fetch reicht aus. Anschließend wird das Update im lokalen Repository festgeschrieben.
Henrik
2
@hced: Sie können auch alle Submodule auf einmal mitgit submodule foreach
Dav Clark
1
.. immer noch nicht bekommen. Gibt es irgendwo im Internet eine einfachere Erklärung?
Eugene
135

Um jedes Submodul zu aktualisieren, können Sie den folgenden Befehl (im Stammverzeichnis des Repositorys) aufrufen:

git submodule -q foreach git pull -q origin master

Sie können die Option -q entfernen , um den gesamten Vorgang zu verfolgen.

MindTooth
quelle
15
Wenn Sie nur git submodule update --init --recursivevom Stamm ausführen , werden alle rekursiv abgerufen und initialisiert, sofern dies noch nicht geschehen ist.
Sam Soffes
10
@SamSoffes Das dient einem ganz anderen Zweck. Durch das Aktualisieren von Submodulen werden die Submodule bei dem Commit überprüft, auf das sie derzeit verweisen (nicht unbedingt das letzte Commit). Die Lösung in der obigen Antwort aktualisiert das Commit jedes Submoduls auf den neuesten HEAD von Ursprung / Master.
Indragie
7
Meine neue Methode:git submodule update --rebase --remote
MindTooth
19

So adressieren Sie die Option --rebasevs.--merge

Angenommen, Sie haben Super-Repository A und Submodul B und möchten einige Arbeiten in Submodul B ausführen. Sie haben Ihre Hausaufgaben gemacht und wissen das nach dem Aufruf

git submodule update

Sie befinden sich in einem Zustand ohne KOPF, daher ist es schwierig, auf Commits zurückzugreifen, die Sie zu diesem Zeitpunkt ausführen. Sie haben also mit der Arbeit an einem neuen Zweig in Submodul B begonnen

cd B
git checkout -b bestIdeaForBEver
<do work>

In der Zwischenzeit hat jemand anderes in Projekt A entschieden, dass die neueste und beste Version von B wirklich das ist, was A verdient. Aus Gewohnheit führen Sie die letzten Änderungen zusammen und aktualisieren Ihre Submodule.

<in A>
git merge develop
git submodule update

Oh nein! Sie sind wieder in einem kopflosen Zustand, wahrscheinlich weil B jetzt auf die SHA zeigt, die mit dem neuen Tipp von B oder einem anderen Commit verbunden ist. Wenn Sie nur hätten:

git merge develop
git submodule update --rebase

Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'

Jetzt wurde die beste Idee für B auf das neue Commit übertragen, und was noch wichtiger ist, Sie befinden sich immer noch in Ihrem Entwicklungszweig für B, nicht in einem kopflosen Zustand!

( --mergeDadurch werden Änderungen von beforeUpdateSHA zu afterUpdateSHA in Ihrem Arbeitszweig zusammengeführt, anstatt Ihre Änderungen auf afterUpdateSHA neu zu gründen.)

robinspb
quelle
7

Git 1.8.2 bietet eine neue Option, --remotedie genau dieses Verhalten ermöglicht. Laufen

git submodule update --rebase --remote

ruft die neuesten Änderungen von Upstream in jedem Submodul ab, stützt sie neu und überprüft die neueste Version des Submoduls. Wie die Dokumentation es ausdrückt:

--Fernbedienung

Diese Option ist nur für den Aktualisierungsbefehl gültig. Verwenden Sie den Status des Fernverfolgungszweigs des Submoduls, anstatt den aufgezeichneten SHA-1 des Superprojekts zum Aktualisieren des Submoduls zu verwenden.

Dies entspricht der Ausführung git pullin jedem Submodul, was im Allgemeinen genau das ist, was Sie wollen.

(Dies wurde aus dieser Antwort kopiert .)

Iulian Onofrei
quelle
Wenn Sie sich entscheiden, eine ältere Frage zu beantworten, die gut etablierte und korrekte Antworten enthält, erhalten Sie möglicherweise keine Gutschrift, wenn Sie spät am Tag eine neue Antwort hinzufügen. Wenn Sie einige unverwechselbare neue Informationen haben oder davon überzeugt sind, dass die anderen Antworten alle falsch sind, fügen Sie auf jeden Fall eine neue Antwort hinzu, aber "noch eine Antwort", die die gleichen grundlegenden Informationen lange nach dem Stellen der Frage liefert, ist normalerweise gewonnen. " Sie verdienen nicht viel Kredit. Es gibt keine Erklärung dafür - nicht einmal einen Link zu externer Dokumentation (was nicht ausreichen würde).
Jonathan Leffler
2
Es ist keine "noch eine andere Antwort", da KEINE andere Antwort diesen Befehl hat (beweise mir das Gegenteil). Andere Antworten haben bei mir nicht funktioniert, dieser Kommentar hat funktioniert, daher habe ich beschlossen, ihn als Antwort zu veröffentlichen und dem ursprünglichen Eigentümer die Ehre zu erweisen. Entfernen Sie also Ihre Downvote.
Iulian Onofrei
Es gibt einen Kommentar von MindTooth aus dem Jahr 2015, der besagt, dass sie dies jetzt tun. Sie geben keine Erklärung dafür, was dies bewirkt (obwohl Sie MindTooth erwähnen, aber es gibt keine wirkliche Erklärung dafür, was Sie damit meinen - das Einbetten von URLs, wie in diesem Kommentar, würde helfen). Sie sagen nicht, warum es eine gute Idee ist. Sie geben keine Vorbehalte. Dies ist meiner Ansicht nach keine hilfreiche Antwort, da mehr Fragen aufgeworfen als gelöst werden.
Jonathan Leffler
1
Damit meinte ich, dass es funktioniert, anstatt nicht zu funktionieren. Glauben Sie mir, wenn mehr Menschen diese Antwort sehen würden, wären sie froh, weil sie funktioniert . Für solche Dinge möchten die meisten Leute nur den Befehl kennen, der ein Git-Submodul aktualisiert, und nicht, wie es implementiert ist.
Iulian Onofrei
Ich habe die Antwort bearbeitet, um zu beweisen, dass Sie falsch liegen. Stackoverflow.com/questions/1979167/git-submodule-update/… !!!
Iulian Onofrei