Close

Sous-modules Git

Les submodules Git vous permettent de conserver un dépôt Git en tant que sous-répertoire d'un autre dépôt Git. Les submodules Git sont simplement une référence à un autre dépôt à un instant précis dans le temps. Les submodules Git permettent à un dépôt Git d'incorporer et de suivre l'historique des versions du code externe.


Qu'est-ce qu'un submodule Git ?


Souvent, un dépôt de code dépendra d'un code externe. Ce code externe peut être incorporé de plusieurs façons différentes. Le code externe peut être directement copié et collé dans le dépôt principal. Cette méthode présente l'inconvénient de perdre tout changement en amont dans le dépôt externe. Une autre méthode d'incorporation du code externe consiste à utiliser le système de gestion des paquets d'un langage comme Ruby Gems ou NPM. Cette méthode présente l'inconvénient de nécessiter une installation et une gestion des versions partout où le code d'origine est déployé. Ces deux propositions de méthodes d'incorporation ne permettent pas de suivre les modifications et les changements apportés au dépôt externe.

Un submodule Git est un enregistrement dans un dépôt Git hôte qui pointe vers un commit spécifique dans un autre dépôt externe. Les submodules sont très statiques et ne suivent que des commits spécifiques. Les submodules ne suivent pas les branches ou les réfs Git, et ne sont pas automatiquement mis à jour en même temps que le dépôt hôte. Lorsque vous ajoutez un submodule à un dépôt, un fichier .gitmodules est créé. Le fichier .gitmodules contient des métadonnées sur le mappage entre l'URL du projet de submodule et le répertoire local. Si le dépôt hôte possède plusieurs submodules, le fichier .gitmodules comportera une entrée pour chaque submodule.

Quand utiliser un submodule Git ?


Si vous avez besoin d'une gestion stricte des versions de vos dépendances externes, il peut être judicieux d'utiliser des submodules Git. Voici quelques exemples de leur utilisation.

  • 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.
  • 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.
Bases de données
Ressource connexe

Comment déplacer un dépôt Git complet

Logo Bitbucket
DÉCOUVRIR LA SOLUTION

Découvrir Git avec Bitbucket Cloud

Commandes courantes pour les submodules Git


Ajout d'un submodule Git

La commande submodule git add est utilisée pour ajouter un nouveau submodule à un dépôt existant. Voici un exemple qui permet de créer un dépôt vide et d'explorer les submodules Git.

$ mkdir git-submodule-demo
$ cd git-submodule-demo/
$ git init
Initialized empty Git repository in /Users/atlassian/git-submodule-demo/.git/

Cette séquence de commandes créera un répertoire git-submodule-demo, entrera dans ce répertoire et l'initialisera en tant que nouveau dépôt. Ensuite, nous ajouterons un submodule à ce nouveau dépôt.

$ git submodule add https://bitbucket.org/jaredw/awesomelibrary
Cloning into '/Users/atlassian/git-submodule-demo/awesomelibrary'...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 8 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.

La commande git submodule add prend un paramètre d'URL qui pointe vers un dépôt Git. Ici, nous avons ajouté awesomelibrary en tant que submodule. Git va immédiatement cloner le submodule. Nous pouvons ensuite examiner l'état actuel du dépôt en utilisant la commande git status

$ git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

new file:   .gitmodules
new file:   awesomelibrary

Il y a maintenant deux nouveaux fichiers dans le dépôt : .gitmodules et le répertoire awesomelibrary. L'examen du contenu de .gitmodules montre le nouveau mappage du submodule.

[submodule "awesomelibrary"]
path = awesomelibrary
url = https://bitbucket.org/jaredw/awesomelibrary
$ git add .gitmodules awesomelibrary/
$ git commit -m "added submodule"
[main (root-commit) d5002d0] added submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 awesomelibrary

Clonage de submodules Git

git clone /url/to/repo/with/submodules
git submodule init
git submodule update

Commande git submodule init

Le comportement par défaut de git submodule init est de copier le mappage à partir du fichier .gitmodules dans le fichier ./.git/config local. Cela peut sembler redondant, et l'utilité de la commande git submodule init peut être remise en question. La commande git submodule init a un comportement élargi dans lequel elle accepte une liste de noms de modules explicites. Cela permet un workflow d'activation des seuls submodules spécifiques qui sont nécessaires pour le travail sur le dépôt. Cela peut être utile s'il y a beaucoup de submodules dans un dépôt, mais qu'ils n'ont pas tous besoin d'être fetchés pour le travail que vous effectuez.

Workflows des submodules

Une fois que les submodules sont correctement initialisés et mis à jour dans un dépôt parent, ils peuvent être utilisés exactement comme des dépôts autonomes. Cela signifie que les submodules ont leurs propres branches et leur propre historique. Lorsque vous apportez des changements à un submodule, il est important de publier les changements du submodule, puis de mettre à jour la référence du dépôt parent vers le submodule. Continuons avec l'exemple awesomelibrary et apportons quelques changements :

$ cd awesomelibrary/
$ git checkout -b new_awesome
Switched to a new branch 'new_awesome'
$ echo "new awesome file" > new_awesome.txt
$ git status
On branch new_awesome
Untracked files:
  (use "git add <file>..." to include in what will be committed)

new_awesome.txt

nothing added to commit but untracked files present (use "git add" to track)
$ git add new_awesome.txt
$ git commit -m "added new awesome textfile"
[new_awesome 0567ce8] added new awesome textfile
 1 file changed, 1 insertion(+)
 create mode 100644 new_awesome.txt
$ git branch
  main
* new_awesome

Ici, nous avons changé de répertoire pour le submodule awesomelibrary. Nous avons créé un fichier texte new_awesome.txt avec du contenu, et nous avons ajouté et commité ce nouveau fichier dans le submodule. Changeons maintenant de répertoire pour revenir au dépôt parent et passons en revue l'état actuel du dépôt parent.

$ cd ..
$ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

modified:   awesomelibrary (new commits)

no changes added to commit (use "git add" and/or "git commit -a")

L'exécution de la commande git status nous montre que le dépôt parent est au courant des nouveaux commits du submodule awesomelibrary. Il n'entre pas dans le détail des mises à jour spécifiques, car c'est la responsabilité des dépôts du submodule. Le dépôt parent doit uniquement s'occuper de rattacher le submodule à un commit. Nous pouvons maintenant mettre à jour le dépôt parent en exécutant les commandes git add et git commit sur le submodule. Tout sera ainsi actualisé avec le contenu local. Si vous travaillez dans un environnement d'équipe, il est essentiel que vous fassiez ensuite un git push des mises à jour du submodule et du dépôt parent.

Lorsque vous utilisez des submodules, un motif de confusion et d'erreur courant est d'oublier de pusher les mises à jour pour les utilisateurs distants. Si nous revoyons le travail sur awesomelibrary que nous venons de faire, nous avons uniquement pushé les mises à jour vers le dépôt parent. Si un autre développeur voulait faire un pull du dernier dépôt parent, celui-ci pointerait vers un commit de awesomelibrary qu'il n'a pas pu faire parce que nous avions oublié de pusher le submodule. Le dépôt local des développeurs distants serait alors défaillant. Pour éviter ce scénario d'échec, assurez-vous de toujours commiter et pusher le submodule et le dépôt parent.

Conclusion


Les submodules Git sont un moyen puissant d'utiliser Git en tant qu'outil de gestion des dépendances externes. Pesez le pour et le contre des submodules Git avant de les utiliser, car il s'agit d'une fonctionnalité avancée qui peut nécessiter une courbe d'apprentissage pour que les membres de l'équipe l'adoptent.


Partager cet article

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.

Des personnes qui collaborent à l'aide d'un mur rempli d'outils

Le blog Bitbucket

Illustration DevOps

Parcours de formation DevOps

Démos Des démos avec des partenaires d'Atlassian

Fonctionnement de Bitbucket Cloud avec Atlassian Open DevOps

Inscrivez-vous à notre newsletter DevOps

Thank you for signing up