HOWTO · Git
Mise à jour du sous-module dans Git
Ce tutoriel montre comment mettre à jour le sous-module à l'aide de plusieurs commandes dans Git.
Sur cette page
Git stocke un sous-module comme un dépôt situé à un chemin de l’arborescence de travail du dépôt parent. Le dépôt parent enregistre un commit précis du sous-module (un gitlink) ; il n’enregistre pas le nom d’une branche et ne suit pas automatiquement le dernier commit du sous-module. Celui-ci possède son propre historique et sa propre arborescence de travail. Modifier ses fichiers et mettre à jour le commit enregistré par le dépôt parent sont deux étapes liées, mais distinctes.
Comment Git enregistre les commits des sous-modules
Le fichier .gitmodules du dépôt parent associe les noms des sous-modules à leurs chemins et indique généralement leurs URL de clonage. Lorsque vous validez une modification dans un sous-module, le dépôt parent n’intègre pas ses fichiers à son propre commit. Son index peut plutôt enregistrer le nouveau commit du sous-module à ce chemin. Une personne qui clone ensuite le dépôt parent récupère le commit qui y est enregistré.
Il existe deux objectifs courants lors d’une mise à jour. Une commande git submodule update classique extrait le commit déjà enregistré par le dépôt parent et laisse généralement le sous-module en état HEAD détaché. L’option --remote récupère les données depuis le dépôt distant du sous-module et sélectionne un commit de sa branche de suivi à distance configurée. Le sous-module peut alors avancer au-delà du commit actuellement enregistré par le dépôt parent ; cette commande ne valide pas cette modification dans le dépôt parent.
Initialiser les sous-modules après le clonage
Pour cloner un projet et remplir récursivement ses sous-modules, utilisez git clone --recurse-submodules <repository-url>. Si vous l’avez déjà cloné sans cette option, exécutez git submodule update --init --recursive depuis le dépôt parent. --init initialise les sous-modules extraits à l’aide de la configuration du parent ; --recursive initialise également les sous-modules imbriqués.
La commande git submodule init copie les paramètres de sous-modules disponibles dans .gitmodules vers le fichier local .git/config ; elle ne crée pas .gitmodules. Ce fichier fait partie du projet parent et doit déjà exister (ou être ajouté par une personne qui le maintient). Si l’URL d’un sous-module a changé dans .gitmodules, git submodule sync --recursive copie l’URL mise à jour dans la configuration locale avant la récupération ou la mise à jour.
Mettre à jour les sous-modules depuis leurs dépôts distants
Pour récupérer les commits de suivi à distance et mettre à jour tous les sous-modules configurés, exécutez git submodule update --remote --recursive dans le dépôt parent. Git utilise la branche configurée pour le sous-module ; si aucune n’est spécifiée, il utilise la branche par défaut du dépôt distant. Un projet peut définir une branche dans .gitmodules, par exemple avec git config -f .gitmodules submodule.<name>.branch <branch>. Validez toute modification délibérée de .gitmodules dans le dépôt parent afin que les autres personnes qui collaborent au projet la reçoivent.
Une mise à jour depuis un dépôt distant peut laisser un sous-module sur un commit différent de celui enregistré par le dépôt parent. Git ne garantit pas que l’arborescence de travail sera propre : des modifications locales, des conflits ou des fichiers non suivis peuvent subsister. Vérifiez l’état du sous-module et du dépôt parent avant de poursuivre, et préservez ou résolvez les modifications locales avant de changer de commit.
Mettre à jour un seul sous-module ou tous les sous-modules
Ajoutez un chemin après les options pour limiter la mise à jour à un seul sous-module : git submodule update --remote -- path/to/submodule. Pour utiliser les commits enregistrés plutôt que les extrémités des branches distantes, omettez --remote : git submodule update -- path/to/submodule met à jour un sous-module, tandis que git submodule update --init --recursive initialise et extrait tous les commits enregistrés, y compris ceux des sous-modules imbriqués. Utilisez les chemins tels qu’ils apparaissent dans .gitmodules et dans l’arborescence de travail du dépôt parent. -- sépare les options du chemin.
Utilisez une mise à jour depuis le dépôt parent avec --remote lorsque vous souhaitez que Git récupère et extraie l’extrémité de la branche distante configurée. Utilisez une mise à jour classique lorsque vous voulez exactement le commit choisi par le projet parent, par exemple après qu’un commit de ce dépôt a modifié le gitlink.
Examiner et valider le commit enregistré du sous-module
Après une mise à jour depuis un dépôt distant ou l’extraction d’un commit choisi, revenez au dépôt parent et examinez git status et git diff --submodule. Un chemin de sous-module modifié signifie que le commit extrait visible par le dépôt parent diffère désormais de celui enregistré dans son index. Si c’est la version que le projet doit utiliser, ajoutez le chemin à l’index avec git add path/to/submodule, examinez git diff --cached --submodule, puis validez la modification du dépôt parent. Ce commit enregistre le gitlink choisi afin que les autres personnes qui collaborent au projet puissent le récupérer.
Si vous avez modifié et validé des fichiers dans le sous-module, ce commit appartient au dépôt du sous-module. Poussez-le vers ce dépôt si les autres personnes doivent pouvoir le récupérer, puis ajoutez à l’index et validez le chemin du sous-module mis à jour dans le dépôt parent. La validation du gitlink ne pousse pas le commit du sous-module et ne publie automatiquement aucun des deux dépôts ; poussez chaque dépôt selon votre flux de travail.
Choisir un commit précis ou une stratégie de fusion
Pour sélectionner un commit connu, accédez au répertoire du sous-module et extrayez-le avec git checkout <commit-id> (ou git switch --detach <commit-id>). L’extraction d’un commit place intentionnellement le sous-module en état détaché ; c’est utile pour épingler une version précise. Vérifiez ensuite l’état du dépôt parent et ajoutez le chemin du sous-module à l’index si vous souhaitez que le parent enregistre ce commit. L’extraction seule ne modifie pas le commit du dépôt parent.
Si vous souhaitez intégrer des modifications distantes à une branche du sous-module plutôt que d’effectuer une extraction détachée, accédez au sous-module, puis exécutez git switch <branch> suivi de git pull. Cette commande suit la configuration de la branche amont et peut créer un commit de fusion ou nécessiter la résolution de conflits. Elle ne correspond pas à git submodule update --remote, qui sélectionne le commit configuré pour le suivi à distance depuis la commande lancée au niveau du dépôt parent. Vous pouvez également demander une fusion ou un rebasage lors d’une mise à jour distante avec git submodule update --remote --merge ou git submodule update --remote --rebase ; examinez le résultat dans le sous-module et ajoutez son commit résultant à l’index du dépôt parent s’il doit être partagé.
Résoudre les problèmes courants de mise à jour
Si un répertoire est vide ou ne contient aucun fichier extrait après le clonage, initialisez-le avec git submodule update --init --recursive. Si une mise à jour reste sur un commit inattendu, vérifiez si vous avez utilisé le mode qui reprend le commit enregistré ou --remote, puis examinez la branche configurée avec git config -f .gitmodules --get submodule.<name>.branch. En l’absence de branche configurée, Git utilise la branche par défaut du dépôt distant.
Si Git signale des modifications locales ou refuse d’extraire un commit, examinez le git status propre au sous-module. Validez, mettez de côté ou préservez autrement ces modifications avant la mise à jour ; l’état du dépôt parent ne révèle pas tous les détails des modifications apportées dans le sous-module. En cas de conflit pendant une fusion ou un rebasage, résolvez-le dans le sous-module et terminez l’opération à cet endroit avant d’examiner le dépôt parent. Enfin, la modification du chemin d’un sous-module dans le dépôt parent n’est pas une erreur en soi : elle signifie que le commit extrait du sous-module diffère de celui que le parent enregistre actuellement. Décidez si vous souhaitez le conserver, puis validez cette modification dans le dépôt parent si elle est intentionnelle.