Concept de base, workflows et conseils

Nicola Paolucci
Nicola Paolucci
Retour à la liste

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 par-ci, par-là, 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

  1. Concept de base
  2. Workflows possibles
  3. Conseils utiles
  4. Comme échanger un submodule Git avec votre propre fork ?
  5. Comment puis-je supprimer un submodule ?
  6. Comment réintégrer un submodule dans mon projet ?
  7. Comment ignorer les changements dans les submodules ?
  8. Attention ! Pièges dans les interactions avec les dépôts distants
  9. Conclusions

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.

Submodules are tracked by the exact commit specified in the parent project, not a branch, a ref, or any other symbolic reference.

They are never automatically updated when the repository specified by the submodule is updated, only when the parent project itself is updated. As very clearly expressed in the Pro Git chapter mentioned earlier:

When you make changes and commit in that [submodule] subdirectory, the superproject notices that the HEAD there has changed and records the exact commit you’re currently working off of; that way, when others clone this project, they can re-create the environment exactly.

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 ou 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

By remembering this core concept and reflecting on it, you can understand that submodule support some workflows well and less optimally others. There are at least three scenarios where submodules are a fair choice:

  • 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é.

  • When you have a component that isn't updated very often and you want to track it as a vendor dependency. I do this for my vim plugins for example.

  • 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.

Credit to finch for the well-explained scenarios.

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.

If you use git submodules in your project you either have run into these or you will. When that happens you will have to look the solution up. Again and again. Let me save you research time: Instapaper, Evernote or old school bookmark this page (:D:D) and you will be set for a while.

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

This updates .git/config which contains a copy of this submodule list (you could also just edit the relevant [submodule] section of .git/config manually).

Référence Stack Overflow

Comment puis-je 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.
  2. Delete the relevant section from .git/config.
  3. Run git rm --cached path_to_submodule (no trailing slash).
  4. Commiter et supprimer les fichiers du submodule qui ne sont désormais plus trackés.

    Référence Stack Overflow

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 submodule dans l'index, mais conservez les fichiers :

    git rm --cached submodule_path (no trailing slash)
  2. Delete the .gitmodules file or if you have more than one submodules edit this file removing the submodule from the list:

    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 submodule à 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 ?

Sometimes your submodules might become dirty by themselves. For example if you use git submodules to track your vim plugins, they might generate or modify local files like helptags. Unfortunately, git status will start to annoy you about those changes, even though you are not interested in them at all, and you have no intention of committing them.

The solution is very simple. Open the file .gitmodules at the root of your repository and for each submodule you want to ignore add ignore = dirty, like in this example:

[submodule ".vim/bundle/msanders-snipmate"]
path = .vim/bundle/msanders-snipmate
url = git://github.com/msanders/snipmate.vim.git
ignore = dirty

Thanks to Nils for the great explanation.

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.

Prêt à découvrir Git ?

Essayez ce tutoriel interactif.

Démarrez maintenant