Utilisation des branches

Rendu à ce chapitre, vous devriez avoir compris que chaque propagation crée une arborescence de fichiers entièrement nouvelle (appelée « révision ») dans le dépôt. Si ce n'est pas le cas, retournez vous informer sur les révisions dans la section intitulée « Révisions ».

Pour ce chapitre, nous reprendrons le même exemple qu'au Chapitre 1, Notions fondamentales. Souvenez-vous que votre collaboratrice Sally et vous partagez un dépôt qui contient deux projets, paint et calc. Notez cependant que dans la Figure 4.2, « Structure initiale du dépôt », le dossier de chaque projet contient désormais des sous-dossiers nommés trunk et branches. Les raisons de cette arborescence apparaîtront bientôt clairement.

Figure 4.2. Structure initiale du dépôt

Structure initiale du dépôt

Comme avant, supposons que Sally et vous avez tous deux une copie de travail du projet « calc ». Plus spécifiquement, vous avez chacun une copie de travail de /calc/trunk. Tous les fichiers du projet sont dans ce sous-dossier plutôt que dans /calc lui-même, parce que votre équipe a décidé que la « ligne principale » de développement du projet allait se situer dans /calc/trunk.

Disons que l'on vous a attribué la tâche d'implémenter une fonctionnalité du logiciel qui prendra longtemps à écrire et touchera à tous les fichiers du projet. Le problème immédiat est que vous ne voulez pas déranger Sally, qui est en train de corriger des bogues mineurs ici et là. Elle a besoin que la dernière version du projet (dans /calc/trunk) demeure en permanence utilisable. Si vous commencez à propager des changements petit à petit, vous allez sûrement rendre les choses difficiles pour Sally (ainsi que pour d'autres membres de l'équipe).

Une stratégie possible est de vous isoler : vous pouvez arrêter de partager des informations avec Sally pendant une semaine ou deux. C'est-à-dire commencer à modifier et à réorganiser les fichiers dans votre copie de travail, mais sans effectuer de propagation ni de mise à jour avant que vous n'ayez complètement terminé la tâche. Cette stratégie comporte certains risques. Premièrement, ce n'est pas sans danger. La plupart des gens aiment propager leurs modifications fréquemment, au cas où leur copie de travail aurait un accident. Deuxièmement, ce n'est pas très flexible. Si vous travaillez sur différents ordinateurs (vous avez peut-être une copie de travail de /calc/trunk sur deux machines différentes), vous aurez besoin de transférer manuellement vos changements entre les deux, ou bien de travailler sur une seule machine. De la même façon, il est difficile de partager vos changements en cours avec quelqu'un d'autre. Une des « bonnes pratiques » du monde du développement logiciel est de permettre à vos pairs de passer votre travail en revue au fur et à mesure. Si personne n'a accès à vos propagations intermédiaires, vous vous coupez d'éventuelles critiques et risquez de partir dans une mauvaise direction pendant des semaines avant que quelqu'un ne s'en aperçoive. Enfin, quand vous en aurez fini avec tous vos changements, vous pourriez avoir du mal à fusionner votre travail avec le code du reste de l'équipe. Sally (et les autres) peuvent avoir apporté de nombreux autres changements au dépôt, changements qui seront difficiles à incorporer dans votre copie de travail, notamment si vous lancez svn update après des semaines d'isolation.

Une solution bien meilleure est de créer votre propre branche, ou ligne de développement, dans le dépôt. Ceci vous permettra de sauvegarder fréquemment votre travail un peu boiteux sans interférer avec vos collaborateurs ; vous pourrez toutefois partager une sélection d'informations avec eux. Vous découvrirez comment tout cela fonctionne exactement au fur et à mesure de ce chapitre.

Création d'une branche

Créer une branche est très simple : il s'agit juste de faire une copie du projet dans le dépôt avec la commande svn copy. Subversion est capable de copier non seulement de simples fichiers, mais aussi des dossiers entiers. Dans le cas présent, vous voulez faire une copie du dossier /calc/trunk. Où doit résider la nouvelle copie ? Là où vous le désirez, cette décision faisant partie de la gestion du projet. Supposons que votre équipe ait pour convention de créer les branches dans la zone /calc/branches du dépôt et que vous vouliez nommer votre branche ma-branche-calc. Vous créez alors un nouveau dossier, /calc/branches/ma-branche-calc, qui commence ainsi sa vie en tant que copie de /calc/trunk.

Vous avez peut-être déjà utilisé svn copy pour copier un fichier vers un autre à l'intérieur d'une copie de travail. Mais il peut aussi être utilisé pour effectuer une copie « distante » entièrement à l'intérieur du dépôt. Il suffit de copier une URL vers une autre :

$ svn copy http://svn.exemple.com/depot/calc/trunk \
           http://svn.exemple.com/depot/calc/branches/ma-branche-calc \
      -m "Création d'une branche privée à partir de /calc/trunk."

Révision 341 propagée.

Cette commande entraîne une opération quasi-instantanée dans le dépôt, créant un nouveau dossier à la révision 341. Ce nouveau dossier est une copie de /calc/trunk, comme l'illustre la Figure 4.3, « Dépôt avec nouvelle copie » [21]. Bien qu'il soit aussi possible de créer une branche en utilisant svn copy pour dupliquer un dossier à l'intérieur de la copie de travail, cette technique n'est pas recommandée. Elle peut s'avérer assez lente, en fait ! Copier un dossier côté client est une opération linéaire en terme de durée, puisque chaque fichier et chaque dossier doit être dupliqué sur le disque local. Copier un dossier sur le serveur, par contre, est une opération dont la durée est constante et c'est ainsi que la plupart des gens créent des branches.

Figure 4.3. Dépôt avec nouvelle copie

Dépôt avec nouvelle copie

Travail sur votre branche

Maintenant que vous avez créé votre branche du projet, vous pouvez extraire une nouvelle copie de travail et commencer à l'utiliser :

$ svn checkout http://svn.exemple.com/depot/calc/branches/ma-branche-calc
A  ma-branche-calc/Makefile
A  ma-branche-calc/entier.c
A  ma-branche-calc/bouton.c
Révision 341 extraite.

Cette copie de travail n'a rien de spéciale ; elle correspond juste à un dossier différent du dépôt. Cependant, quand vous propagerez vos modifications, Sally ne les verra pas quand elle effectuera une mise à jour, car sa copie de travail correspond à calc/trunk (pensez bien à lire la section intitulée « Parcours des branches » plus loin dans ce chapitre : la commande svn switch est une méthode alternative pour créer une copie de travail d'une branche).

Imaginons qu'une semaine passe et que les propagations suivantes ont lieu :

  • Vous modifiez /calc/branches/ma-branche-calc/bouton.c, ce qui crée la révision 342.

  • Vous modifiez /calc/branches/ma-branche-calc/entier.c, ce qui crée la révision 343.

  • Sally modifie /calc/trunk/entier.c, ce qui crée la révision 344.

À présent, deux lignes de développement indépendantes (voir la Figure 4.4, « Historique des branches d'un fichier ») existent pour entier.c.

Figure 4.4. Historique des branches d'un fichier

Historique des branches d'un fichier

Les choses deviennent intéressantes quand on regarde l'historique des modifications apportées à votre copie de entier.c :

$ pwd
/home/utilisateur/ma-branche-calc

$ svn log -v entier.c
------------------------------------------------------------------------
r343 | utilisateur | 2002-11-07 15:27:56 -0600 (jeu. 07 nov. 2002) | 2 lignes
Chemins modifiés :
   M /calc/branches/ma-branche-calc/entier.c

* entier.c:  machiné le bidule.

------------------------------------------------------------------------
r341 | utilisateur | 2002-11-03 15:27:56 -0600 (jeu. 07 nov. 2002) | 2 lignes
Chemins modifiés :
   A /calc/branches/ma-branche-calc (from /calc/trunk:340)

Création d'une branche privée à partir de /calc/trunk.

------------------------------------------------------------------------
r303 | sally | 2002-10-29 21:14:35 -0600 (mar. 29 oct. 2002) | 2 lignes
Chemins modifiés :
   M /calc/trunk/entier.c

* entier.c:  modifié une docstring.

------------------------------------------------------------------------
r98 | sally | 2002-02-22 15:35:29 -0600 (ven. 22 fev. 2002) | 2 lignes
Chemins modifiés :
  A /calc/trunk/entier.c
* entier.c:  ajout du fichier dans ce projet.

------------------------------------------------------------------------

Notez bien que Subversion reprend tout l'historique du entier.c de votre branche à travers le temps, remontant même au delà du point où il a été copié. Il liste la création d'une branche en tant qu'élément de l'historique, parce qu'entier.c a été copié implicitement lorsque calc/trunk tout entier a été copié. Maintenant regardez ce qui se passe quand Sally lance la même commande sur sa copie du fichier :

$ pwd
/home/sally/calc

$ svn log -v entier.c
------------------------------------------------------------------------
r344 | sally | 2002-11-07 15:27:56 -0600 (jeu. 07 nov. 2002) | 2 lignes
 Chemins modifiés :
    M /calc/trunk/entier.c

 * entier.c:  corrigé un ensemble de coquilles.

 ------------------------------------------------------------------------
 r303 | sally | 2002-10-29 21:14:35 -0600 (mar. 29 oct. 2002) | 2 lignes
 Chemins modifiés :
    M /calc/trunk/entier.c

 * entier.c:  modifié une docstring.

 ------------------------------------------------------------------------
 r98 | sally | 2002-02-22 15:35:29 -0600 (ven. 22 fev. 2002) | 2 lignes
 Chemins modifiés :
   A /calc/trunk/entier.c

* entier.c:  ajout du fichier dans ce projet.

------------------------------------------------------------------------

Sally voit la modification due à sa propre révision 344, mais pas le changement que vous avez effectué dans la révision 343. Pour Subversion, ces deux propagations ont touché des fichiers différents dans des dossiers distincts. Néanmoins, Subversion indique bien que les deux fichiers partagent une histoire commune. Avant que la copie de branche n'ait été faite en révision 341, les fichiers ne faisaient qu'un. C'est pourquoi Sally et vous voyez tous les deux les modifications apportées en révisions 303 et 98.

Gestion des branches par Subversion : notions clé

Il y a deux leçons importantes à retenir de ce paragraphe. Premièrement, Subversion n'a pas de notion interne de branche — il sait seulement faire des copies. Quand vous copiez un dossier, le dossier qui en résulte n'est une « branche » que parce que vous le considérez comme tel. Vous aurez beau envisager ce dossier différemment ou le traiter différemment, pour Subversion c'est juste un dossier ordinaire auquel sont associées des informations extra-historiques.

Deuxièmement, à cause de ce mécanisme de copie, les branches de Subversion existent en tant que dossiers classiques du système de fichiers du dépôt. En cela, Subversion diffère des autres systèmes de gestion de versions, où les branches sont définies par l'ajout d'« étiquettes » extra-dimensionnelles à des groupes de fichiers. L'emplacement du dossier de votre branche importe peu à Subversion. La plupart des équipes ont pour convention de placer toutes les branches dans un dossier /branches, mais vous êtes libre d'inventer la convention qui vous plaît.



[21] Subversion n'accepte pas les copies entre des dépôts distincts. Quand vous utilisez des URLs avec svn copy et svn move, vous ne pouvez copier que des éléments faisant partie du même dépôt.