Git : le partage de sources amélioré
Cela fait déjà un petit moment que je suis devenu fan de Git. Mes collègues que je saoule régulièrement, et ceux qui étaient là à l’OpenREX que j’y avais consacré en Juillet dernier, le savent ! Mais jusqu’à récemment, je devais me contenter d’utiliser Git en “sous-marin” via git-svn sur les projets sur lesquels j’ai travaillé. Un moyen de nettement améliorer l’usage de SVN, certes, mais une frustration de ne pas pouvoir pleinement utiliser toute la puissance de Git.
Il y a quelques mois, j’ai commencé un nouveau projet, et il m’a semblé que toutes les conditions étaient réunies pour tenter une expérience “full git” :
- un projet au forfait, pour un gros client qui nous laisse libre de nos outils ;
- un projet de relativement courte durée (environ 3 mois) ;
- une équipe réduite de deux autres développeurs (donc seulement deux personnes à convaincre, puis à former) ;
- un abonnement à GitHub souscrit par Ippon, permettant donc d’avoir des dépôts privés ;
- le feu vert de mon chef ;
- un alignement Mars-Jupiter favorable dans le troisième quadrant de Neptune.
Organisation
Etant donné la taille réduite de l’équipe, j’ai opté pour une organisation simple : un dépôt central hébergé sur GitHub, et un clône sur la machine de chaque développeur. Les développeurs ont le droit de pousser directement sur le dépôt central. On se rapproche ici d’un modèle centralisé. Ce modèle peut avoir des limites, notamment lorsque la taille des équipes devient grosse, mais on peut dans ce cas là introduire des niveaux intermédiaires (un dépôt central par équipe par exemple). Dans notre cas, tous les développeurs se trouvant dans un rayon de 3 mètres, ce modèle était largement suffisant et un peu de communication orale suffisait à ne pas se marcher sur les pieds.
Workflow
Développement
Restait ensuite à définir un workflow de travail. Celui que nous avons mis en pratique est très fortement inspiré de ce maintenant fameux billet que je vous recommande d’aller lire ici.
Il peut se résumer de la façon suivante:
- La branche master ne contient que des releases taguées, prêtes à être déployées;
- La branche develop est la branche ou se fait l’intégration des fonctionnalités pour la prochaine release;
- Chaque fonctionnalité est codée dans une branche à part, et mergée sur la branche develop une fois terminée et testée.
L’idée de ce workflow est de grouper ensemble les commits faisant partie d’un même ensemble logique (une fonctionnalité). Le but est d’encourager des commits fréquents et unitaires, sans risques de déstabiliser la branche d’intégration (develop), puisque celle-ci ne contient que des fonctionnalités terminées et testées (en théorie).
En pratique, le workflow ressemble à ceci:
Nous sommes sur la branche develop Création d'une nouvelle branche $ git co -b feature/maNouvelleFeature # code ... code ... code $ git commit -a -m "Rajoute bidule" #code ... code ... code $ git commit -a -m "Implémente machin"# Retour sur la branche develop $ git co develop # On se met à jour $ git pull $ git merge --no-ff feature/maNouvelleFonctionalité # Ici, on teste que le merge fonctionne correctement, et on résoud les conflits éventuels # Et enfin, on pousse le tout sur le dépôt central $ git push
C’est à ce moment là qu’il faut faire preuve de pas mal de pédagogie pour expliquer que oui, c’est un peu plus compliqué, mais en fait, c’est mieux que de faire :
code ... code ... code pendant 3 semaines $ svn update $ svn commit
Les avantages de faire des commits unitaires et fréquents sont multiples (historique plus détaillé et plus facile à naviguer, facilité à trouver les régressions, facilité à revenir en arrière lorsqu’on s’engage dans une mauvaise piste…), mais les habitudes d’un développeur habitué à SVN sont dures à changer.
Saurez-vous distinguer le développeur habitué à Git du développeur habitué à SVN ?
Releases
Le workflow que nous avons utilisé pour faire nos releases est également inspiré du billet mentionné ci-dessus, et se résume aux étapes ci-dessous :
- une fois toutes les fonctionnalités mergées sur la branche develop, on crée une branche de release (par exemple release/0.3);
- sur cette branche, on prépare la release : changements des versions dans les pom.xml (par exemple, de 0.3-SNAPSHOT en 0.3), corrections de dernière minute…
- sur la branche develop, on change les versions des poms pour la prochaine version de développement (par exemple 0.4-SNAPSHOT),
- une fois la branche de release prête, on la merge dans master (pour rappel, la branche master ne contient que des versions releasées)
- on tag la version mergée dans master
- on merge la branche master dans develop : cette étape permet de rapatrier dans la branche develop les éventuels corrections faites sur la branche de release pendant la phase de stabilisation, et de faire en sorte que le commit taggé soit un ancêtre du commit courant (ce qui est logique : on travaille pour la 0.4, donc on est, topologiquement parlant, “après” la version 0.3)
- on pousse le tout (branches develop et master, ainsi que le nouveau tag) sur le dépôt central.
L’avantage de ce workflow est de pouvoir préparer et stabiliser une release, tout en permettant à d’autres développeurs de continuer à développer et intégrer des fonctionnalités pour la prochaine version. Je l’admet, dans notre cas, nous aurions pu grandement le simplifier, étant donné que l’effort de stabilisation était commun et se faisait directement sur la branche develop. La branche de release n’a donc plus vraiment de raison d’être, mais il était intéressant tout de même d’expérimenter ce workflow.
Outils
Etant un fervent partisan de la ligne de commande, je ne m’embarrasse pas de beaucoup d’outils graphiques, à part GitX de temps en temps. Par contre, mes collègues sous Windows ont eu besoin d’un outil graphique pour les accompagner dans leur apprentissage de Git. Malheureusement, notre projet était basé sur Flex, ce qui nous obligeait à utiliser FlashBuilder, l’environnement d’Adobe, qui est basé sur Eclipse Galileo (3.5). Nous n’avons donc pas pu utiliser le plugin EGit qui commence à devenir très utilisable mais ne fonctionne qu’avec Eclipse Helios.
Une des seules alternatives restantes est donc TortoiseGit, l’équivalent du vénérable TortoiseSVN pour le monde Git. C’est un outil relativement complet, qui supporte un grand nombre de fonctionnalités, même avancées (push, pull / pull –rebase, rebase interactif, merge, commit, diff, etc…). C’est donc un outil intéressant, et qui nous a bien aidé. Cependant, il n’est pas sans défaut. En particulier, je le trouve parfois, un peu “fouillis”, avec un grand nombre de fenêtres différentes qui donnent parfois l’impression d’un manque de cohérence, et des workflows pas forcément évidents à deviner. A noter également l’utilisation de termes qui ne correspondent pas toujours à la terminologie de Git (par exemple, “revert” dans TortoiseGit ne fait pas la même chose qu’un “git revert”).
En ce qui concerne l’intégration continue, il n’a suffit que de quelques minutes pour installer le plugin Git dans Jenkins pour pouvoir récupérer les sources à partir de GitHub. Il existe également un plugin GitHub qui permet lorsqu’on clique sur un commit d’être redirigé vers la vue GitHub du commit en question.
Bilan
Globalement, l’expérience a été un succès. Un outil de versionnement est quelque chose qu’un développeur utilise tous les jours. Introduire un nouvel outil, pas forcément facile à prendre en main, peut donc représenter un risque pour un projet avec un un planning serré. Le fait que cela se soit bien passé tient à mon avis à plusieurs facteurs:
- une taille d’équipe réduite, permettant de supporter la montée en compétence
- des développeurs prêts à jouer le jeu
- l’existence d’un Plan B en cas de problème (exporter les sources et les importer dans SVN)
- savoir être pragmatique : étant donné la flexibilité qu’apporte Git, il est important d’avoir un workflow établi et formalisé, mais il faut savoir laisser le temps à quelqu’un qui apprend de digérer les différents concepts, et de faire des erreurs, quitte à avoir parfois un historique plus compliqué que nécessaire. Il a d’ailleurs été intéressant d’observer l’évolution de la façon d’utiliser Git de mes collègues, passant d’une méthode “à la SVN” au début (un seul gros commit au bout d’une semaine, oubli de faire un “git pull” avant de merger sa branche), à une méthode “à la Git” (commits plus fréquents, merges bien faits, utilisation de fonctionnalités plus avancées telles que le stash ou le bisect).
Au final, l’utilisation de Git n’a pas du tout été un frein pour le projet, mais a au contraire apporté plus de flexibilité pour les développeurs après une phase d’adaptation (branches locales, stash, vrais merges…).
Le futur
Ce première expérience m’a permis de tester l’utilisation de Git “dans la vraie vie”, d’expérimenter des workflows de développement, mais il y a d’autres pistes que j’espère pouvoir explorer un jour :
- utilisation plus poussée de GitHub : utilisation des tickets ou du wiki (dans notre cas, nous avons gardé l’outillage standard d’Ippon, basé sur Trac)
- expérimenter un workflow un peu différent, là encore en utilisant GitHub : un fork par développeur, puis utilisation des “pull requests” afin de promouvoir la revue de code
- intégration avec Maven et son module SCM afin de faciliter les releases
- utilisation du plugin pour Eclipse
- …
Conclusion
Ce que je vais dire est aujourd’hui presque une banalité : utiliser Git en entreprise, oui, ça marche. Certes, ça demande de changer quelques habitudes, ce qui n’est jamais facile, mais cela ne reste au final qu’un outil, et un outil suffisamment flexible pour s’adapter à différentes utilisations. Pas la peine d’être un gros projet Open Source ultra-distribué pour bénéficier de Git : il est également possible de l’utiliser de façon plus centralisée, proche de ce qu’on peut avoir avec SVN, mais avec tout le confort pour les développeurs que Git apporte.
Etant donné la place qu’est en train de prendre Git en ce moment (pour rappel, plus d’un million de projets sur GitHub), le nombre de projets Open Source qui migrent ou ont migré vers Git (Eclipse, Spring, Hibernate, Seam, …), il me semble difficile d’y échapper encore longtemps, donc autant s’y préparer maintenant !
Je ne recommande pas de se lancer tête baissée avec Git dans tous vos projets, ou de l’imposer par la force, mais si vous avez quelques collègues motivés et un projet qui s’y prête, alors demandez à votre chef un abonnement à GitHub (si ce n’est pas déjà fait), et tentez l’experience sur votre prochain projet !