Submodules : concept de base, workflows et conseils
Nicola Paolucci
Expert en développement
L'intégration de submodules à votre développement Git vous permet d'inclure d'autres projets à votre base de code, tout en conservant des historiques distincts, mais synchronisés avec le vôtre. C'est une méthode pratique pour résoudre les problèmes de dépendance et de bibliothèque de fournisseur. Comme toujours et à tout niveau avec Git
, l'approche est très pointilleuse et nécessite un peu d'étude pour être utilisée avec efficacité. Il existe déjà des informations fiables et précises sur les submodules
à divers endroits, je ne vais donc pas les répéter. Je vais maintenant partager avec vous certains points utiles qui vous aideront à tirer le meilleur parti de cette fonctionnalité.
Sommaire
Ressource connexe
Comment déplacer un dépôt Git complet
DÉCOUVRIR LA SOLUTION
Découvrir Git avec Bitbucket Cloud
Concept de base
Je vais tout d'abord vous expliquer brièvement l'un des concepts de base des submodules. Vous pourrez ainsi les utiliser plus facilement.
Les submodules sont suivis par le commit exact spécifié dans le projet parent, donc pas dans une branche, une réf ni aucune autre référence symbolique.
Ils ne sont jamais automatiquement mis à jour lorsque le dépôt spécifié par le sous-module est mis à jour, uniquement lorsque le projet parent l'est. Comme le dit très clairement le chapitre Pro Git cité plus tôt :
Lorsque vous apportez des changements et que vous les commitez dans ce sous-répertoire [submodule], le superprojet remarque que le HEAD a été modifié et enregistre le commit exact sur lequel vous travaillez actuellement ; ainsi, lorsque ce projet est cloné, il est possible de recréer exactement l'environnement.
Ou en d'autres termes :
[…] les submodules Git […] sont statiques. Très statiques. Vous suivez des commits spécifiques avec les submodules Git, pas des branches, des références ni un commit unique. Si vous ajoutez des commits à un submodule, le projet parent ne le sait pas. Si vous disposez de plusieurs forks d'un module, les submodules Git n'en tiennent pas compte. Vous avez un dépôt distant unique et vous pointez vers un commit unique. Jusqu'à ce que vous mettiez le projet parent à jour, rien ne change.
Workflows possibles
En vous remémorant ce concept de base et en y réfléchissant, vous comprendrez que les commandes submodule
peuvent s'avérer très utiles pour certains workflows et beaucoup moins pour d'autres. Trois scénarios se prêtent particulièrement à l'utilisation des submodules :
-
Lorsqu'un composant ou un sous-projet change trop rapidement ou que des changements futurs interrompent l'API, vous pouvez verrouiller le code sur un commit spécifique pour votre propre sécurité.
-
Lorsque vous disposez d'un composant qui n'est pas souvent mis à jour et que vous souhaitez le suivre en tant que dépendance de fournisseur. Je procède ainsi pour mes plug-ins VIM, par exemple.
-
Lorsque vous déléguez une partie d'un projet à un tiers et que vous souhaitez intégrer son travail à un moment précis ou à une livraison spécifique. À nouveau, cela fonctionne lorsque les mises à jour ne sont pas trop fréquentes.
Merci à Finch pour ses excellentes explications sur les scénarios.
Conseils utiles
L'infrastructure submodule est efficace et permet de séparer et d'intégrer utilement des bases de code. Toutefois, pour certaines opérations simples, il n'existe ni procédure simplifiée, ni prise en charge efficace de l'interface de ligne de commande.
Si vous utilisez des submodules Git dans votre projet, vous avez déjà rencontré ce type d'opérations, sinon cela ne saurait tarder. Dans ces situations, vous devez chercher une solution. Encore et encore. Je vais vous faire gagner du temps : utilisez Instapaper, Evernote, ou mettez la page suivante dans vos favoris (:D:D) et vous serez paré pour un moment.
Voilà ce que j'ai pour vous :
Comme échanger un submodule Git avec votre propre fork ?
Il s'agit d'un workflow très commun : vous commencez à utiliser le projet d'une autre personne comme submodule, puis, après quelque temps, vous réalisez qu'il vous faut le personnaliser et l'adapter vous-même, vous souhaitez donc faire un fork du projet et remplacer le submodule par votre propre fork. Comment faire ?
Les submodules sont stockés dans .gitmodules
:
$ cat .gitmodules [submodule "ext/google-maps"] path = ext/google-maps url = git://git.naquadah.org/google-maps.git
Vous pouvez simplement modifier l'URL avec un éditeur de texte, puis exécuter la commande suivante :
$ git submodule sync
Ce faisant, vous mettez à jour .git/config
, qui contient une copie de cette liste de submodules (vous pouvez aussi vous contenter de modifier la section [submodule]
concernée de .git/config
manuellement).
Comment supprimer un submodule ?
C'est un besoin habituel, mais qui implique une procédure complexe. Pour supprimer un submodule, vous devez :
1. Supprimez la ligne concernée du fichier .gitmodules
. CSV.
2. Supprimez la section concernée de .git/config
.
3. Exécutez git rm --cached path_to_sous-module
(sans barre oblique à la fin).
4. Commitez et supprimez les fichiers du sous-module qui ne sont désormais plus suivis.
Comment réintégrer un submodule dans mon projet ?
Ou, en d'autres termes, comment retirer un submodule Git ? Si vous souhaitez simplement intégrer votre code de submodule au dépôt principal, il vous suffit de retirer le submodule et de rajouter les fichiers dans le dépôt principal :
1. Supprimez la référence au sous-module dans l'index, mais conservez les fichiers :
git rm --cached submodule_path (no trailing slash)
2. Supprimez le fichier .gitmodules ou , si vous avez plusieurs sous-modules, modifiez ce fichier en supprimant le sous-module de la liste :
git rm .gitmodules
3. Supprimez le fichier de métadonnées .git (n'oubliez pas de faire un backup) :
rm -rf submodule_path/.git
4. Ajoutez le sous-module
à l'index du dépôt principal :
git add submodule_path git commit -m "remove submodule"
REMARQUE : la procédure indiquée ci-dessus est destructive pour l'historique du submodule. Si vous souhaitez conserver un historique conforme de vos submodules, vous devez utiliser un « merge ». Pour en savoir plus, reportez-vous à cette référence Stack Overflow très complète.
Comment ignorer les changements dans les submodules ?
Il se peut que vos sous-modules
se polluent (dirty
) d'eux-mêmes. Par exemple, si vous utilisez des commandes Git sous-modules
pour suivre vos plug-ins VIM, des fichiers locaux comme helptags
peuvent être créés ou modifiés. Malheureusement, git status ne va pas vous lâcher concernant ces changements, même si aucun d'eux ne vous intéresse et que vous ne souhaitez pas les commiter.
La solution est très simple. Ouvrez le fichier .gitmodules
à la racine de votre dépôt et, pour chaque submodule que vous voulez ignorer, ajoutez ignore = dirty
comme le montre cet exemple :
[submodule ".vim/bundle/msanders-snipmate"] path = .vim/bundle/msanders-snipmate url = git://github.com/msanders/snipmate.vim.git ignore = dirty
Merci à Nils pour ses explications géniales.
Attention ! Pièges dans les interactions avec les dépôts distants
Comme nous le rappelle le tutoriel sur les submodules Git de kernel.org, certains éléments sont importants lors des interactions avec vos dépôts distants.
Tout d'abord, toujours publier les changements apportés au submodule avant de publier les changements dans le superprojet qui le référence. Cette étape est essentielle pour permettre à d'autres personnes de cloner le dépôt.
Deuxièmement, n'oubliez jamais de commiter tous vos changements avant d'exécuter git submodule update
pour éviter qu'ils ne soient écrasés !
Conclusions
Grâce à ces conseils, vous êtes prêts à affronter bon nombre de workflows fréquemment utilisés avec les submodules. Dans un prochain billet, je vous en dirai plus sur les solutions alternatives à git submodule
.
Suivez-moi (@durdn) et l'incroyable équipe @Bitbucket pour plus d'infos passionnantes sur DVCS.
Partager cet article
Thème suivant
Lectures recommandées
Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.