Comment créer des sous-modules git peu profonds?

139

Est-il possible d'avoir des sous-modules peu profonds? J'ai un superprojet avec plusieurs sous-modules, chacun avec une longue histoire, donc ça devient inutilement gros de traîner toute cette histoire.

Tout ce que j'ai trouvé, c'est ce fil sans réponse .

Dois-je simplement pirater git-submodule pour implémenter cela?

Mauricio Scheffer
la source
1
" git submodule add/update" peut maintenant cloner les dépôts de sous-modules de manière superficielle! Voir ma réponse ci
VonC

Réponses:

133

Nouveau dans le prochain git1.8.4 (juillet 2013) :

" git submodule update" peut éventuellement cloner les dépôts de sous-modules de manière superficielle.

(Et git 2.10 Q3 2016 permet d'enregistrer cela avec git config -f .gitmodules submodule.<name>.shallow true.
Voir la fin de cette réponse)

Voir commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f :

Ajouter le --depth option aux commandes d'ajout et de mise à jour de "git submodule", qui est ensuite transmise à la commande clone. Ceci est utile lorsque le ou les sous-modules sont énormes et que vous n'êtes pas vraiment intéressé par autre chose que le dernier commit.

Des tests sont ajoutés et quelques ajustements d'indentation ont été faits pour se conformer au reste du fichier de test sur "la mise à jour des sous-modules peut gérer les liens symboliques dans pwd".

Signé par: Fredrik Gustafsson <[email protected]>
Reconnu par: Jens Lehmann<[email protected]>

Cela signifie que cela fonctionne:

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

Avec:

--depth::

Cette option est valable pour les commandes addet update.
Créez un clone «superficiel» avec un historique tronqué au nombre de révisions spécifié.


atwyman ajoute dans les commentaires :

Pour autant que je sache, cette option n'est pas utilisable pour les sous-modules qui ne suivent pas de mastertrès près. Si vous définissez la profondeur 1, submodule updatecela ne peut réussir que si le commit de sous-module souhaité est le dernier maître. Sinon, vous obtenez " fatal: reference is not a tree" .

C'est vrai.
Autrement dit, jusqu'à git 2.8 (mars 2016). Avec la version 2.8, le submodule update --deptha une chance de plus de réussir, même si le SHA1 est directement accessible à partir de l'un des HEAD du repo distant.

Voir commit fb43e31 (24 février 2016) par Stefan Beller ( stefanbeller) .
Aide: Junio ​​C Hamano ( gitster) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 9671a76 , 26 février 2016)

sous-module: essayez plus fort de récupérer sha1 nécessaire en récupérant directement sha1

Lors de la révision d'un changement qui met également à jour un sous-module dans Gerrit, une pratique de révision courante consiste à télécharger et à sélectionner le correctif localement pour le tester.
Cependant, lors du test local, le ' git submodule update' peut échouer lors de la récupération du sous-module correct sha1 car le commit correspondant dans le sous-module ne fait pas encore partie de l'historique du projet, mais aussi simplement une proposition de changement.

Si $sha1ne faisait pas partie de la récupération par défaut, nous essayons de récupérer $sha1directement le fichier . Cependant, certains serveurs ne prennent pas en charge la récupération directe par sha1, ce qui conduit git-fetchà une panne rapide.
Nous pouvons nous échouer ici car le sha1 encore manquant entraînerait de toute façon un échec plus tard dans la phase de vérification, donc échouer ici est aussi bien que nous pouvons l'obtenir.


MVG souligne dans les commentaires pour commettre fb43e31 (git 2.9, février 2016)

Il me semble que le commit fb43e31 demande le commit manquant par ID SHA1, donc les paramètres uploadpack.allowReachableSHA1InWantet uploadpack.allowTipSHA1InWantsur le serveur affecteront probablement si cela fonctionne.
J'ai écrit un article sur la liste git aujourd'hui , indiquant comment l'utilisation de sous-modules peu profonds pourrait être améliorée pour certains scénarios, à savoir si le commit est également une balise.
Attendons voir.

Je suppose que c'est une raison pour laquelle fb43e31 a fait de la récupération pour un SHA1 spécifique une solution de secours après la récupération de la branche par défaut.
Néanmoins, dans le cas de «--depth 1», je pense qu'il serait logique d'abandonner prématurément: si aucune des références répertoriées ne correspond à celle demandée et que la demande par SHA1 n'est pas prise en charge par le serveur, alors il n'y a aucun intérêt à chercher quoi que ce soit, car nous ne serons pas en mesure de satisfaire l'exigence de sous-module de toute façon.


Mise à jour août 2016 (3 ans plus tard)

Avec Git 2.10 (Q3 2016), vous pourrez faire

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

Voir « Sous-module Git sans poids supplémentaire » pour en savoir plus.


Git 2.13 (Q2 2017) ajoute le commit 8d3047c (19 avril 2017) par Sebastian Schuberth ( sschuberth) .
(Fusionné par Sebastian Schuberth - sschuberth- in commit 8d3047c , 20 avril 2017)

un clone de ce sous-module sera effectué comme un clone peu profond (avec une profondeur d'historique de 1)

Cependant, Ciro Santilli ajoute dans les commentaires (et des détails dans sa réponse )

shallow = trueon .gitmodulesn'affecte que la référence suivie par le HEAD de la télécommande lors de l'utilisation --recurse-submodules, même si le commit cible est pointé par une branche, et même si vous mettez branch = mybranchle .gitmodulesaussi.


Git 2.20 (Q4 2018) améliore la prise en charge des sous-modules, qui a été mis à jour pour lire à partir de l'objet blob HEAD:.gitmoduleslorsque le .gitmodulesfichier est absent de l'arborescence de travail.

Voir commit 2b1257e , commit 76e9bdc (25 octobre 2018) et commit b5c259f , commit 23dd8f5 , commit b2faad4 , commit 2502ffc , commit 996df4d , commit d1b13df , commit 45f5ef3 , commit bcbc780 (05 octobre 2018) par Antonio Ospite ( ao2) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit abb4824 , 13 novembre 2018)

submodule: supporte la lecture .gitmodulesquand ce n'est pas dans l'arbre de travail

Lorsque le .gitmodulesfichier n'est pas disponible dans l'arborescence de travail, essayez d'utiliser le contenu de l'index et de la branche actuelle.
Cela couvre le cas où le fichier fait partie du référentiel mais pour une raison quelconque, il n'est pas extrait, par exemple en raison d'une extraction éparse.

Cela permet d'utiliser au moins les git submodulecommandes ' ' qui lisent le gitmodulesfichier de configuration sans remplir complètement l'arborescence de travail.

L'écriture dans .gitmodulesnécessitera toujours que le fichier soit extrait, alors vérifiez-le avant d'appeler config_set_in_gitmodules_file_gently.

Ajoutez également une vérification similaire git-submodule.sh::cmd_add()pour anticiper l'échec éventuel de la git submodule addcommande " " lorsqu'elle .gitmodulesn'est pas inscriptible en toute sécurité; cela empêche la commande de laisser le référentiel dans un état faux (par exemple, le référentiel de sous-modules a été cloné mais .gitmodulesn'a pas été mis à jour car config_set_in_gitmodules_file_gentlyéchoué).

De plus, étant donné qu'il config_from_gitmodules()accède désormais au magasin d'objets global, il est nécessaire de protéger tous les chemins de code qui appellent la fonction contre l'accès simultané au magasin d'objets global.
Actuellement, cela ne se produit que dans builtin/grep.c::grep_submodules(), alors appelez grep_read_lock()avant d'appeler du code impliquant config_from_gitmodules().

REMARQUE: il existe un cas rare où cette nouvelle fonctionnalité ne fonctionne pas encore correctement: les sous-modules imbriqués sans .gitmodulesdans leur arbre de travail.


Remarque: Git 2.24 (Q4 2019) corrige un éventuel segfault lors du clonage d'un sous-module peu profond.

Voir commit ddb3c85 (30 sept. 2019) par Ali Utku Selen ( auselen) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 678a9ca , 09 octobre 2019)


Git 2.25 (Q1 2020), clarifie la git submodule updatedocumentation.

Voir commit f0e58b3 (24 nov.2019 ) de Philippe Blain ( phil-blain) .
(Fusionné par Junio ​​C Hamano - gitster- in commit ef61045 , 05 déc 2019)

doc: mentionnez que 'git submodule update' récupère les commits manquants

Aide: Junio ​​C Hamano
Aide: Johannes Schindelin
Signature: Philippe Blain

'git submodule update' récupérera les nouveaux commits du sous-module distant si le SHA-1 enregistré dans le superprojet n'est pas trouvé . Cela n'a pas été mentionné dans la documentation.


Attention: avec Git 2.25 (Q1 2020), l'interaction entre " git clone --recurse-submodules" et le magasin d'objets alternatif était mal conçue.

La documentation et le code ont appris à faire des recommandations plus claires lorsque les utilisateurs constatent des échecs.

Voir commit 4f3e57e , commit 10c64a0 (02 décembre 2019) par Jonathan Tan ( jhowtan) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 5dd1d59 , 10 déc 2019)

submodule--helper: avis sur une erreur alternative fatale

Signé par: Jonathan Tan
Reconnu par: Jeff King

Lors du clonage récursif d'un superprojet avec des modules peu profonds définis dans son .gitmodules, puis reclonage avec " --reference=<path>", une erreur se produit. Par exemple:

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

échoue avec:

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

Lorsqu'une alternative calculée à partir de l'alternative du superprojet ne peut pas être ajoutée, que ce soit dans ce cas ou dans un autre, conseillez de configurer l' submodule.alternateErrorStrategyoption de configuration " " et d'utiliser " --reference-if-able" au lieu de " --reference" lors du clonage.

Cela est détaillé dans:

Avec Git 2.25 (Q1 2020), l'interaction entre "git clone --recurse-submodules" et un magasin d'objets alternatif était mal conçue.

Doc: expliquer submodule.alternateErrorStrategy

Signé par: Jonathan Tan
Reconnu par: Jeff King

Commit 31224cbdc7 (" clone: l'option récursive et de référence déclenche des alternatives de sous-module", 17/08/2016, Git v2.11.0-rc0 - fusion répertoriée dans le lot n ° 1 ) a appris à Git à prendre en charge les options de configuration " submodule.alternateLocation" et " submodule.alternateErrorStrategy" sur un superprojet .

Si " submodule.alternateLocation" est configuré sur " superproject" sur un superprojet, chaque fois qu'un sous-module de ce superprojet est cloné, il calcule à la place le chemin alternatif analogue pour ce sous-module à partir $GIT_DIR/objects/info/alternatesdu superprojet et y fait référence.

L' submodule.alternateErrorStrategyoption " " détermine ce qui se passe si cette alternative ne peut pas être référencée.
Cependant, il n'est pas clair que le clone se déroule comme si aucune alternative n'était spécifiée lorsque cette option n'est pas définie sur "die" (comme on peut le voir dans les tests de 31224cbdc7 ).
Par conséquent, documentez-le en conséquence.

La documentation du sous-module de configuration comprend désormais:

submodule.alternateErrorStrategy::

Spécifie comment traiter les erreurs avec les alternatives pour un sous-module comme calculé via submodule.alternateLocation.
Les valeurs possibles sont ignore, info, die.
La valeur par défaut est die.
Notez que s'il est défini sur ignoreou info, et s'il y a une erreur avec l'alternative calculée, le clone se déroule comme si aucune alternative n'était spécifiée .

VonC
la source
2
Wow c'était rapide! Thx pour la réponse au fait. Oh et --depthdevrait prendre une dispute aussi;)
Brice
3
Il me semble que le commit fb43e31 demande le commit manquant par ID SHA1, donc les paramètres uploadpack.allowReachableSHA1InWantet uploadpack.allowTipSHA1InWantsur le serveur affecteront probablement si cela fonctionne. J'ai écrit un article sur la liste git aujourd'hui, indiquant comment l'utilisation de sous-modules peu profonds pourrait être améliorée pour certains scénarios, à savoir si le commit est également une balise. Attendons voir.
MvG
2
Avec l'ajout récent de l'option peu profonde dans .gitmodules, l' --depth 1option fonctionne-t-elle pour les succursales qui ne suivent pas le maître de près?
CMCDragonkai
2
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Merci pour la précision et le test. J'ai inclus votre commentaire dans la réponse pour plus de visibilité et j'ai voté pour votre réponse.
VonC
2
La réponse n'indique pas clairement quelle est la façon actuelle de procéder. En outre, il n'est pas clair si tout cela est nécessaire chaque fois que quelqu'un clone une nouvelle copie ou que ces paramètres de sous-module rares deviennent une partie du dépôt qui fait référence à ces sous-modules (par exemple, chaque nouvelle mise à jour de clone et de sous-module entraîne des extractions de sous-modules rares)
Pavel P
26

Git 2.9.0 prend en charge directement les sous-modules de clonage superficiel, vous pouvez donc simplement appeler:

git clone url://to/source/repository --recursive --shallow-submodules
KindDragon
la source
2
Cette option est la plus prometteuse, mais elle échoue sur git 2.14.1 le commit du sous-module n'est suivi ni par une branche ni par une balise: stackoverflow.com/a/47374702/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Assurez-vous que votre serveur git est également mis à jour
KindDragon
Merci, j'ai testé localement, sans serveur, et sur GitHub, que je ne peux pas mettre à jour :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
J'ai le même problème avec git 2.20, cela ne fonctionne pas lorsque le sous-module n'est pas à l'extrémité de la branche.
Zitrax
16

Suite à la réponse de Ryan, j'ai pu créer ce script simple qui itère à travers tous les sous-modules et les clone superficiellement:

#!/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
la source
Je reçois fatal: reference is not a tree: 88fb67b07621dfed054d8d75fd50672fb26349dfpour chaque sous
knocte
1
@knocte: J'ai écrit ma réponse en 2010. Les choses ont changé. Vous ne pouvez pas vous attendre à ce que tout le monde maintienne toutes ses réponses. J'ai marqué la réponse valide actuelle comme acceptée.
Mauricio Scheffer
13
@knocte C'est l'une des raisons pour lesquelles j'ai arrêté de contribuer à Stackoverflow. Les gens ont ces attentes irréalistes. Ce serait un travail à plein temps de maintenir chacune de mes 1637 réponses. Et puis il y a aussi les commentaires, je suppose que je devrais aussi les maintenir? Jetez un œil aux dates, c'est à cela qu'elles servent. Si vous lisez un blog .NET de 2002 avec du code utilisant ArrayList au lieu de List, l'utiliseriez-vous? Souhaitez-vous exiger que l'auteur mette à jour son message? Le même principe s'applique ici.
Mauricio Scheffer
1
s / statusquo / progress /
knocte
8

En lisant le git-submodule "source", il semble git submodule addpouvoir gérer les sous-modules qui ont déjà leurs dépôts présents. Dans ce cas...

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

Vous voudrez vous assurer que le commit requis est dans le dépôt de sous-modules, alors assurez-vous de définir un --depth approprié.

Edit: Vous pourrez peut-être vous en sortir avec plusieurs clones de sous-modules manuels suivis d'une seule mise à jour:

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update
Ryan Graham
la source
5
Maintenant, pour git 1.8.0, vous ne pouvez plus cloner un référentiel dans un référentiel. Donc, cette solution ne fonctionne plus.
Bohr
7

Résumé du comportement bogué / inattendu / ennuyeux à partir de Git 2.14.1

  1. shallow = truein .gitmodulesaffecte uniquement git clone --recurse-submodulessi le HEADdu sous-module distant pointe vers le commit requis, même si le commit cible est pointé par une branche, et même si vous mettez branch = mybranchle .gitmodulesaussi.

    Script de test local . Même comportement sur GitHub 2017-11, où HEADest contrôlé par le paramètre de dépôt de branche par défaut:

    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-submoduleséchoue si le Commit est ni référencé par une branche ou une étiquette avec un message: error: Server does not allow request for unadvertised object.

    Script de test local . Même comportement sur GitHub:

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

    J'ai également demandé sur la liste de diffusion: https://marc.info/?l=git&m=151863590026582&w=2 et la réponse était:

    En théorie, cela devrait être facile. :)

    En pratique pas tellement, malheureusement. C'est parce que le clonage n'obtiendra que la dernière astuce d'une branche (généralement master). Il n'y a pas de mécanisme dans le clone pour spécifier le sha1 exact souhaité.

    Le protocole filaire prend en charge la demande de sha1s exacts, ce qui devrait être couvert. (Attention: cela ne fonctionne que si l'opérateur du serveur active uploadpack.allowReachableSHA1InWant quel github n'a pas AFAICT)

    git-fetch permet de récupérer un sha1 arbitraire, donc comme solution de contournement, vous pouvez lancer une extraction après le clone récursif en utilisant "git submodule update" car cela utilisera des récupérations après le clone initial.

Test TODO: allowReachableSHA1InWant.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
Il semble qu'il n'y ait tout simplement pas de moyen simple d'extraire un hachage de commit HEAD détaché pour le sous-module, et d'avoir des utilisateurs en aval git clone --recursivequi ne récupèrent que ce commit spécifique.
CMCDragonkai
3

Les emplacements canoniques de vos sous-modules sont-ils distants? Si oui, êtes-vous d'accord pour les cloner une fois? En d'autres termes, voulez-vous les clones peu profonds simplement parce que vous souffrez de la bande passante gaspillée de fréquents (re) clones de sous-modules?

Si vous voulez que les clones peu profonds sauvent l'espace disque local, alors la réponse de Ryan Graham semble être une bonne solution. Clonez manuellement les référentiels afin qu'ils soient superficiels. Si vous pensez que cela serait utile, adaptez-vous git submodulepour le soutenir. Envoyez un email à la liste pour en savoir plus (conseils pour sa mise en œuvre, suggestions sur l'interface, etc.). À mon avis, les gens là-bas soutiennent tout à fait les contributeurs potentiels qui souhaitent sincèrement améliorer Git de manière constructive.

Si vous êtes d'accord pour faire un clone complet de chaque sous-module (plus des récupérations ultérieures pour les garder à jour), vous pouvez essayer d'utiliser l' --referenceoption de git submodule update(c'est dans Git 1.6.4 et versions ultérieures) pour faire référence aux magasins d'objets locaux (par exemple créer des --mirrorclones des référentiels de sous-modules canoniques, puis les utiliser --referencedans vos sous-modules pour pointer vers ces clones locaux). Assurez-vous simplement de lire sur git clone --reference/ git clone --sharedavant d'utiliser --reference. Le seul problème probable avec les miroirs de référencement serait s'ils finissent par récupérer des mises à jour non rapides (bien que vous puissiez activer les reflogs et étendre leurs fenêtres d'expiration pour aider à conserver les commits abandonnés qui pourraient causer un problème). Vous ne devriez pas avoir de problèmes tant que

  • vous ne faites aucun commit de sous-module local, ou
  • tous les commits laissés en suspens par des envois non rapides que les référentiels canoniques pourraient publier ne sont pas des ancêtres de vos commits de sous-module local, ou
  • vous faites preuve de diligence pour garder vos commits de sous-modules locaux rebasés au-dessus de tout ce qui pourrait être publié dans les référentiels de sous-modules canoniques.

Si vous optez pour quelque chose comme ça et qu'il y a une chance que vous puissiez transporter des commits de sous-modules locaux dans vos arbres de travail, ce serait probablement une bonne idée de créer un système automatisé qui s'assure que les objets critiques référencés par les sous-modules extraits ne sont pas laissé en suspens dans les référentiels miroir (et le cas échéant, les copie dans les référentiels qui en ont besoin).

Et, comme le git clonedit la page de manuel, ne l'utilisez pas --referencesi vous ne comprenez pas ces implications.

# 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

Vous --referencepouvez également utiliser les clones de miroir en combinaison avec la fonctionnalité de liaison fixe par défaut de git cloneen utilisant des miroirs locaux comme source pour vos sous-modules. Dans les nouveaux clones de super-projet, faites git submodule init, modifiez les URL des sous-modules .git/configpour pointer vers les miroirs locaux, puis faitesgit submodule update. Vous devrez recloner tous les sous-modules extraits existants pour obtenir les liens physiques. Vous économiseriez de la bande passante en ne téléchargeant qu'une seule fois dans les miroirs, puis en les récupérant localement dans vos sous-modules extraits. La liaison matérielle permettrait d'économiser de l'espace disque (bien que les récupérations aient tendance à s'accumuler et à être dupliquées sur plusieurs instances des magasins d'objets des sous-modules extraits; vous pouvez périodiquement recloner les sous-modules extraits des miroirs pour récupérer l'économie d'espace disque fournie par liaison directe).

Chris Johnsen
la source
2

J'ai créé une version légèrement différente, pour quand elle ne fonctionne pas à la fine pointe, ce que tous les projets ne font pas. Les ajouts de sous-modules standard n'ont pas fonctionné, pas plus que le script ci-dessus. J'ai donc ajouté une recherche de hachage pour la référence de la balise, et si elle n'en a pas, elle revient au clonage complet.

#!/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
la source
2

Référence à Comment cloner le référentiel git avec une révision / un ensemble de modifications spécifique?

J'ai écrit un script simple qui ne pose aucun problème lorsque la référence de votre sous-module est éloignée du maître

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

Cette instruction récupérera la version référencée du sous-module.

C'est rapide mais vous ne pouvez pas valider votre modification sur le sous-module (vous devez le récupérer avant https://stackoverflow.com/a/17937889/3156509 )

en entier:

#!/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
la source
1

Le clonage superficiel d'un sous-module est parfait car ils prennent un instantané à une révision / modification particulière. Il est facile de télécharger un zip à partir du site Web, j'ai donc essayé un script.

#!/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 efface l'arborescence des sous-modules qui permet au script d'être réutilisable.

git submodulerécupère les 40 caractères sha1 suivis d'un chemin qui correspond au même dans .gitmodules. J'utilise perl pour concaténer ces informations, délimitées par deux points, puis j'utilise une transformation variable pour séparer les valeurs en myshaetmysub .

Ce sont les clés critiques car nous avons besoin du sha1 pour télécharger et du chemin pour corréler les urlin .gitmodules.

Étant donné une entrée de sous-module typique:

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

myurltouches sur path =puis regarde 2 lignes après pour obtenir la valeur. Cette méthode peut ne pas fonctionner de manière cohérente et nécessiter des améliorations. L'url grep supprime toutes les .gitréférences de type restantes en les faisant correspondre à la dernière /et à tout ce qui. .

mydirest mysubmoins une finale/name qui serait par le répertoire menant au nom du sous-module.

Vient ensuite un wgetavec le format de l'url d'archive zip téléchargeable. Cela pourrait changer à l'avenir.

Décompressez le fichier dans mydirlequel se trouverait le sous-répertoire spécifié dans le chemin du sous-module. Le dossier résultant sera le dernier élément du url- sha1.

Vérifiez si le sous-répertoire spécifié dans le chemin du sous-module existe et supprimez-le pour permettre le changement de nom du dossier extrait.

mv renommez le dossier extrait contenant notre sha1 en son chemin de sous-module correct.

Supprimer le fichier zip téléchargé.

Init du sous-module

Il s'agit plus d'une preuve de concept WIP qu'une solution. Quand cela fonctionne, le résultat est un clone superficiel d'un sous-module à un changeset spécifié.

Si le référentiel réintègre un sous-module vers un commit différent, réexécutez le script pour mettre à jour.

Le seul moment où un script comme celui-ci serait utile est pour la construction locale non collaborative d'un projet source.

noabody
la source