Subversion en action

Il est temps de passer de l'abstrait au concret. Dans cette section, nous vous montrons des exemples réels d'utilisation de Subversion.

URL des dépôts Subversion

Tout au long de ce livre, Subversion utilise des URL pour identifier des fichiers et des répertoires suivis en version au sein de dépôts Subversion. Pour la plupart, ces URL utilisent la syntaxe standard, permettant de spécifier les noms des serveurs et les numéros de port à l'intérieur même de l'URL :

$ svn checkout http://svn.exemple.com:9834/depot
…

Mais il existe quelques nuances dans la gestion des URL par Subversion qui doivent être notées. Par exemple, les URL ayant pour méthode d'accès file:// (utilisée pour les dépôts locaux) doivent posséder, en accord avec les conventions, soit un nom de serveur localhost , soit pas de nom de serveur du tout :

$ svn checkout file:///var/svn/depot
…
$ svn checkout file://localhost/var/svn/depot
…

D'autre part, les utilisateurs du procédé file:// sur les plateformes Windows doivent se servir d'une syntaxe qui est un « standard » officieux pour accéder à leurs dépôts se trouvant sur la même machine mais sur un disque différent du disque de travail habituel du client. Les deux syntaxes de chemin d'URL suivantes fonctionnent, X étant le disque sur lequel le dépôt se trouve :

C:\> svn checkout file:///X:/var/svn/depot
…
C:\> svn checkout "file:///X|/var/svn/depot"
…

Dans la seconde syntaxe, vous devez entourer l'URL de guillemets pour éviter que la barre verticale ne soit interprétée comme un symbole de redirection (un « pipe »). De plus, remarquez qu'une URL utilise des barres obliques (/) alors que la forme native (non-URL) d'un chemin sous Windows utilise des barres obliques inversées (\).

[Note] Note

Les URL Subversion file:// ne peuvent pas être utilisées dans un navigateur web classique de la même façon qu'une URL file:// habituelle. Lorsque vous essayez de visualiser une URL file:// dans un navigateur web classique, il lit et affiche le contenu du fichier situé à cet emplacement en interrogeant directement le système de fichiers. Cependant, les ressources de Subversion existent dans un système de fichier virtuel (cf. la section intitulée « Couche dépôt ») et votre navigateur ne comprend pas comment interagir avec ce système de fichiers.

Enfin, il faut noter que le client Subversion encode automatiquement les URL en cas de besoin, exactement comme le fait un navigateur web. Par exemple, si une URL contient un espace ou un caractère ASCII spécial, comme dans ce qui suit :

$ svn checkout "http://hote/chemin avec espace/projet/españa"

alors Subversion banalise les caractères spéciaux et se comporte comme si vous aviez tapé :

$ svn checkout http://hote/chemin%20avec%20espace/projet/espa%C3%B1a

Si l'URL contient des espaces, prenez bien soin de la placer entre guillemets, pour que votre shell traite le tout comme un unique argument du programme svn.

Copies de travail

Vous avez déjà découvert ce que sont les copies de travail ; nous allons maintenant vous expliquer comment le client Subversion les crée et les utilise.

Une copie de travail Subversion est une arborescence classique de répertoires de votre système local, contenant un ensemble de fichiers. Vous pouvez éditer ces fichiers comme vous le voulez et, s'il s'agit de code source, vous pouvez compiler votre programme à partir de ceux-ci de la façon habituelle. Votre copie de travail est votre espace de travail personnel privé : Subversion n'y incorporera jamais les changements d'autres personnes ni ne rendra jamais disponibles vos propres changements à d'autres personnes tant que vous ne lui demanderez pas explicitement de le faire. Vous pouvez même avoir plusieurs copies de travail d'un même projet.

Après que vous ayez apporté quelques modifications aux fichiers de votre copie de travail et vérifié qu'elles fonctionnent correctement, Subversion vous fournit des commandes pour « publier » vos changements vers les autres personnes qui travaillent avec vous sur votre projet (en les transmettant au dépôt). Si d'autres personnes publient leurs propres modifications, Subversion vous fournit des commandes pour fusionner ces changements dans votre copie de travail (en les obtenant du dépôt).

Une copie de travail contient également quelques fichiers supplémentaires, créés et gérés par Subversion, pour l'aider à effectuer ces opérations. En particulier, chaque répertoire de votre copie de travail contient un sous-répertoire appelé .svn, aussi appelé répertoire administratif de votre copie de travail. Les fichiers de chacun de ces répertoires administratifs permettent à Subversion d'identifier quels fichiers contiennent des modifications non-publiées et quels fichiers sont périmés vis-à-vis du travail des autres personnes.

Un dépôt Subversion contient bien souvent les fichiers (ou code source) de plusieurs projets ; habituellement, chaque projet est un sous-répertoire de l'arborescence du système de fichiers du dépôt. Dans cette situation, la copie de travail d'un utilisateur correspond à une sous-arborescence particulière du dépôt.

Par exemple, supposons que votre dépôt contienne deux projets logiciels, paint et calc. Chaque projet réside dans son propre sous-répertoire racine, comme indiqué dans la Figure 1.6, « Système de fichiers du dépôt ».

Figure 1.6. Système de fichiers du dépôt

Système de fichiers du dépôt

Pour obtenir une copie de travail, vous devez extraire une sous-arborescence du répertoire (le terme « extraire », « check out » en anglais, peut vous faire penser que cela a quelque chose à voir avec verrouiller ou réserver des ressources, mais ce n'est pas le cas ; cela crée simplement pour vous une copie privée du projet). Par exemple, si vous extrayez /calc, vous obtenez une copie de travail qui ressemble à ceci :

$ svn checkout http://svn.exemple.com/depot/calc
A    calc/Makefile
A    calc/entier.c
A    calc/bouton.c
Révision 56 extraite.

$ ls -A calc
Makefile  entier.c  bouton.c  .svn/

Les lettres A qui s'affichent dans la marge de gauche indiquent que Subversion est en train d'ajouter des éléments dans votre copie de travail. Vous avez désormais votre copie personnelle du répertoire /calc du dépôt, avec une entrée supplémentaire, .svn, qui contient des informations complémentaires nécessaires à Subversion, comme évoqué précédemment.

Supposons que vous fassiez des modifications à bouton.c. Comme le répertoire .svn se souvient de la date de modification et du contenu du fichier original, Subversion peut en déduire que vous avez modifié le fichier. Néanmoins, Subversion ne rend pas vos modifications publiques tant que vous ne lui dites pas de le faire. L'action de publication de vos modifications est plus communément appelée propagation (« commit » ou « check in » en anglais et, parfois, archivage ou livraison en français) des modifications au sein du dépôt.

Pour rendre publiques vos modifications, vous pouvez utiliser la commande Subversion svn commit :

$ svn commit bouton.c -m "Coquille corrigée dans bouton.c."
Ajout        bouton.c
Transmission des données .
Révision 57 propagée.

À présent, vos modifications de bouton.c ont été propagées au sein du dépôt, avec un commentaire décrivant ces changements (« vous avez corrigé une coquille »). Si un autre utilisateur extrait une copie de travail de /calc/, il va voir vos modifications dans la dernière version du fichier.

Supposons que vous ayez une collaboratrice, Sally, qui a extrait une copie de travail de /calc en même temps que vous. Lorsque vous propagez votre modification de bouton.c, la copie de travail de Sally reste inchangée ; Subversion ne modifie les copies de travail qu'à la demande des utilisateurs.

Pour mettre son projet à jour, Sally peut demander à Subversion de mettre à jour (« update » en anglais) sa copie de travail, en utilisant la commande svn update. Cela va intégrer vos modifications dans sa copie de travail, ainsi que celles qui ont été envoyées par d'autres personnes depuis qu'elle l'avait extraite.

$ pwd
/home/sally/calc

$ ls -A 
Makefile bouton.c entier.c .svn/ 

$ svn update
U    bouton.c
Actualisé à la révision 57.

En sortie, la commande svn update indique que Subversion a mis à jour le contenu de bouton.c. Remarquez que Sally n'a pas eu besoin de spécifier quels fichiers devaient être mis à jour ; Subversion utilise les informations contenues dans le répertoire .svn, ainsi que d'autres informations en provenance du dépôt, pour décider quels fichiers doivent être mis à jour.

Révisions

Une opération svn commit publie les modifications d'un nombre quelconque de fichiers et de répertoires en une seule opération atomique. Dans votre copie de travail, vous pouvez modifier le contenu des fichiers : créer, supprimer, renommer et copier fichiers et répertoires ; puis propager un ensemble de modifications en une seule transaction atomique.

Par « transaction atomique », on entend simplement ceci : soit toutes les modifications sont propagées dans le dépôt, soit aucune ne l'est. Subversion tente de conserver cette atomicité aussi bien face à des « plantages » de programmes, de systèmes d'exploitation ou de réseau, que face aux actions des autres utilisateurs.

Chaque fois que le dépôt accepte une propagation, ceci crée un nouvel état de l'arborescence du système de fichiers, appelé révision. Un numéro unique est associé à chaque révision, correspondant au numéro de la révision précédente augmenté de 1. La révision initiale d'un dépôt fraîchement créé porte le numéro 0 et ne consiste en rien d'autre qu'un répertoire racine vide.

La Figure 1.7, « Le dépôt » offre une vue intéressante du dépôt. Imaginez un tableau de numéros de révisions, commençant à 0 et s'étirant de la gauche vers la droite. Chaque numéro de révision correspond à une arborescence de système de fichiers située en-dessous de lui et chaque arborescence est une photo, un « instantané » (« snapshot » en anglais) du dépôt prise après une propagation.

Figure 1.7. Le dépôt

Le dépôt

Il est important de noter que les copies de travail ne correspondent pas toujours à une unique révision du dépôt ; elles peuvent contenir des fichiers provenant de plusieurs révisions différentes. Par exemple, supposons que vous extrayiez une copie de travail d'un dépôt dont la révision la plus récente est la numéro 4 :

calc/Makefile:4
     integer.c:4
     button.c:4

À cet instant, le répertoire de travail correspond exactement à la révision 4 du dépôt. Néanmoins, supposons que vous modifiiez bouton.c et que vous propagiez cette modification. En supposant qu'aucune autre propagation n'a eu lieu, votre propagation crée la révision 5 du dépôt et votre copie de travail ressemble maintenant à ceci :

calc/Makefile:4
    entier.c:4
    bouton.c:5

Supposons maintenant qu'à ce moment précis, Sally propage une modification d'entier.c, créant la révision 6. Si vous utilisez svn update pour mettre à jour votre copie de travail, elle ressemble alors à ceci :

calc/Makefile:6
    entier.c:6
    bouton.c:6

Les modifications apportées par Sally à entier.c apparaissent dans votre copie de travail et vos modifications sont toujours présentes dans bouton.c. Dans cet exemple, le texte de Makefile est identique dans les révisions 4, 5 et 6 mais Subversion marque votre copie de travail de Makefile comme étant à la révision 6 pour indiquer qu'elle est à jour. Ainsi, quand vous effectuez une mise à jour au niveau de la racine de votre copie de travail, celle-ci correspond en général à une révision donnée du dépôt.

Les copies de travail suivent l'évolution du dépôt

Pour chaque fichier d'un répertoire de travail, Subversion enregistre deux informations essentielles dans la zone administrative .svn/ :

  • la révision sur laquelle votre fichier de travail est basé (qui est appelée la révision de travail du fichier) et

  • la date et l'heure de la dernière mise à jour de la copie locale depuis le dépôt

À partir de ces informations, en dialoguant avec le dépôt, Subversion est capable de déterminer dans lequel des quatre états suivants se trouve un fichier de travail :

Inchangé et à jour

Le fichier est inchangé dans le répertoire de travail et aucune modification de ce fichier n'a été propagée vers le dépôt depuis sa révision de travail. Un appel à svn commit sur le fichier ne fera rien, un appel à svn update sur le fichier ne fera rien non plus.

Modifié localement et à jour

Le fichier a été modifié dans le répertoire de travail et aucune modification du fichier n'a été propagée dans le dépôt depuis la dernière mise à jour. Il existe des modifications locales qui n'ont pas été propagées vers le dépôt, donc un appel à svn commit sur le fichier permettra de publier vos modifications et un appel à svn update ne fera rien.

Inchangé et périmé

Le fichier n'a pas été modifié dans le répertoire de travail mais a changé dans le dépôt. Le fichier devra être mis à jour à un moment ou à un autre, pour l'amener au niveau de la dernière révision publique. Un appel à svn commit sur le fichier ne fera rien et un appel à svn update incorporera les dernières modifications dans votre copie de travail.

Modifié localement et périmé

Le fichier a été modifié à la fois dans le répertoire de travail et dans le dépôt. Un appel à svn commit sur le fichier va échouer, renvoyant comme erreur « Périmé » (« out-of-date » en anglais). Le fichier doit d'abord être mis à jour ; un appel à svn update va tenter de fusionner les modifications publiques avec les modifications locales. Si Subversion ne parvient pas à réaliser automatiquement cette fusion de manière crédible, il va laisser à l'utilisateur la tâche de résoudre le conflit.

Tout ceci peut sembler compliqué à gérer mais la commande svn status vous indique dans quel état se trouve n'importe quel élément de votre copie de travail. Pour plus d'informations sur cette commande, référez-vous à la section intitulée « Avoir une vue d'ensemble des changements effectués ».

Copies de travail mixtes, à révisions mélangées

Un principe général de Subversion est d'être aussi flexible que possible. Un type particulier de flexibilité est la capacité d'avoir une copie de travail contenant des fichiers et des répertoires avec un mélange de différents numéros de révision. Malheureusement, cette flexibilité a tendance à embrouiller un certain nombre de nouveaux utilisateurs. Si l'exemple précédent contenant des révisions mixtes vous laisse perplexe, voici une amorce d'explication à la fois sur les raisons pour lesquelles cette fonctionnalité existe et sur la façon de l'utiliser.

Mise à jour et propagation sont deux choses distinctes

Une des règles fondamentales de Subversion est que l'action de « pousser » ne déclenche pas une action de « tirer », ni l'inverse. Le simple fait que vous soyez prêt à soumettre vos nouvelles modifications au dépôt ne veut pas dire que vous êtes prêts à recevoir les modifications d'autres personnes. Et si vous avez de nouvelles modifications encore en cours, alors svn update fusionne élégamment les changements du dépôt avec les vôtres, plutôt que de vous forcer à les publier.

Le principal effet secondaire de cette règle est que la copie de travail a de la comptabilité supplémentaire à effectuer pour suivre les mélanges de révision et également être tolérante vis-à-vis de l'ensemble. Cela est rendu encore plus difficile par le fait que les répertoires eux-mêmes sont suivis en versions.

Par exemple, supposons que vous ayez une copie de travail qui soit intégralement à la révision 10. Vous éditez le fichier truc.html et réalisez ensuite un svn commit qui crée la révision 15 dans le dépôt. Après que la propagation ait réussi, nombreux sont ceux parmi les nouveaux utilisateurs qui s'attendraient à ce que toute la copie de travail soit à la révision 15, mais ce n'est pas le cas ! Un certain nombre de modifications ont pu avoir lieu dans le dépôt entre les révisions 10 et 15. Le client ne sait rien de ces changements qui ont été apportés au dépôt, puisque vous n'avez pas encore exécuté la commande svn update et la commande svn commit ne récupère pas les nouvelles modifications. D'un autre côté, si la commande svn commit téléchargeait automatiquement les modifications les plus récentes, alors il serait possible d'avoir toute la copie de travail à la révision 15 mais, dans ce cas, nous enfreindrions la règle fondamentale selon laquelle « pousser » et « tirer » doivent demeurer des actions distinctes. Ainsi, la seule chose que le client Subversion peut faire en toute sécurité est de marquer le fichier truc.html, et lui seulement, comme étant à la révision 15. Le reste de la copie de travail reste à la révision 10. Seule l'exécution de la commande svn update permet de récupérer les dernières modifications et de marquer la copie de travail comme étant à la révision 15.

Des révisions mélangées sont normales

Le fait est qu' à chaque fois que vous exécutez la commande svn commit, votre copie de travail se retrouve composée d'un mélange de révisions. Les éléments que vous venez juste de propager sont marqués comme ayant un numéro de révision plus élevé que tous les autres. Après plusieurs propagations (sans mise à jour entre-temps), votre copie de travail va contenir tout un mélange de révisions. Même si vous êtes la seule personne à utiliser le dépôt, vous constaterez quand même ce phénomène. Pour étudier votre propre mélange de révisions de travail, utilisez la commande svn status avec l'option --verbose (voir la section intitulée « Avoir une vue d'ensemble des changements effectués » pour plus d'informations).

Souvent, les nouveaux utilisateurs n'ont pas du tout conscience que leur copie de travail contient des révisions mélangées. Cela peut être déroutant car beaucoup de commandes client sont sensibles à la révision de travail de l'élément qu'elles examinent. Par exemple, la commande svn log est utilisée pour afficher l'historique des modifications d'un fichier ou d'un répertoire (cf. la section intitulée « Affichage de l'historique »). Lorsque l'utilisateur appelle cette commande sur un objet de la copie de travail, il s'attend à obtenir l'historique complet de celui-ci. Mais si la révision de travail de l'objet est assez ancienne (souvent parce que svn update n'a pas été lancé depuis un certain temps), alors c'est l'historique de l'ancienne version de l'objet qui est affiché.

Un mélange de révisions est utile

Si votre projet est suffisamment complexe, vous allez découvrir qu'il est parfois pratique d'effectuer un retour en arrière forcé (c'est-à-dire de faire une mise à jour vers une version plus ancienne que celle que vous avez déjà) sur certaines parties de votre copie de travail vers des révisions plus anciennes ; vous apprendrez comme le faire dans le Chapitre 2, Utilisation de base. Vous avez peut-être envie de tester une version précédente d'un sous-module contenu dans un sous-répertoire ou bien de comprendre comment un bogue est apparu pour la première fois dans un fichier donné. C'est le côté « machine à voyager dans le temps » d'un logiciel de gestion de versions, la fonctionnalité qui vous permet de déplacer n'importe quelle partie de votre copie de travail en avant ou en arrière dans le temps.

Les mélanges de révisions ont des limites

Quelle que soit la façon dont vous utilisez les mélanges de révision dans votre copie de travail, il existe des limites à cette flexibilité.

Premièrement, vous ne pouvez pas propager la suppression d'un fichier ou d'un répertoire qui n'est pas complètement à jour. Si une version plus récente de l'élément existe dans le dépôt, votre tentative de suppression est rejetée, afin de vous empêcher de détruire accidentellement des modifications dont vous n'aviez pas encore connaissance.

Deuxièmement, vous ne pouvez propager la modification des métadonnées d'un répertoire que si celui-ci est complètement à jour. Vous apprendrez comment associer des « propriétés » à des éléments dans le Chapitre 3, Sujets avancés. La révision de travail d'un répertoire définit un ensemble précis d'entrées et de propriétés et propager la modification d'une propriété d'un répertoire périmé risquerait de détruire des propriétés dont vous n'aviez pas encore connaissance.