Blog myBlog = BlogFactory.getWordPressBlog();
Gérer un projet Maven multi-modules avec Git
J’ai récemment assisté à l’atelier Git avancé de Christophe Porteneuve. Au programme, de nombreuses choses intéressantes, dont les submodules Git, La partie de la formation les concernant m’intéressait particulièrement pour une problématique que je rencontre très fréquemment : travailler avec un projet Maven multi-modules.
Il y a bien sûr la solution qui consiste à utiliser un unique dépôt Git à la racine du projet. Ca fonctionne bien, mais pour des gros projets, je préfère avoir un dépôt dédié à chacun des modules Maven. Cela ne poserait aucun problème, s’il n’y avait une arborescence de répertoires entre le projet principal, et ses modules.
Voyons donc avec un exemple comment mettre en place une gestion de configuration séparée pour chacun des modules d’un projet Maven.
Créer le projet de démonstration
Commençons par créer le projet Maven multi-module qui va nous servir d’exemple. Pour faciliter cette étape, j’ai choisi d’utiliser l’archetype appfuse-modular-jsf (qui me fournit directement un projet de deux sous-modules).
1 | mvn archetype:generate -B -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-modular-jsf -DarchetypeVersion=2.0.2 -DgroupId=org.courtine -DartifactId=demo |
Si la création s’est bien passée, le projet dont nous allons nous servir doit ressembler à ça :
Nous avons donc pour la suite des évènements :
- le projet « demo »
- le module « demo-core »
- le module « demo-webapp »
Mise en place des dépôts distants
- création des dépôts distants (paradoxalement en local, pour simplifier le tutoriel, mais cela fonctionne évidemment avec des dépôts placés sur un serveur central) :
1 2 3 4 | cd $BARE_REPOS git init --bare demo-core.git git init --bare demo-webapp.git git init --bare demo.git |
- chargement de la première révision des modules dans le dépôt distant :
1 2 3 4 5 6 | cd $PROJECT_HOME/demo/core git init git add . git commit -m 'Initial revision' git remote add origin $BARE_REPOS/demo-core.git git push -u origin master |
On fait la même chose pour le module « demo-webapp ».
Le dépôt du projet Démo
Jusqu’ici, rien d’extraordinaire : nous avons deux dépôts distincts dans notre projet, chacun possédant un dépôt distant.
Passons maintenant au dépôt qui nous intéresse : celui du projet « Démo », qui va contenir les deux submodules.
1 2 3 4 | cd $PROJECT_HOME/demo/ git init git submodule add $BARE_REPOS/demo-core.git core git submodule add $BARE_REPOS/demo-webapp.git web |
Arrêtons-nous sur la commande git submodule add :
- le premier argument est l’adresse du dépôt distant du module
- le deuxième argument est le répertoire local dans lequel va se trouver ce module.
Après ces commandes, regardons le statut de notre projet :
Nous remarquons que la création des sous-modules a ajouté un fichier .gitmodules, listant les sous-modules (ainsi que les adresses de leurs dépôts distants respectifs). Nous remarquons aussi que la commande s’est bien comportée comme prévu : l’ensemble des fichiers des deux sous-modules n’est pas dupliqué dans le dépôt principal. Les core et web affichés dans le statut sont des références à la révision respective des sous-modules utilisée.
Si un sous-module est un projet partagé (librairie, etc.), il est ainsi possible dans le projet principal de se caler sur une révision précise de celle-ci (qui n’est pas forcément la dernière).
Finissons maintenant la mise en place du projet Démo :
1 2 3 4 | git add . git commit -m "Commit initial du projet Demo" git remote add origin $BARE_REPOS/demo.git git push -u origin master |
Utilisation
Cloner le dépôt
Pour un nouveau développeur qui arrive sur le projet, il faut commencer par cloner ce projet contenant des submodules. La marche à suivre est la suivante :
1 2 3 4 | git clone $BARE_REPOS/demo.git cd demo git submodule init git submodule update |
Pour aller plus vite (surtout utile dans le cas où les submodules ont eux-mêmes des submodules), on peut utiliser le raccourci suivant :
1 | git clone --recursive $BARE_REPOS/demo.git |
Travailler sur un submodule
Après avoir cloné un projet contenant un submodule, si on va dans le répertoire de celui-ci, on s’aperçoit que l’on est sur un « detached HEAD ». En effet, le git submodule update du projet principal récupère une référence précise du submodule, en se moquant de savoir si celle-ci correspond à une branche, un tag, etc.
Pour travailler sur le submodule, il faut donc se replacer sur une branche connue. Ca ne pose pas de problème particulier, mais il faut juste le savoir :
1 2 | cd $PROJECT_HOME/demo/core git checkout master |
Mettre à jour un submodule
La mise à jour d’un submodule se fait en plusieurs phases. Tout d’abord, la mise à jour du submodule lui-même :
1 2 3 4 | cd $PROJECT_HOME/demo/core # Modif... git commit -am "Modification du module" git push |
Dans le projet principal, un nouveau git status permet de voir qu’une modification du submodule a bien été détectée. Pour partager cette mise à jour, il ne faut donc pas oublier de la publier également dans le projet principal :
1 2 3 | cd $PROJECT_HOME/demo git commit -am "Nouvelle version du submodule" git push |
Ici, deux erreurs à ne pas faire :
- publier le submodule en oubliant de publier le projet principal
- pire : publier le projet principal en ayant oublié de publier le submodule. En local, on ne s’aperçoit de rien mais si un autre développeur fait une mise à jour, la référence du submodule dans le projet principal lui sera inconnue (car non publiée)…
Récupérer une mise à jour de submodule
Dernier piège : récupérer un submodule mis à jour (par un autre développeur) :
1 2 3 | cd $PROJECT_HOME/demo git pull git submodule update |
Le simple pull permet de récupérer la nouvelle révision de référence du submodule, mais pas le module lui-même. Pour cela, il faut le compléter d’un git submodule update.
Conclusion
Les submodules permettent donc de répondre convenablement à la problématique initiale. Cependant, avant de les mettre véritablement en place, il faut s’entraîner afin de bien comprendre leur mode de fonctionnement (on a très vite fait d’oublier une étape…).
| Imprimer l'article | Cette entrée a été posté par Benoît Courtine le 4 mars 2011 à 10 h 12 min, et placée dans Systèmes d'information. Vous pouvez suivre les réponses à cette entrée via RSS 2.0. Vous pouvez laisser une réponse, ou bien un trackback depuis votre site. |






about 1 year ago
Pourquoi préfères tu avoir un dépôt dédié à chacun des modules Maven (au lieu d’un unique dépôt Git à la racine du projet) ?
about 1 year ago
Certains modules (objets métiers, fonctionnalités de type « librairies ») peuvent être partagés entre plusieurs projets dans une entreprise. Leur affecter un dépôt propre permet de les inclure facilement dans plusieurs projets.