Gestion de sources, versions de logiciels

Lorsqu’on développe un logiciel, il est absolument nécessaire d’utiliser un outil de gestion de sources. Évidemment, il serait possible de stocker ses fichiers dans un répertoire. Mais si vous voulez travailler sérieusement, vous aurez besoin de stocker les différentes versions de vos sources, pour suivre leur évolution au fil du temps ; et si vous travaillez à plusieurs sur le même projet, cela devient impossible.

Les logiciels de gestion de sources permettent à plusieurs personnes de travailler sur les mêmes fichiers, chacun dans leur coin, puis de tout rassembler pour obtenir une version continuellement à jour des sources. Ils apportent des fonctions permettant de définir des versions globales. Il existe un grand nombre de ces systèmes :

  • Les ancêtres RCS et CVS ont laissé la place à Subversion, qui offre des fonctionnalités supplémentaires bien appréciables. Ce sont des systèmes centralisés faciles à appréhender et à installer, et sont sous licence libre.
  • De nouveaux système sont apparus, basés sur un modèle décentralisé. Parmi ceux-ci, ont peut noter que les plus connus dans le monde de l’open-source sont Bazaar (sponsorisé par Canonical, à l’origine de la distribution Linux Ubuntu), Git (utilisé pour le noyau Linux) et Mercurial.
  • Du côté des logiciels propriétaires, les plus connus sont Visual SourceSafe de Microsoft et BitKeeper (qui a été utilisé pour le noyau Linux jusqu’en 2005).

Je vais vous présenter l’utilisation de ces outils, en utilisant l’exemple de Subversion (SVN en abrégé) car c’est le système de plus répandu et celui que j’utilise ; mais ces concepts sont toujours valables.

Principes généraux

Gestion basique

A la base, les sources d’un projet sont disponibles sur la branche principale (trunk). Les développeurs y récupèrent les sources (checkout) sur leur propre environnement de travail, et y ajoutent leurs versions modifiées (commit).

 

Plusieurs utilisateurs peuvent récupérer les sources et committer leurs modifications.

 

La mise-à-jour (update) permet de récupérer les modifications commitées par les autres utilisateurs. Une bonne pratique : avant de committer, il faut mettre-à-jour pour récupérer les dernières modifications committées par les autres utilisateurs.

 

Tags

Lorsqu’un ensemble de modifications aboutit à une version stable que l’on souhaite pouvoir retrouver à l’avenir, il faut faire un tag du repository. C’est comme faire une copie, une photographie à un instant donné, qui est mise de côté.

 

Branches

Le modèle de développement checkout/update/commit fonctionne très bien lorsque les modifications sont assez simples pour que le TRUNK soit toujours dans un état stable (sans bug de régression). Par contre, dès qu’un lot de modifications fait prendre le moindre risque (quant à sa durée ou à sa complexité), on créera une branche qui servira à effectuer ce développement. Chaque branche se retrouve à vivre sa propre vie, avec ses propres checkout/update/commit.

Pour transférer des modifications d’une branche à une autre, il faut faire un merge. Par exemple, lorsqu’un développement est terminé sur une branche qui lui est dédié, on effectuera un merge depuis la branche vers le TRUNK, pour y rapatrier les modifications.

 

Branches de maintenance

Il existe un cas un peu particulier, celui des branches de maintenance. Quand on pose un tag pour créer une version qui sera utilisée en production, on continue par la suite les développements ; mais si jamais il faut faire une petite correction, on ne peut pas importer directement en production les dernières modifications ayant été commitées. Dans ce cas-là, on crée une branche à partir de la version qui nous intéresse, sur laquelle on pourra effectuer les corrections.

 

Bonne pratiques

  • Updatez fréquemment, pour récupérer les modifications commitées par les autres développeurs. Updatez toujours avant de commiter.
  • Commitez souvent, mais commitez toujours des modifications stables. Un commit ne doit pas rendre les sources inutilisables (bug de régression, erreur de syntaxe, fichier qui ne compile plus, …).
  • Ne jamais commiter sur un tag. Les tags sont des « snapshots » immuables.
  • Ne jamais créer une branche à partir d’une branche. Seul le trunk peut être « branché ».
  • Quand vous commitez, indiquez le nom de la branche au début du commentaire.
trunk: Ajout de vérifications d'erreur. sms-alert: Connexion au broker de SMS.
  • Limiter le nombre de branches actives. Ne créez pas de nouvelle branche sans l’aval du directeur technique, et seulement si nécessaire. Si une branche n’est plus utile, signifiez-le pour qu’elle soit effacée.
  • Quand vous créez une branche, indiquez dans le commentaire le numéro de révision ou le tag à partir duquel la branche est créée.
sms-alert: Création de la branche de développement des alertes SMS, à partir de la révision [79]. statitics: Création de la branche de statistiques, à partir du tag 1.3.1.
  • Utilisez svn move/svn rename pour déplacer et renommer les fichiers. Ne pas les effacer du repository, puis les re-ajouter depuis un autre emplacement (mauvaise habitude venant de CVS).
  • Concernant les merges :
    • Ne pas faire de merge directement d’une branche à une autre. Les mises-à-jour doivent être faites sur le trunk d’abord, puis backportées (voir plus bas).
    • Toujours faire d’abord un merge avec l’option –dry-run pour tester, avant de faire le vrai merge.
    • Indiquer clairement la teneur du merge dans le commentaire : « trunk: Merge 72:81 depuis la branche sms-alert. »
    • A chaque tag posé sur le trunk, faire un « backport » (un merge du trunk vers une branche) vers toutes les branches actives. Etudiez chaque branche au cas-par-cas, pour voir si elle peut recevoir le backport.
    • A chaque backport, indiquer dans le commentaire de la branche backportée le numéro de révision : « sms-alert: Backport depuis [81]. »

Normalisation

Il faut obligatoirement se forcer à respecter une norme pour le nommage des tags et des branches. Voici celle que j’utilise, que vous êtes libres d’adapter en fonction de vos besoins.

Dans le cadre du processus classique de livraison, il existe 3 types de tags qui peuvent être posés :

  • versions instables, nommées X.Y.Z, avec X le numéro de version majeure, Y le numéro impair de version mineure, et Z le numéro de révision.
    • 0.1.0, 0.1.1, 0.1.2, 0.3.0, 0.3.1, …
    • 1.1.0, 1.3.0, 1.3.1, 1.3.2, …
  • versions stables, nommées X.Y.0, avec X le numéro de version majeure, Y le numéro pair de version mineure. Ne peut être créé qu’à partir du trunk.
    • 0.2.0, 0.4.0, …
    • 1.0.0, 1.2.0, …
  • versions de maintenance, nommées X.Y.Z, avec X le numéro de version majeure, Y le numéro pair de version mineure, et Z le numéro de révision. Peut être créé à partir d’une branche de maintenance, ou plus rarement à partir du trunk.
    • 1.0.1, 1.0.2, …
    • 1.2.1, 1.2.2, …

Les versions instables sont testées sur la plate-forme de recette.

  • Si la version testée n’est pas validée, des correctifs sont apportés, et un nouveau tag est créé, en incrémentant le numéro de version de maintenance. Si la version 2.1.0 n’est pas validée, elle sera corrigée, puis la version 2.1.1 sera testée à son tour. Si celle-ci n’est toujours pas valide, elle sera corrigée puis la version 2.1.2 sera testée.
  • Si la version testée est validée, elle est retagguée telle-quelle en incrémentant le numéro de version mineure, avec le numéro de maintenance à zéro. La version instable 1.3.0 devient, après validation, la version 1.4.0. La version 2.1.2 devient, après validation, la version 2.2.0.

De plus :

  • A ces tags s’ajoutent des tags de suivi des merges. Ils sont de la forme merged-X.Y.Z, avec X.Y.Z le numéro de version qui a été mergée vers le trunk.
  • Les branches de maintenance sont créées après chaque tag de version stable. Elles sont nommées X.Y.x, avec X le numéro de version majeure, et Y le numéro pair de version mineure.

 

7 commentaires pour “Gestion de sources, versions de logiciels

  1. Article très intéressant !
    Je fait mes début en sysadmin dans une entreprise de développement et c’est un sujet sur lequel j’avais du mal à les suivre !

    Merci !

  2. Merci pour cet article, très clair et concis !
    Les schémas aident beaucoup ( même si graphiquement ils sont un peu old-school ^^ )

  3. Héhé, pas de soucis, sinon j’ai une petite question, j’ai une architecture directement inspirée de ton modèle ( 2 branches : tma et évolution ) .

    Lorsque je merge la branche tma sur mon trunk , ça copie également le dossier Tags de la branche, ça devrait pas si ?

  4. @Vincent : En fait, il ne devrait y avoir qu’un seul dossier « tags », au même niveau que « trunk » et « branches ». Chaque branche n’a pas ses propres tags. Quand tu crée un tag, tu prends une photographie de ton code, qu’il soit sur le trunk ou sur une branche.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Notifiez-moi des commentaires à venir via email. Vous pouvez aussi vous abonner sans commenter.