Wie mache ich flache Git-Submodule?

139

Ist es möglich, flache Submodule zu haben? Ich habe ein Superprojekt mit mehreren Submodulen, jedes mit einer langen Geschichte, so dass es unnötig groß wird, wenn man die ganze Geschichte in die Länge zieht.

Ich habe nur diesen unbeantworteten Thread gefunden .

Sollte ich nur das Git-Submodul hacken , um dies zu implementieren?

Mauricio Scheffer
quelle
1
" git submodule add/update" kann jetzt die Submodul-Repositorys flach klonen! Siehe meine Antwort unten
VonC

Antworten:

133

Neu im kommenden git1.8.4 (Juli 2013) :

" git submodule update" kann optional die Submodul-Repositorys flach klonen.

(Und Git 2.10 Q3 2016 ermöglicht es, dies mit aufzuzeichnen git config -f .gitmodules submodule.<name>.shallow true.
Siehe das Ende dieser Antwort)

Siehe Commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f :

Fügen Sie die --depthOption zu den Befehlen zum Hinzufügen und Aktualisieren von "git submodule" hinzu, die dann an den Befehl clone weitergeleitet werden. Dies ist nützlich, wenn die Submodule sehr groß sind und Sie nur an dem neuesten Commit interessiert sind.

Es werden Tests hinzugefügt und einige Einrückungsanpassungen vorgenommen, um dem Rest der Testdatei zu entsprechen. "Submodul-Update kann symbolische Links in pwd verarbeiten".

Unterzeichnet von: Fredrik Gustafsson <[email protected]>
Bestätigt von: Jens Lehmann<[email protected]>

Das heißt, das funktioniert:

git submodule add --depth 1 -- repository path
git submodule update --depth -- [<path>...]

Mit:

--depth::

Diese Option gilt für addund updateBefehle.
Erstellen Sie einen "flachen" Klon mit einem Verlauf, der auf die angegebene Anzahl von Revisionen abgeschnitten ist.


atwyman fügt in den Kommentaren hinzu :

Soweit ich das beurteilen kann, ist diese Option nicht für Submodule geeignet, die nicht mastersehr genau verfolgt werden. Wenn Sie Tiefe 1 festlegen, submodule updatekann dies nur dann erfolgreich sein, wenn das gewünschte Submodul-Commit der neueste Master ist. Sonst bekommst du " fatal: reference is not a tree" .

Das ist wahr.
Das heißt, bis Git 2.8 (März 2016). Mit 2.8 submodule update --depthhat der eine weitere Erfolgschance, selbst wenn der SHA1 direkt von einem der Remote-Repo-Köpfe aus erreichbar ist.

Siehe Commit fb43e31 (24. Februar 2016) von Stefan Beller ( stefanbeller) .
Mit freundlichergitster Unterstützung von Junio ​​C Hamano ( ) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 9671a76 , 26. Februar 2016)

Submodul: Versuchen Sie stärker, das benötigte sha1 durch direktes Abrufen von sha1 abzurufen

Bei der Überprüfung einer Änderung, mit der auch ein Submodul in Gerrit aktualisiert wird, wird häufig empfohlen, den Patch lokal herunterzuladen und auszuwählen, um ihn zu testen.
Beim lokalen Testen kann es jedoch vorkommen, dass das ' git submodule update' das richtige Submodul sha1 nicht abruft, da das entsprechende Commit im Submodul noch nicht Teil der Projekthistorie ist, sondern nur eine vorgeschlagene Änderung.

Wenn dies $sha1nicht Teil des Standardabrufs war, versuchen wir, den $sha1direkt abzurufen . Einige Server unterstützen jedoch kein direktes Abrufen durch sha1, was git-fetchzu einem schnellen Ausfall führt .
Wir können hier versagen, da das noch fehlende sha1 später in der Checkout-Phase ohnehin zu einem Fehler führen würde. Daher ist ein Fehler hier so gut wie möglich.


MVG weist in den Kommentaren darauf hin , fb43e31 zu verpflichten (git 2.9, Feb 2016)

Es scheint mir, dass Commit fb43e31 das fehlende Commit nach SHA1-ID anfordert, sodass die Einstellungen uploadpack.allowReachableSHA1InWantund uploadpack.allowTipSHA1InWantauf dem Server wahrscheinlich Einfluss darauf haben, ob dies funktioniert.
Ich habe heute einen Beitrag in die Git-Liste geschrieben , in dem ich darauf hinwies, wie die Verwendung von flachen Submodulen für einige Szenarien besser funktionieren könnte, wenn das Commit auch ein Tag ist.
Lass uns abwarten und sehen.

Ich denke, dies ist ein Grund, warum fb43e31 den Abruf für einen bestimmten SHA1 zu einem Fallback nach dem Abruf für den Standardzweig gemacht hat.
Im Falle von "--depth 1" halte ich es jedoch für sinnvoll, vorzeitig abzubrechen: Wenn keine der aufgelisteten Refs mit der angeforderten übereinstimmt und die Anfrage von SHA1 vom Server nicht unterstützt wird, hat dies keinen Sinn etwas abrufen, da wir die Submodul-Anforderung in beiden Fällen nicht erfüllen können.


Update August 2016 (3 Jahre später)

Mit Git 2.10 (Q3 2016) können Sie dies tun

 git config -f .gitmodules submodule.<name>.shallow true

Weitere Informationen finden Sie unter " Git-Submodul ohne zusätzliches Gewicht ".


Git 2.13 (Q2 2017) fügt Commit 8d3047c (19. April 2017) von Sebastian Schuberth ( sschuberth) hinzu .
(Zusammengeführt von Sebastian Schuberth - sschuberth- in Commit 8d3047c , 20. April 2017)

Ein Klon dieses Submoduls wird als flacher Klon ausgeführt (mit einer Verlaufstiefe von 1).

Allerdings Ciro Santilli fügt in den Kommentaren (und Details in seiner Antwort )

shallow = trueEin .gitmoduleswirkt sich nur auf die Referenz aus, die bei Verwendung vom HEAD der Fernbedienung verfolgt wird --recurse-submodules, selbst wenn das Ziel-Commit von einem Zweig angezeigt wird, und selbst wenn Sie branch = mybranchdas .gitmodulesauch aktivieren.


Git 2.20 (Q4 2018) verbessert die Submodul-Unterstützung, die aktualisiert wurde, um aus dem Blob zu lesen, HEAD:.gitmoduleswenn die .gitmodulesDatei im Arbeitsbaum fehlt.

Siehe Commit 2b1257e , Commit 76e9bdc (25. Oktober 2018) und Commit b5c259f , Commit 23dd8f5 , Commit b2faad4 , Commit 2502ffc , Commit 996df4d , Commit d1b13df , Commit 45f5ef3 , Commit bcbc780 (05. Oktober 2018) von Antonio Ospite ( ao2) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit abb4824 , 13. November 2018)

submodule: Unterstützung beim Lesen, .gitmoduleswenn es nicht im Arbeitsbaum ist

Wenn die .gitmodulesDatei im Arbeitsbaum nicht verfügbar ist, versuchen Sie, den Inhalt aus dem Index und aus dem aktuellen Zweig zu verwenden.
Dies gilt für den Fall, dass die Datei Teil des Repositorys ist, aber aus irgendeinem Grund nicht ausgecheckt wird, z. B. aufgrund einer spärlichen Prüfung.

Dies ermöglicht es, mindestens die git submoduleBefehle ' ' zu verwenden, mit denen die Konfigurationsdatei gelesengitmodules wird, ohne den Arbeitsbaum vollständig zu füllen.

Für das Schreiben in .gitmodulesmuss die Datei weiterhin ausgecheckt sein. Überprüfen Sie dies vor dem Aufruf config_set_in_gitmodules_file_gently.

Fügen Sie eine ähnliche Prüfung hinzu git-submodule.sh::cmd_add(), um den eventuellen Fehler des git submodule addBefehls " " zu antizipieren, wenn er .gitmodulesnicht sicher beschreibbar ist. Dies verhindert, dass der Befehl das Repository in einem falschen Zustand verlässt (z. B. wurde das Submodul-Repository geklont, aber .gitmodulesnicht aktualisiert, weil es config_set_in_gitmodules_file_gentlyfehlgeschlagen ist).

Da config_from_gitmodules()jetzt auf den globalen Objektspeicher zugegriffen wird, müssen außerdem alle Codepfade, die die Funktion aufrufen, vor gleichzeitigem Zugriff auf den globalen Objektspeicher geschützt werden.
Derzeit geschieht dies nur in builtin/grep.c::grep_submodules(), rufen Sie also auf, grep_read_lock()bevor Sie den betreffenden Code aufrufen config_from_gitmodules().

HINWEIS: Es gibt einen seltenen Fall, in dem diese neue Funktion noch nicht ordnungsgemäß funktioniert: verschachtelte Submodule ohne .gitmodulesin ihrem Arbeitsbaum.


Hinweis: Git 2.24 (Q4 2019) behebt einen möglichen Segfault beim Klonen eines flachen Submoduls.

Siehe Commit ddb3c85 (30. September 2019) von Ali Utku Selen ( auselen) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 678a9ca , 09. Oktober 2019)


Git 2.25 (Q1 2020) verdeutlicht die git submodule updateDokumentation.

Siehe Commit f0e58b3 (24. November 2019) von Philippe Blain ( phil-blain) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit ef61045 , 05. Dezember 2019)

doc: Erwähne, dass 'git submodule update' fehlende Commits abruft

Unterstützt von: Junio ​​C Hamano
Unterstützt von: Johannes Schindelin
Unterzeichnet von: Philippe Blain

' git submoduleupdate' ruft neue Commits von der Submodul-Fernbedienung ab, wenn der im Superprojekt aufgezeichnete SHA-1 nicht gefunden wird . Dies wurde in der Dokumentation nicht erwähnt.


Warnung: Mit Git 2.25 (Q1 2020) war die Interaktion zwischen " git clone --recurse-submodules" und alternativem Objektspeicher schlecht gestaltet.

Die Dokumentation und der Code wurden gelehrt, um klarere Empfehlungen abzugeben, wenn die Benutzer Fehler sehen.

Siehe Commit 4f3e57e , Commit 10c64a0 (02. Dezember 2019) von Jonathan Tan ( jhowtan) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 5dd1d59 , 10. Dezember 2019)

submodule--helper: Hinweise zu schwerwiegenden alternativen Fehlern

Unterzeichnet von: Jonathan Tan
Bestätigt von: Jeff King

Beim rekursiven Klonen eines Superprojekts mit einigen darin definierten flachen Modulen und beim .gitmoduleserneuten Klonen mit " --reference=<path>" tritt ein Fehler auf. Beispielsweise:

git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  master
git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  --reference master master2

schlägt fehl mit:

fatal: submodule '<snip>' cannot add alternate: reference repository
'<snip>' is shallow

Wenn eine Alternative, die aus der Alternative des Superprojekts berechnet wurde, in diesem oder einem anderen Fall nicht hinzugefügt werden kann, sollten Sie die Konfigurationsoption submodule.alternateErrorStrategykonfigurieren und beim Klonen " --reference-if-able" anstelle von " --reference" verwenden.

Das ist detailliert in:

Mit Git 2.25 (Q1 2020) war die Interaktion zwischen "git clone --recurse-submodules" und dem alternativen Objektspeicher schlecht gestaltet.

Doc: Erkläre submodule.alternateErrorStrategy

Unterzeichnet von: Jonathan Tan
Bestätigt von: Jeff King

Commit 31224cbdc7 (" clone: rekursive und Referenzoption löst Submodulalternativen aus", 2016-08-17, Git v2.11.0-rc0 - Zusammenführung in Stapel 1 aufgeführt ) brachte Git bei, die Konfigurationsoptionen " submodule.alternateLocation" und " submodule.alternateErrorStrategy" für ein Superprojekt zu unterstützen .

Wenn " submodule.alternateLocation" für " superproject" in einem Superprojekt konfiguriert ist, berechnet es jedes Mal, wenn ein Submodul dieses Superprojekts geklont wird, stattdessen den analogen alternativen Pfad für dieses Submodul aus $GIT_DIR/objects/info/alternatesdem Superprojekt und verweist darauf.

Die submodule.alternateErrorStrategyOption " " bestimmt, was passiert, wenn auf diese Alternative nicht verwiesen werden kann.
Es ist jedoch nicht klar, dass der Klon so vorgeht, als ob keine Alternative angegeben worden wäre, wenn diese Option nicht auf "sterben" gesetzt ist (wie aus den Tests in 31224cbdc7 hervorgeht ).
Dokumentieren Sie es daher entsprechend.

Die Dokumentation zum Konfigurations-Submodul enthält jetzt:

submodule.alternateErrorStrategy::

Gibt an, wie Fehler mit den Alternativen für ein Submodul behandelt werden, wie über berechnet submodule.alternateLocation.
Mögliche Werte sind ignore, info, die.
Standard ist die.
Beachten Sie, dass der Klon so fortgesetzt wird, als ob keine Alternative angegeben wurde , wenn auf ignoreoder gesetzt infoist und ein Fehler mit der berechneten Alternative vorliegt .

VonC
quelle
2
Wow das war schnell! Danke übrigens für die Antwort. Oh und --depthsollte auch ein Argument nehmen;)
Brice
3
Es scheint mir, dass Commit fb43e31 das fehlende Commit nach SHA1-ID anfordert, sodass die Einstellungen uploadpack.allowReachableSHA1InWantund uploadpack.allowTipSHA1InWantauf dem Server wahrscheinlich Einfluss darauf haben, ob dies funktioniert. Ich habe heute einen Beitrag in die Git-Liste geschrieben , in dem ich darauf hinwies, wie die Verwendung von flachen Submodulen für einige Szenarien besser funktionieren könnte, nämlich wenn das Commit auch ein Tag ist. Lass uns abwarten und sehen.
MvG
2
Mit der kürzlich erfolgten Zugabe von flacher Option .gitmodules, funktioniert die --depth 1Option Arbeit für Filialen , die nicht Meister eng Tracking werden?
CMCDragonkai
2
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Vielen Dank für die Präzision und den Test. Ich habe Ihren Kommentar zur besseren Sichtbarkeit in die Antwort aufgenommen und Ihre Antwort positiv bewertet.
VonC
2
Aus der Antwort geht nicht hervor, wie dies derzeit zu tun ist. Es ist auch nicht klar, ob all dies jedes Mal benötigt wird, wenn jemand eine neue Kopie klont oder diese Sparce-Submodul-Einstellungen Teil des Repos werden, das auf diese Submodule verweist (z. B. führt jede neue Klon- und Submodul-Aktualisierung zu Sparce-Submodul-Checkouts)
Pavel P
26

Git 2.9.0 unterstützt Submodule mit flachem Klon direkt, sodass Sie jetzt einfach Folgendes aufrufen können:

git clone url://to/source/repository --recursive --shallow-submodules
KindDragon
quelle
2
Diese Option ist die vielversprechendste, schlägt jedoch in Git 2.14.1 fehl. Das Festschreiben des Submoduls wird weder von einem Zweig noch von einem Tag verfolgt: stackoverflow.com/a/47374702/895245
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
1
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Stellen Sie sicher, dass Ihr Git-Server auch aktualisiert wird
KindDragon
Danke, ich habe lokal, ohne Server und auf GitHub getestet, was ich nicht aktualisieren kann :-)
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
1
Ich habe das gleiche Problem mit Git 2.20, es funktioniert nicht, wenn sich das Submodul nicht an der Spitze des Zweigs befindet.
Zitrax
16

Nach Ryans Antwort konnte ich dieses einfache Skript entwickeln, das alle Submodule durchläuft und sie flach klont:

#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
    spath=$(git config -f .gitmodules --get submodule.$i.path)
    surl=$(git config -f .gitmodules --get submodule.$i.url)
    git clone --depth 1 $surl $spath
done
git submodule update
Mauricio Scheffer
quelle
Ich bekomme fatal: reference is not a tree: 88fb67b07621dfed054d8d75fd50672fb26349dffür jedes Submodul
Knocte
@knocte haben Sie gesehen, stackoverflow.com/questions/2144406/git-shallow-submodules/…
Mauricio Scheffer
1
@knocte: Ich habe meine Antwort 2010 geschrieben. Die Dinge haben sich geändert. Sie können nicht erwarten, dass jeder alle seine Antworten beibehält. Ich habe die aktuell gültige Antwort als akzeptiert markiert.
Mauricio Scheffer
13
@knocte Dies ist einer der Gründe, warum ich aufgehört habe, zu Stackoverflow beizutragen. Die Menschen haben diese unrealistischen Erwartungen. Es wäre eine Vollzeitbeschäftigung, jede meiner 1637 Antworten zu pflegen. Und dann gibt es noch die Kommentare, ich nehme an, ich müsste diese auch beibehalten? Schauen Sie sich die Daten an, dafür sind sie da. Wenn Sie ein .NET-Blog aus dem Jahr 2002 mit Code lesen, der ArrayList anstelle von List verwendet, würden Sie das verwenden? Würden Sie verlangen, dass der Autor seinen Beitrag aktualisiert? Gleiches gilt hier.
Mauricio Scheffer
1
s / statusquo / progress /
knocte
8

Beim Durchlesen der "Quelle" des Git-Submoduls sieht es so aus, als git submodule addkönnten Submodule verarbeitet werden, deren Repositorys bereits vorhanden sind. In diesem Fall...

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...

Sie sollten sicherstellen, dass sich das erforderliche Commit im Submodul-Repo befindet. Stellen Sie daher sicher, dass Sie eine geeignete Tiefe festlegen.

Bearbeiten: Möglicherweise können Sie mit mehreren manuellen Submodul-Klonen davonkommen, gefolgt von einem einzigen Update:

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update
Ryan Graham
quelle
5
Für Git 1.8.0 können Sie jetzt kein Repository mehr in ein Repository klonen. Diese Lösung funktioniert also nicht mehr.
Bohr
7

Zusammenfassung des fehlerhaften / unerwarteten / nervigen Verhaltens ab Git 2.14.1

  1. shallow = truein .gitmoduleswirkt sich nur , git clone --recurse-submoduleswenn die HEADvon den entfernten Submodul auf die benötigte begehen, auch wenn das Ziel durch einen Zweig wird darauf verpflichten, und selbst wenn Sie setzen branch = mybranchdie auf .gitmodulesauch.

    Lokales Testskript . Gleiches Verhalten auf GitHub 2017-11, wo HEADdie Standardeinstellung für das Zweig-Repo gesteuert wird:

    git clone --recurse-submodules https://github.com/cirosantilli/test-shallow-submodule-top-branch-shallow
    cd test-shallow-submodule-top-branch-shallow/mod
    git log
    # Multiple commits, not shallow.
    
  2. git clone --recurse-submodules --shallow-submodulesschlägt fehl, wenn das Commit weder von einem Zweig noch von einem Tag mit einer Nachricht referenziert wird : error: Server does not allow request for unadvertised object.

    Lokales Testskript . Gleiches Verhalten auf GitHub:

    git clone --recurse-submodules --shallow-submodules https://github.com/cirosantilli/test-shallow-submodule-top-sha
    # error
    

    Ich fragte auch auf der Mailingliste: https://marc.info/?l=git&m=151863590026582&w=2 und die Antwort war:

    Theoretisch sollte dies einfach sein. :) :)

    In der Praxis leider nicht so sehr. Dies liegt daran, dass beim Klonen nur der neueste Tipp eines Zweigs (normalerweise Master) abgerufen wird. Es gibt keinen Mechanismus im Klon, um das genaue sha1 anzugeben, das gewünscht wird.

    Das Wire-Protokoll unterstützt das Abfragen exakter sha1s, so dass dies abgedeckt werden sollte. (Vorsichtsmaßnahme: Es funktioniert nur, wenn der Server-Operator uploadpack.allowReachableSHA1InWant aktiviert, welcher Github kein AFAICT hat.)

    Mit git-fetch können Sie beliebiges sha1 abrufen. Um dieses Problem zu umgehen, können Sie nach dem rekursiven Klon einen Abruf ausführen, indem Sie "git submodule update" verwenden, da nach dem ersten Klon Abrufe verwendet werden.

TODO-Test : allowReachableSHA1InWant.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
Es scheint, als gäbe es keine einfache Möglichkeit, einen getrennten HEAD-Commit-Hash für das Submodul auszuchecken und nachgeschaltete Benutzer zu haben git clone --recursive, die nur diesen bestimmten Commit abrufen.
CMCDragonkai
3

Sind die kanonischen Speicherorte für Ihre Submodule entfernt? Wenn ja, können Sie sie einmal klonen? Mit anderen Worten, möchten Sie die flachen Klone nur, weil Sie unter der verschwendeten Bandbreite häufiger Submodul- (Re-) Klone leiden?

Wenn Sie möchten, dass flache Klone lokalen Speicherplatz sparen, ist die Antwort von Ryan Graham ein guter Weg. Klonen Sie die Repositorys manuell so, dass sie flach sind. Wenn Sie denken, dass es nützlich wäre, passen Sie es an, um es git submodulezu unterstützen. Senden Sie eine E-Mail an die Liste, in der Sie danach gefragt werden (Ratschläge zur Implementierung, Vorschläge zur Benutzeroberfläche usw.). Meiner Meinung nach unterstützen die Leute dort potenzielle Mitwirkende, die Git auf konstruktive Weise ernsthaft verbessern wollen.

Wenn Sie einen vollständigen Klon jedes Submoduls erstellen können (plus spätere Abrufe, um sie auf dem neuesten Stand zu halten), können Sie versuchen, mit der --referenceOption git submodule update(in Git 1.6.4 und höher) auf lokale Objektspeicher zu verweisen (z Erstellen Sie --mirrorKlone der kanonischen Submodul-Repositorys und verwenden Sie sie dann --referencein Ihren Submodulen, um auf diese lokalen Klone zu verweisen. Lesen Sie unbedingt über git clone --reference/, git clone --sharedbevor Sie es verwenden --reference. Das einzige wahrscheinliche Problem bei der Referenzierung von Spiegeln besteht darin, dass sie jemals Aktualisierungen ohne schnellen Vorlauf abrufen (obwohl Sie Reflogs aktivieren und ihre Ablauffenster erweitern können, um abgebrochene Commits beizubehalten, die ein Problem verursachen könnten). Sie sollten keine Probleme haben, solange

  • Sie machen keine lokalen Submodul-Commits oder
  • Commits, die durch nicht schnelles Vorwärtsspulen, das die kanonischen Repositorys möglicherweise veröffentlichen, hängen bleiben, sind keine Vorfahren Ihrer lokalen Submodul-Commits oder
  • Sie sind fleißig dabei, Ihre lokalen Submodul-Commits auf der Grundlage von Nicht-Schnellvorläufen, die möglicherweise in den kanonischen Submodul-Repositories veröffentlicht werden, neu zu definieren.

Wenn Sie sich für so etwas entscheiden und die Möglichkeit besteht, dass Sie lokale Submodul-Commits in Ihren Arbeitsbäumen haben, ist es wahrscheinlich eine gute Idee, ein automatisiertes System zu erstellen, das sicherstellt, dass kritische Objekte, auf die von den ausgecheckten Submodulen verwiesen wird, dies nicht tun links in den Spiegel-Repositorys baumeln lassen (und wenn welche gefunden werden, kopieren Sie sie in die Repositorys, die sie benötigen).

Und, wie in der git cloneManpage angegeben, nicht verwenden, --referencewenn Sie diese Auswirkungen nicht verstehen.

# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git

# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super

# To avoid extra packs in each of the superprojects' submodules,
#   update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done

cd super
git pull             # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
                     #   but no download since they reference the updated mirrors

Alternativ können Sie stattdessen --referencedie Spiegelklone in Kombination mit der Standard-Hardlinking-Funktionalität verwenden, git cloneindem Sie lokale Spiegel als Quelle für Ihre Submodule verwenden. git submodule initBearbeiten Sie in neuen Superprojektklonen die Submodul-URLs so .git/config, dass sie auf die lokalen Spiegel verweisen, und tun Sie danngit submodule update. Sie müssten alle vorhandenen ausgecheckten Submodule erneut klonen, um die Hardlinks zu erhalten. Sie würden Bandbreite sparen, indem Sie nur einmal in die Spiegel herunterladen und dann lokal von diesen in Ihre ausgecheckten Submodule abrufen. Durch die feste Verknüpfung wird Speicherplatz gespart (obwohl Abrufe dazu neigen, sich über mehrere Instanzen der Objektspeicher der ausgecheckten Submodule zu sammeln und zu duplizieren), können Sie die ausgecheckten Submodule regelmäßig von den Spiegeln erneut klonen, um die von bereitgestellte Speicherplatzersparnis wiederherzustellen Hardlinking).

Chris Johnsen
quelle
2

Ich habe eine etwas andere Version erstellt, wenn sie nicht auf dem neuesten Stand ist, was nicht bei allen Projekten der Fall ist. Die Standard-Submodul-Ergänzungen funktionierten nicht und das obige Skript auch nicht. Also habe ich eine Hash-Suche für die Tag-Referenz hinzugefügt, und wenn es keine gibt, wird auf den vollständigen Klon zurückgegriffen.

#!/bin/bash
git submodule init
git submodule | while read hash name junk; do
    spath=$(git config -f .gitmodules --get submodule.$name.path)
    surl=$(git config -f .gitmodules --get submodule.$name.url)
    sbr=$(git ls-remote --tags $surl | sed -r "/${hash:1}/ s|^.*tags/([^^]+).*\$|\1|p;d")
    if [ -z $sbr ]; then
        git clone $surl $spath
    else
        git clone -b $sbr --depth 1 --single-branch $surl $spath
    fi
done
git submodule update 
sfossen
quelle
2

Verweis auf Wie klone ich ein Git-Repository mit einer bestimmten Revision / einem bestimmten Änderungssatz?

Ich habe ein einfaches Skript geschrieben, das kein Problem hat, wenn Ihre Submodulreferenz vom Master entfernt ist

git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'

Diese Anweisung ruft die referenzierte Version des Submoduls ab.

Es ist schnell, aber Sie können Ihre Bearbeitung nicht für das Submodul festschreiben (Sie müssen sie vor https://stackoverflow.com/a/17937889/3156509 abrufen ).

vollständig:

#!/bin/bash
git submodule init
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'
git submodule update --recursive
Beeno Tung
quelle
1

Der flache Klon eines Submoduls ist perfekt, da sie bei einer bestimmten Revision / einem bestimmten Änderungssatz einen Schnappschuss erstellen. Es ist einfach, eine Zip-Datei von der Website herunterzuladen, also habe ich versucht, ein Skript zu erstellen.

#!/bin/bash
git submodule deinit --all -f
for value in $(git submodule | perl -pe 's/.*(\w{40})\s([^\s]+).*/\1:\2/'); do
  mysha=${value%:*}
  mysub=${value#*:}
  myurl=$(grep -A2 -Pi "path = $mysub" .gitmodules | grep -Pio '(?<=url =).*/[^.]+')
  mydir=$(dirname $mysub)
  wget $myurl/archive/$mysha.zip
  unzip $mysha.zip -d $mydir
  test -d $mysub && rm -rf $mysub
  mv $mydir/*-$mysha $mysub
  rm $mysha.zip
done
git submodule init

git submodule deinit --all -f Löscht den Submodulbaum, sodass das Skript wiederverwendbar ist.

git submoduleRuft die 40 Zeichen sha1 ab, gefolgt von einem Pfad, der dem gleichen in entspricht .gitmodules. Ich verwende Perl, um diese durch einen Doppelpunkt getrennten Informationen zu verketten, und verwende dann eine variable Transformation, um die Werte in myshaund zu trennen mysub.

Dies sind die kritischen Schlüssel, da wir den sha1 zum Herunterladen und den Pfad zum Korrelieren der urlin .gitmodules benötigen.

Bei einem typischen Submoduleintrag:

[submodule "label"]
    path = localpath
    url = https://github.com/repository.git

myurlTasten auf path =dann sieht 2 Zeilen nach, um den Wert zu erhalten. Diese Methode funktioniert möglicherweise nicht konsistent und muss verfeinert werden. Das URL-Grep entfernt alle verbleibenden .gitTypreferenzen, indem es mit dem letzten /und allem bis zu a übereinstimmt ..

mydirist mysubminus ein Finale, /namedas durch das Verzeichnis zum Submodulnamen führen würde.

Als nächstes folgt eine wgetmit dem Format der herunterladbaren Zip-Archiv-URL. Dies kann sich in Zukunft ändern.

Entpacken Sie die Datei, mydirzu der das im Submodulpfad angegebene Unterverzeichnis gehören soll. Der resultierende Ordner ist das letzte Element des url- sha1.

Überprüfen Sie, ob das im Submodulpfad angegebene Unterverzeichnis vorhanden ist, und entfernen Sie es, um das Umbenennen des extrahierten Ordners zu ermöglichen.

mv Benennen Sie den extrahierten Ordner mit unserem sha1 in den richtigen Submodulpfad um.

Gelöschte Zip-Datei löschen.

Submodul init

Dies ist eher ein WIP-Proof of Concept als eine Lösung. Wenn es funktioniert, ist das Ergebnis ein flacher Klon eines Submoduls mit einem bestimmten Änderungssatz.

Sollte das Repository ein Submodul für ein anderes Commit neu starten, führen Sie das zu aktualisierende Skript erneut aus.

Das einzige Mal, wenn ein solches Skript nützlich wäre, ist die nicht kollaborative lokale Erstellung eines Quellprojekts.

Niemand
quelle