La notion de submodule permet d'avoir des dépôts git à l'intérieur d'un dépôt, tout en gardant la gestion des différents dépôts séparée.
Permet par exemple d'intégrer une lib à l'intérieur d'un projet, ou de séparer la gestion d'un projet en plusieurs sous-projets tout en pouvant les utiliser ensemble.
Référence : https://git-scm.com/book/en/v2/Git-Tools-Submodules
Permet par exemple d'intégrer une lib à l'intérieur d'un projet, ou de séparer la gestion d'un projet en plusieurs sous-projets tout en pouvant les utiliser ensemble.
Référence : https://git-scm.com/book/en/v2/Git-Tools-Submodules
Premiers pas
On se place dans le répertoiregit-tests
, qui contient déjà les dépôts repo1
, clone-repo1
, et on initialise un nouveau dépôt de test :
git init submodule-testOn crée un fichier et fait un premier commit :
cd submodule-test echo "première ligne" > fichier1.txt git add fichier1.txt git ci -m "Première ligne dans fichier1.txt"On ajoute maintenant le dépôt
repo1
comme submodule du dépôt submodule-test
:
git submodule add ../repo1/
Clonage dans '/path/to/git-test/submodule-test/repo1'... fait.On constate l'effet de la commande avec
git status
:
git st
Sur la branche main Modifications qui seront validées : (utilisez "git reset HEADNote La commande..." pour désindexer) nouveau fichier : .gitmodules nouveau fichier : repo1
git submodule add ../repo1/met une copie de
repo1
à la racine. Pour que repo1
soit recopié dans un sous-répertoire, on peut faire par exemple :
git submodule add ../repo1/ path/to/subdirectory
Fichier .gitmodules
Le fichier.gitmodules
a été créé par git :
cat .gitmodules
[submodule "repo1"] path = repo1 url = ../repo1/
Fichier .git/config
On peut voir aussi que.git/config
a été modifié :
[submodule "repo1"] url = /path/to/git-test/repo1 active = trueCe qu'on a fait est correct dans le cadre d'un exercice, mais pas adapté à la vie réelle, car si quelqu'un clone le dépôt
submodule-test
, git va aller voir le fichier .submodule
et essayer de le rappatrier depuis le path ../repo1
. A moins que l'utilisateur ait déjà le dépôt repo1
sur sa machine, il n'arrivera pas à récupérer le submodule.
Donc il aurait mieux valu créer le submodule avec un path que tous les utilisateurs peuvent utiliser, par exemple
git submodule add https://github.com/.../repo1.gitÇa ne nous empêche pas d'utiliser la version locale de
repo1
, en faisant :
git config submodule.repo1.url ../repo1Cela modifie
.git/config
, donc affecte uniquement la version locale du dépôt submodule-test
.
Récapitulation
project ├── .gitmodules ├── MyModule │ └── .git └── .git └── config
Dans le submodule
Si on va dedans, on peut voir que ce dépôt a été cloné avec tout son historique :cd repo1 git slog git remote -vPourtant, on voit que
.git
n'est plus un répertoire mais un fichier qui contient une seule ligne :
gitdir: ../.git/modules/repo1Le répertoire
.git/modules/repo1
est un répertoire (bare) qui contient le dépôt correspondant au submodule.
Cloner un dépôt avec submodules
git clone https://github.com/some-user/Project
git submodule init
git submodule updateou, directement :
git clone --recurse-submodules https://github.com/some-user/Project(fait init et update du submodule et de tous ses sous-modules).
Si on a oublié
--recurse-submodules
dans le clone, on peut faire :
git submodule update --init --recursive
Travailler avec les submodules
cd path/to/MyNewModule # vérifier si des modifications ont été apportées git fetch # récupérer ces modifications en local git merge origin/main
git diff --cached path/to/MyNewModule
git diff --cached --submodulePour éviter de faire
--submodule
à chaque fois :
git config --global diff.submodule log # ou alors git config --local diff.submodule logPour éviter de faire
cd path/to/MyNewModule
lors du fetch
:
git submodule update --remote path/to/MyNewModuleUtilise la branche
main
par défaut.
Pour suivre une autre branche :
git config -f .gitmodules submodule.MyNewModule.branch stableSans l'option
-f .gitmodules
, seul .git/config
est modifié.
Avec
-f .gitmodules
, la modification ira aussi dans .gitmodules
et sera donc versionnée. Tous ceux qui cloneront votre dépôt suivront cette branche.
Maintenant, quand on fait :
git pullgit nous indique que des changements ont eu lieu dans les submodules. Pour avoir aussi un résumé des changements :
git config status.submodulesummary 1Une fois les modifications enregistrées dans un commit, on peut les voir avec :
git log -p --submodule
Récupérer les changements dans un submodule
Un simplegit pull
fait un git fetch
dans nos submodules, mais pas un update
.
Il faut faire :
git submodule update --init --recursive
--recursive
est nécessaire si certains submodules ont eux-même des submodules - à toujours faire par sécurité au cas où un de nos submodule soit transformé pour avoir lui-même un submodule.
Si un submodule change d'url, le
git pull
ne va pas marcher.
Dans ce cas, faire :
git submodule sync --recursive
Travailler sur un submodule
Cas où on travaille à la fois sur le projet principal et dans différents submodules.Jusqu'à présent,
git submodule update
sert à rappatrier les changements dans les submodules, mais les sous-répertoires se trouvent dans un état de “detached HEAD”.
Pour remédier à cela, il faut aller dans chaque sous-module et indiquer à git quelle branche suivre :
cd path/to/submodule git checkout stablePour récupérer les changements dans les submodules, il faut dorénavant faire :
git submodule update --remote --mergeSi on fait des changements dans le submodule, faire par exemple :
git submodule update --remote --rebaseAttention, si on oublie
--merge
ou --rebase
, git va récupérer les changements et mettre le dédôt des sous-modules dans un état "detached HEAD".
Si on a travaillé en local sur un submodule et qu'un
git submodule update
génère des conflits, on doit les gérer (dans le répertoire de chaque submodule) comme on gère un conflit normal.
Attention, lorsqu'on fait un commit sur le dépôt principal, il faut aussi faire un push des commits effectués dans les submodules.
A DETAILLER
git push --recurse-submodules=on-demand
git push --recurse-submodules=check
git config push.recurseSubmodules check