Mir ist nicht klar, was das Folgende bedeutet (aus der Aktualisierung des Git-Submoduls Dokumentation):
…wird die Submodule HEAD abtrennen, es sei denn --rebase
oder --merge
angegeben…
Wie funktioniert --rebase
/--merge
Dinge ändern?
Mein Hauptanwendungsfall ist es, eine Reihe zentraler Repositories zu haben, die ich über Submodule in andere Repositories einbetten werde. Ich möchte in der Lage sein, diese zentralen Repositorys zu verbessern, entweder direkt an ihrem ursprünglichen Speicherort oder aus ihren eingebetteten Repositorys (denjenigen, die sie über Submodule verwenden).
- Kann ich innerhalb dieser Submodule Verzweigungen/Modifikationen erstellen und Push/Pull verwenden, so wie ich es in normalen Repositories tun würde, oder gibt es Dinge, bei denen man vorsichtig sein muss?
- Wie würde ich das Submodul, auf das verwiesen wird, von sagen wir (markiert) 1.0 auf 1.1 vorrücken (obwohl der Kopf des ursprünglichen Repositorys bereits bei 2.0 ist) oder auswählen, welches Commit des Zweigs überhaupt verwendet wird?
Dies GitPro-Seite fasst die Konsequenz eines Git-Submodul-Updates gut zusammen
Wenn du rennst git submodule update
, wird die spezifische Version des Projekts ausgecheckt, jedoch nicht innerhalb einer Verzweigung. Dies nennt man einen abgetrennten Kopf – es bedeutet, dass die HEAD-Datei direkt auf einen Commit verweist, nicht auf eine symbolische Referenz.
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, in diesem Submodul-Verzeichnis committen, ohne einen Zweig zum Arbeiten zu erstellen, und dann git submodule update erneut vom Superprojekt aus ausführen, ohne in der Zwischenzeit zu committen, wird Git Ihre Änderungen überschreiben, ohne es Ihnen mitzuteilen. Technisch gesehen verlieren Sie die Arbeit nicht, aber Sie haben keinen Zweig, der darauf zeigt, daher wird es etwas schwierig sein, sie abzurufen.
Hinweis März 2013:
Wie in „Git-Submodul-Tracking neuste“ erwähnt, kann ein Submodul jetzt (git1.8.2) einen Branch 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
Sehen “git submodule update --remote
vs git pull
“.
Die Antwort von MindTooth veranschaulicht ein manuelles Update (ohne lokale Konfiguration):
git submodule -q foreach git pull -q origin master
In beiden Fällen ändern sich dadurch die Submodulreferenzen (die gitlinkein spezieller Eintrag im übergeordneten Repo-Index), und Sie müssen diese Referenzen aus dem Haupt-Repo hinzufügen, festschreiben und pushen.
Wenn Sie dieses übergeordnete Repository das nächste Mal klonen, werden die Submodule gefüllt, um diese neuen SHA1-Referenzen widerzuspiegeln.
Der Rest dieser Antwort beschreibt die klassische Submodulfunktion (Verweis auf a Fest Commit, was der springende Punkt hinter dem Begriff eines Submoduls ist).
Um dieses Problem zu vermeiden, erstellen Sie einen Zweig, wenn Sie in einem Untermodulverzeichnis mit git checkout -b work oder etwas Äquivalentem arbeiten. Wenn Sie das Submodul-Update ein zweites Mal durchführen, wird Ihre Arbeit immer noch zurückgesetzt, aber zumindest haben Sie einen Zeiger, zu dem Sie zurückkehren können.
Das Wechseln von Zweigen mit darin enthaltenen Submodulen kann ebenfalls schwierig sein. Wenn Sie einen neuen Zweig erstellen, dort ein Submodul hinzufügen und dann zurück zu einem Zweig ohne dieses Submodul wechseln, haben Sie immer noch das Submodulverzeichnis als nicht verfolgtes Verzeichnis:
Also, um deine Fragen zu beantworten:
kann ich Verzweigungen/Änderungen erstellen und Push/Pull verwenden, so wie ich es in normalen Repos tun würde, oder gibt es Dinge, bei denen man vorsichtig sein muss?
Sie können einen Branch erstellen und Änderungen pushen.
ACHTUNG (ab Git-Submodul-Tutorial): Veröffentlichen (pushen) Sie immer die Änderung des Submoduls, bevor Sie die Änderung an das 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 auf das Submodul verwiesene Commit von sagen wir (markiert) 1.0 auf 1.1 vorrücken (obwohl der Kopf des ursprünglichen Repos bereits bei 2.0 ist)
Die Seite “Untermodule verstehen” kann helfen
Git-Submodule werden mit zwei beweglichen Teilen implementiert:
- der
.gitmodules
Datei und
- eine besondere Art von Baumobjekt.
Diese triangulieren zusammen eine bestimmte Revision eines bestimmten Repositorys, das an einem bestimmten Ort in Ihrem Projekt ausgecheckt wird.
Von dem git-Submodulseite
Sie können den Inhalt des Untermoduls nicht innerhalb des Hauptprojekts ändern
100% richtig: Sie können ein Submodul nicht ändern, sondern nur auf eines seiner Commits verweisen.
Aus diesem Grund müssen Sie, wenn Sie ein Untermodul innerhalb des Hauptprojekts ändern:
- müssen sich verpflichten und pushen innerhalb das Submodul (zum Upstream-Modul) und
- Gehen Sie dann in Ihr Hauptprojekt und führen Sie ein erneutes Commit durch (damit dieses Hauptprojekt auf das neue Submodul-Commit verweist, das Sie gerade erstellt und gepusht haben).
Ein Submodul ermöglicht es Ihnen, a komponentenbasierter Ansatz Entwicklung, wobei sich das Hauptprojekt nur auf bestimmte Commits anderer Komponenten bezieht (hier “andere als Submodule deklarierte Git-Repositories”).
Ein Untermodul ist ein Marker (Commit) für ein anderes Git-Repository, das nicht an den Hauptentwicklungszyklus des Projekts gebunden ist: Es (das „andere“ Git-Repository) kann sich unabhängig entwickeln.
Es ist Sache des Hauptprojekts, aus diesem anderen Repo den Commit auszuwählen, den es benötigt.
Wenn Sie jedoch möchten, aus Bequemlichkeiteines dieser Submodule direkt aus Ihrem Hauptprojekt heraus modifizieren, Git erlaubt Ihnen dies, sofern Sie dies tun Erste Veröffentlichen Sie diese Submodul-Modifikationen in ihrem ursprünglichen Git-Repo und dann Begehen Sie Ihr Hauptprojekt unter Bezugnahme auf a Neu Version des Submoduls.
Aber die Hauptidee bleibt: 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 Aufbau (das ist was Aufbau Management dreht sich alles um ein reines Versionskontrollsystem)
Wenn ein Bauteil wirklich entwickelt werden könnte zur selben Zeit als Ihr Hauptprojekt (da jede Änderung am Hauptprojekt eine Änderung des Unterverzeichnisses beinhalten würde und umgekehrt), dann wäre es kein “Untermodul” mehr, sondern eine Zusammenführung von Unterbäumen (auch in der Frage Übertragen von Legacy-Code dargestellt base von cvs zum verteilten Repository), die den Verlauf der beiden Git-Repositorys miteinander verknüpft.
Hilft das, die wahre Natur von Git-Submodulen zu verstehen?
Um jedes Submodul zu aktualisieren, könnten Sie den folgenden Befehl aufrufen (im Stammverzeichnis des Repositorys):
git submodule -q foreach git pull -q origin master
Sie können die entfernen -Q Möglichkeit, den gesamten Prozess zu verfolgen.
Um die anzusprechen --rebase
vs. --merge
Möglichkeit:
Angenommen, Sie haben das Super-Repository A und das Submodul B und möchten in Submodul B arbeiten. Sie haben Ihre Hausaufgaben gemacht und wissen das nach dem Anruf
git submodule update
Sie befinden sich in einem HEAD-losen Zustand, daher sind alle Commits, die Sie an diesem Punkt durchführen, schwer wieder zu erreichen. Sie haben also mit der Arbeit an einem neuen Zweig in Untermodul 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. Sie führen aus Gewohnheit die letzten Änderungen herunter und aktualisieren Ihre Submodule.
<in A>
git merge develop
git submodule update
Oh nein! Sie befinden sich wieder in einem kopflosen Zustand, wahrscheinlich weil B jetzt auf den SHA zeigt, der mit Bs neuem Tipp oder einem anderen Commit verknüpft ist. Wenn du nur hättest:
git merge develop
git submodule update --rebase
Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'
Jetzt wurde diese beste Idee aller Zeiten für B auf das neue Commit umgestellt, und was noch wichtiger ist, Sie befinden sich immer noch in Ihrem Entwicklungszweig für B, nicht in einem kopflosen Zustand!
(Die --merge
führt Änderungen von beforeUpdateSHA zu afterUpdateSHA in Ihren Arbeitszweig zusammen, anstatt Ihre Änderungen auf afterUpdateSHA umzubasieren.)
Git 1.8.2 bietet eine neue Option ,--remote
, die genau dieses Verhalten ermöglichen. Laufen
git submodule update --rebase --remote
ruft die neuesten Änderungen von Upstream in jedem Submodul ab, rebasiert sie und checkt die neueste Revision des Submoduls aus. Als die Dokumentation bringt es auf den Punkt:
–Fernbedienung
Diese Option gilt nur für den Update-Befehl. Anstatt den aufgezeichneten SHA-1 des Superprojekts zu verwenden, um das Submodul zu aktualisieren, verwenden Sie den Status des Remote-Tracking-Zweigs des Submoduls.
Das ist gleichbedeutend mit Laufen git pull
in jedem Untermodul, was im Allgemeinen genau das ist, was Sie wollen.
(Dies wurde aus dieser Antwort kopiert.)
Zum Thema “abgetrennter 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
30. Dezember 2009 um 10:39 Uhr
“Sie können den Inhalt des Untermoduls nicht innerhalb des Hauptprojekts ändern”: ja, wahr. Und ich habe meine Antwort bearbeitet, um diesen scheinbaren Widerspruch zu beleuchten (nicht modifizierbares Untermodul, das Sie immer noch aus dem Hauptprojekt-Repo modifizieren können!)
– VonC
30. Dezember 2009 um 14:04 Uhr