Ich habe ein Projekt mit einem Git-Submodul. Es stammt von einer ssh: // ... -URL und befindet sich auf Commit A. Commit B wurde auf diese URL verschoben, und ich möchte, dass das Submodul das Commit abruft und zu diesem wechselt.
Mein Verständnis ist, dass dies git submodule update
getan werden sollte, aber es tut es nicht. Es macht nichts (keine Ausgabe, Erfolgs-Exit-Code). Hier ist ein Beispiel:
$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...
Ich habe auch versucht git fetch mod
, das einen Abruf zu tun erscheint (aber kann unmöglich, weil es nicht für ein Kennwort eingeben müssen !), Aber git log
und git show
leugnen die Existenz von neuen Commits. Bisher habe ich rm
das Modul nur bearbeitet und erneut hinzugefügt, aber dies ist im Prinzip sowohl falsch als auch in der Praxis mühsam.
git
git-submodules
git-pull
Thanatos
quelle
quelle
--remote
Option die Funktionalität verfügt, die Sie benötigen , wäre es vielleicht nützlich, dies als akzeptierte Antwort und nicht als "von Hand" -Ansatz in Jasons Antwort zu markieren.--remote
ist zu diesem Zeitpunkt definitiv eine bessere Lösung, und da diese Frage von einem Github Gist zu Submodulen verknüpft wurde, halte ich es für besser, wenn eingehende Leser die neue Antwort sehen.hunter2
Passwort: o)Antworten:
Der
git submodule update
Befehl teilt Git tatsächlich mit, dass Ihre Submodule jedes Mal das Commit auschecken sollen, das bereits im Index des Superprojekts angegeben ist. Wenn Sie Ihre Submodule auf das neueste Commit aktualisieren möchten , das von ihrer Fernbedienung verfügbar ist, müssen Sie dies direkt in den Submodulen tun.Also zusammenfassend:
Oder wenn Sie beschäftigt sind:
quelle
git submodule foreach git pull
git submodule foreach git pull origin master
.git submodule foreach --recursive git pull origin master
.-a
Schalter fürgit commit
" Weist den Befehl an, Dateien, die geändert und gelöscht wurden, automatisch bereitzustellen , aber neue Dateien, von denen Sie Git nichts erzählt haben, sind nicht betroffen."Git 1.8.2 bietet eine neue Option,
--remote
die genau dieses Verhalten ermöglicht. Laufenruft die neuesten Änderungen aus dem Upstream in jedem Submodul ab, führt sie zusammen und überprüft die neueste Version des Submoduls. Wie die Dokumentation es ausdrückt:
Dies entspricht der Ausführung
git pull
in jedem Submodul, was im Allgemeinen genau das ist, was Sie wollen.quelle
git pull
in jedem Submodul" Zur Verdeutlichung gibt es keinen Unterschied (aus Sicht des Benutzers) zwischen Ihrer Antwort undgit submodule foreach git pull
?foreach git pull
hat sie nur ausgecheckt, aber den Zeiger des Haupt-Repos nicht aktualisiert, um auf das neuere Commit des Submoduls zu verweisen. Nur--remote
damit wurde auf das letzte Commit hingewiesen.Führen Sie in Ihrem übergeordneten Projektverzeichnis Folgendes aus:
Oder wenn Sie rekursive Submodule ausführen lassen:
Manchmal funktioniert dies immer noch nicht, weil Sie lokale Änderungen im lokalen Submodulverzeichnis haben, während das Submodul aktualisiert wird.
In den meisten Fällen ist die lokale Änderung möglicherweise nicht diejenige, die Sie festschreiben möchten. Dies kann aufgrund eines Löschens einer Datei in Ihrem Submodul usw. geschehen. Wenn dies der Fall ist, führen Sie einen Reset in Ihrem lokalen Submodulverzeichnis und in Ihrem übergeordneten Projektverzeichnis erneut aus:
quelle
Ihr Hauptprojekt weist auf ein bestimmtes Commit hin, bei dem sich das Submodul befinden sollte.
git submodule update
versucht, dieses Commit in jedem initialisierten Submodul zu überprüfen. Das Submodul ist wirklich ein unabhängiges Repository - nur ein neues Commit im Submodul zu erstellen und das zu pushen ist nicht genug. Sie müssen auch die neue Version des Submoduls explizit im Hauptprojekt hinzufügen.In Ihrem Fall sollten Sie also das richtige Commit im Submodul finden - nehmen wir an, das ist der Tipp von
master
:Kehren Sie nun zum Hauptprojekt zurück, stellen Sie das Submodul bereit und legen Sie Folgendes fest:
Schieben Sie nun Ihre neue Version des Hauptprojekts:
Wenn ab diesem Zeitpunkt jemand anderes sein Hauptprojekt
git submodule update
aktualisiert, aktualisiert er für ihn das Submodul, sofern es initialisiert wurde.quelle
Es scheint, als würden in dieser Diskussion zwei verschiedene Szenarien miteinander vermischt:
Szenario 1
Mit den Zeigern meines übergeordneten Repositorys auf Submodule möchte ich das Commit in jedem Submodul überprüfen, auf das das übergeordnete Repository verweist, möglicherweise nachdem ich zuerst alle Submodule durchlaufen und diese von Remote aktualisiert / abgerufen habe.
Dies ist, wie bereits erwähnt, erledigt
Szenario 2, das meiner Meinung nach das Ziel von OP ist
In einem oder mehreren Submodulen sind neue Dinge passiert, und ich möchte 1) diese Änderungen übernehmen und 2) das übergeordnete Repository so aktualisieren, dass es auf das (neueste) HEAD-Commit dieses / dieser Submodule verweist.
Dies würde von erledigt werden
Nicht sehr praktisch, da Sie n Pfade zu allen n Submodulen in z. B. einem Skript fest codieren müssten, um die Festschreibungszeiger des übergeordneten Repositorys zu aktualisieren.
Es wäre cool, eine automatisierte Iteration durch jedes Submodul zu haben und den übergeordneten Repository-Zeiger (mit
git add
) zu aktualisieren , um auf den Kopf des Submoduls (der Submodule) zu zeigen.Dafür habe ich dieses kleine Bash-Skript erstellt:
git-update-submodules.sh
Führen Sie es aus, um es auszuführen
Ausarbeitung
Zunächst gehe ich davon aus, dass der Zweig mit dem Namen $ BRANCH (zweites Argument) in allen Repositorys vorhanden ist. Fühlen Sie sich frei, dies noch komplexer zu machen.
In den ersten Abschnitten wird überprüft, ob die Argumente vorhanden sind. Dann ziehe ich die neuesten Inhalte des übergeordneten Repositorys ab (ich bevorzuge es, --ff (Schnellvorlauf) zu verwenden, wenn ich nur Pulls mache. Ich habe Rebase Off, BTW).
Dann kann eine Submodulinitialisierung erforderlich sein, wenn neue Submodule hinzugefügt wurden oder noch nicht initialisiert wurden:
Dann aktualisiere / ziehe ich alle Submodule:
Beachten Sie einige Dinge: Zunächst verkette ich einige Git-Befehle mit
&&
- was bedeutet, dass der vorherige Befehl fehlerfrei ausgeführt werden muss.Nach einem möglichen erfolgreichen Pull (wenn neue Inhalte auf der Fernbedienung gefunden wurden) mache ich einen Push, um sicherzustellen, dass ein mögliches Merge-Commit nicht auf dem Client zurückbleibt. Wiederum passiert es nur, wenn ein Zug tatsächlich neue Sachen einbringt.
Schließlich stellt das Finale
|| true
sicher, dass das Skript bei Fehlern fortgesetzt wird. Damit dies funktioniert, muss alles in der Iteration in doppelte Anführungszeichen gesetzt werden, und die Git-Befehle werden in Klammern gesetzt (Operatorpriorität).Mein Lieblingsabschnitt:
Iterieren Sie alle Submodule - mit
--quiet
, wodurch die Ausgabe 'Eingabe von MODULE_PATH' entfernt wird. Mit'echo $path'
(muss in einfachen Anführungszeichen stehen) wird der Pfad zum Submodul in die Ausgabe geschrieben.Diese Liste der relativen Submodulpfade wird in einem Array (
$(...)
) erfasst. Wiederholen Sie dies schließlichgit add $i
, um das übergeordnete Repository zu aktualisieren.Schließlich ein Commit mit einer Meldung, die erklärt, dass das übergeordnete Repository aktualisiert wurde. Dieses Festschreiben wird standardmäßig ignoriert, wenn nichts unternommen wurde. Schieben Sie dies zum Ursprung, und Sie sind fertig.
Ich habe ein Skript, das dies in einem Jenkins- Job ausführt, das anschließend mit einer geplanten automatisierten Bereitstellung verknüpft wird, und es funktioniert wie ein Zauber.
Ich hoffe, das wird jemandem helfen.
quelle
pwd
Befehl gibt den richtigen 'absoluten Pfad' für jedes vorhandene Submodul aus.--recursive
stellt sicher, dass wir alle Submodule besuchen , einschließlich der Submodule innerhalb der Submodule, die in einem großen Projekt vorhanden sein können. Beide Methoden verursachen Probleme mit Verzeichnissen, die Leerzeichen enthalten./c/Users/Ger/Project\ Files/...
Daher wird in unseren Projekten niemals Leerzeichen verwendet.--remote
Option hinzugefügt .git submodule update --remote
verhält sich ungefähr so wie Ihr Skript.The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
Ich möchte weder .gitmodules noch .git / config jedes Mal bearbeiten, wenn ich dies für einen anderen Zweig als master tun möchte. Aber vielleicht habe ich etwas verpasst? Außerdem scheint die Methode rekursive Zusammenführungen zu erzwingen (wodurch die Möglichkeit eines schnellen Vorlaufs fehlt).Schlicht und einfach, um die Submodule zu holen:
Und jetzt aktualisieren Sie sie auf den neuesten Hauptzweig (zum Beispiel):
quelle
Beachten Sie, dass die moderne Form der Aktualisierung von Submodul-Commits Folgendes wäre:
Die ältere Form war:
Außer ... diese zweite Form ist nicht wirklich "leise".
Siehe Commit a282f5a (12. April 2019) von Nguyễn Thái Ngọc Duy (
pclouds
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit f1c9f6c , 25. April 2019)Und Git 2.23 (Q3 2019) behebt ein weiteres Problem: "
git submodule foreach
" hat die an den Befehl übergebenen Befehlszeilenoptionen nicht geschützt, damit sie in jedem Submodul korrekt ausgeführt werden, wenn die--recursive
Option " " verwendet wurde.Siehe Commit 30db18b (24. Juni 2019) von Morian Sonnet (
momoson
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 968eecb , 09. Juli 2019)quelle
Dadurch werden die neuesten Commits abgerufen.
quelle
In meinem Fall wollte ich
git
auf den neuesten Stand aktualisieren und gleichzeitig alle fehlenden Dateien neu füllen.Im Folgenden wurden die fehlenden Dateien wiederhergestellt (dank
--force
derer hier anscheinend nichts erwähnt wurde), aber es wurden keine neuen Commits gezogen:git submodule update --init --recursive --force
Dies tat:
git submodule update --recursive --remote --merge --force
quelle
@ Jason ist in gewisser Weise korrekt, aber nicht ganz.
Also,
git submodule update
checkout, aber es ist das Commit im Index des enthaltenen Repositorys. Das neue Commit ist noch gar nicht bekannt. Gehen Sie also zu Ihrem Submodul, holen Sie sich das gewünschte Commit und schreiben Sie den aktualisierten Submodulstatus im Haupt-Repository fest. Führen Sie dann das ausgit submodule update
.quelle
git submodule update
, verschiebt update das Submodul auf das Commit, das im aktuellen HEAD des Superprojekts angegeben ist. (Was auch immer das letzte Commit im Superprojekt besagt, dass das Teilprojekt sein sollte - dieses Verhalten erscheint mir nach der Erklärung in Jasons Beitrag logisch) Es scheint auch abzurufen, aber nur für den Fall, dass sich das Teilprojekt auf dem falschen Commit befindet , was zu meiner Verwirrung beitrug.Hier ist ein großartiger Einzeiler, mit dem Sie alles auf den neuesten Stand bringen können:
Vielen Dank an Mark Jaquith
quelle
Wenn Sie den Host-Zweig nicht kennen, gehen Sie wie folgt vor:
Es wird ein Zweig des Haupt-Git-Repositorys abgerufen und dann für jedes Submodul derselbe Zweig abgerufen.
quelle
Wenn Sie den
master
Zweig für jedes Submodul auschecken möchten, können Sie zu diesem Zweck den folgenden Befehl verwenden:quelle