Gestion de Version avec Subversion : Concepts de Base
[Note de l'éditeur : Ceci est un aperçu du second chapitre de Version Control with Subversion à sortir chez O'Reilly]
Ce chapitre est une courte introduction à Subversion.
Si vous n’avez aucune notion de la gestion de version, ce chapitre est écrit pour vous.
Nous commencerons par une discussion générale des concepts de gestion de version, puis nous présenterons les idées propres à Subversion, et nous montrerons quelques exemples simples de l’utilisation de Subversion.
Bien que les exemples dans ce chapitre présentent des personnes partageant du code source de programmes, rappelez-vous que Subversion peut gérer toutes sortes de collections de fichiers - il n’est pas limité à aider les développeurs.
Le Repository
Subversion est un système centralisé pour partager l’information. Tout repose sur le repository, qui est l’endroit où sont stockées les informations. Le repository stocke les informations sous la forme d’une arborescence — une hiérarchie typique de fichiers et répertoires. Les clients se connectent au repository, puis lisent et écrivent sur ces fichiers. En écrivant des données, le client rend les informations disponibles aux autres ; en lisant les données, le client reçoit les informations des autres. La Figure 2-1 illustre ceci. Pourquoi cela est-il intéressant ? Jusqu’à présent, cela ressemble à la définition d’un serveur de fichier classique. Et, en effet, le repository est une sorte de serveur de fichier, mais pas tout à fait du même genre. Ce qui rend le repository de Subversion spécial, c’est qu’il se rappelle toutes les modifications qui y sont écrites : toute modification sur tout fichier, ainsi que les modifications sur la hiérarchie des répertoires eux-mêmes, tel que des ajouts, des suppressions et des réarrangements de fichiers et de répertoires.

Figure 2-1. Un système client/serveur classique.
Quand un client lit les données depuis le repository, il ne voit que la dernière version du système de fichiers.
Mais le client peut également voir les états précédents du système de fichiers.
Par exemple, un client peut poser des questions sur l’historique comme, Que contenait ce répertoire mercredi dernier ? ou Quelle est la dernière personne ayant modifiée ce fichier, et qu’a-t-elle fait ?
C’est ce genre de questions qui est au coeur de tout système de gestion de versions : des systèmes qui sont conçus pour enregistrer et conserver un historique des modifications sur les données au fil du temps.
Les Modèles de Gestion de Versions
Le rôle principal d’un système de gestion de versions est de permettre l’édition collaborative et le partage de données.
Cependant, différents systèmes utilisent différentes stratégies pour l’accomplir.
La Problématique du Partage de Fichiers
Tous les systèmes de gestion de versions doivent résoudre le même problème fondamental : comment le système peut-il mettre les données à disposition des utilisateurs, tout en les empêchant de se marcher les uns sur les autres ?
Considérez le scénario montré dans la Figure 2-2.
Supposez que nous ayons deux collègues, Harry et Sally.
Ils décident tous les deux d’éditer le même repository au même moment.
Si Harry sauvegarde ses modifications dans le repository le premier, alors il est possible que (peu de temps après) Sally écrase accidentellement ces modifications par sa propre version de fichier.
Bien que la version du fichier de Harry ne soit pas complètement perdue (puisque le système enregistre chaque modification), les changements apportés par Harry ne seront pas présents dans la version de Sally, parce qu’elle n’a jamais vu les modifications apportées par Harry.
Le travail de Harry est quand même perdu - ou tout du moins n’apparaît pas dans la version finale du fichier - par accident.
C’est de toute évidence une situation que vous voulez éviter à tout prix !
La solution du Verrouiller-Modifier-Déverrouiller
De nombreux systèmes de gestion de versions utilisent le modèle verrouiller-modifier-déverrouiller pour répondre à ce problème.
Dans un tel système, le repository permet à une seule personne à la fois de modifier le fichier.
Premièrement, Harry doit verrouiller le fichier avant toute modification.
Verrouiller le fichier ressemble beaucoup à l’emprunt d’un livre à la bibliothèque ; si Harry a verrouillé le fichier, alors Sally ne peut pas le modifier.
Si elle tente de le faire, le système l’en empêche.
Tout ce qu’elle peut faire c’est lire le fichier, et attendre que Harry finisse ses modifications et déverrouille le fichier.
Après qu’Harry a déverrouillé le fichier, son tour est terminé, et maintenant Sally peut prendre le sien pour modifier le fichier en le verrouillant.
La Figure 2-3 démontre cette solution simple.

Figure 2-2. Le problème à éviter.
Le problème avec cette technique de verrouillage est qu’elle est un peu restrictive, et il se peut que les utilisateurs aient à faire la queue :
- Le verrouillage peut créer des problèmes d’administration
- Parfois Harry verrouille un fichier et l’oublie.
Entre temps Sally attend pour modifier ce fichier.
Et Harry part en vacances.
Maintenant, Sally doit faire appel à l’administrateur pour forcer le verrou de Harry.
Cette situation entraîne des contretemps inutiles. - Le verrouillage peut provoquer des sérialisations inutiles
- Que se passe-t-il si Harry édite le début d’un fichier et que Sally veut éditer la fin du même fichier ?
Ces modifications ne se chevauchent pas du tout.
Ils pourraient facilement éditer le fichier simultanément, et aucun problème ne serait à craindre, si ces modifications sont correctement mises ensemble.
Il ne devrait pas y avoir besoin d’attendre son tour dans ce genre de situation. - Le verrouillage peut créer un faux sentiment de sécurité
- Imaginez que Harry verrouille et édite le fichier A, tandis que Sally verrouille et édite le fichier B en même temps.
Mais supposez que A et B dépendent l’un de l’autre, et que les modifications faites soient sémantiquement incompatibles.
Tout à coup, A et B ne fonctionnent plus ensemble.
Le système de verrouillage était incapable d’empêcher ce problème - et pourtant il a fait croire qu’il n’y aurait pas de problème.
Il est très facile pour Harry et Sally d’imaginer qu’ayant verrouillé leur fichier, chacun commence une tâche isolée en toute sécurité, et qu’en conséquence cela les empêche de discuter des incompatibilités de modifications évoquées juste avant.

Figure 2-3. La solution verrouiller-modifier-déverrouiller.
La solution Copier-Modifier-Fusionner
Subversion, CVS et d’autres utilisent le modèle copier-modifier-fusionner comme alternative au verrouillage.
Dans ce modèle, chaque interface utilisateur contacte le repository et crée une copie de travail personnelle - qui est une copie locale des fichiers et répertoires du repository.
Les utilisateurs travaillent en parallèle, modifiant leur copie privée.
Enfin, les copies privées sont fusionnées ensemble en une nouvelle version, la version finale.
Le système de gestion de versions aide souvent à la phase de fusion, mais parfois, c’est l’utilisateur qui doit y prendre part pour que tout se passe correctement.
Voici un exemple.
Disons que Harry et Sally créent chacun une copie de travail d’un même projet, copié à partir du repository.
Ils travaillent en parallèle, et effectuent des modifications sur leur copie du même fichier A.
Sally sauvegarde ses modifications dans le repository la première.
Quand Harry essaie de sauvegarder ses modifications un peu plus tard, le système l’informe que sa version de fichier A est trop vieille.
Alors Harry effectue par son client une fusion des nouvelles modifications récupérées depuis le repository et de sa copie de travail du fichier A.
Il y a de grandes chances pour que les modifications de Sally n’empiètent pas sur les siennes ; une fois qu’il a intégré les deux modifications, il peut sauvegarder sa copie vers le repository.
Les figures 2-4 et 2-5 montrent ce processus.

Figure 2-4. La solution copier-modifier-fusionner
Mais que se passe-t-il si les modifications de Sally empiètent sur les modifications de Harry ?
On appelle cette situation un conflit et, en général, ce n’est pas un gros problème.
Quand Harry demande à son client de fusionner les dernières modifications du repository avec celles de sa copie de travail, sa copie de fichier A est marquée comme étant en état de conflit : il pourra voir les deux modifications et choisir entre les deux.
Notez que le logiciel ne peut pas automatiquement résoudre les conflits ; seul un homme est capable de comprendre et de faire les choix intelligents.
Une fois que Harry a résolu les conflits - peut-être après en avoir discuté avec Sally - il peut en tout sécurité sauvegarder le fichier vers le repository.
Le modèle copier-modifier-fusionner peut paraître un peu chaotique, mais en pratique, tout se passe en douceur.
Les utilisateurs peuvent travailler en parallèle, sans jamais s’attendre l’un l’autre.
Quand ils travaillent sur les même fichiers, il se trouve que la plupart du temps, leurs modifications ne se chevauchent pas ; les conflits sont rares.
Et le temps passé à la résolution des conflits est bien moindre que le temps perdu par le système de verrouillage.

Figure 2-5. La solution verrouiller-modifier-déverrouiller (suite).
En fait, tout dépend d’un facteur critique : la communication entre utilisateurs.
Quand les utilisateurs communiquent peu, les risques de conflits syntaxique et sémantique augmentent.
Ne vous laisser donc pas bercer par la sécurité illusoire du système à verrouillage ; dans les faits, le verrouillage réduit la productivité.
Subversion en Action
Il est temps de passer de la théorie à la pratique.
Dans cette section, nous montrerons de vrais exemples d’utilisation de Subversion.
Copies de Travail
Vous savez déjà ce que sont les copies de travail ; maintenant nous allons vous montrer comment le client de Subversion les crée et les utilise.
Une copie de travail de Subversion est une arborescence classique sur votre système local, qui contient une collection de fichiers.
Vous pouvez éditer ces fichiers comme vous le souhaitez, et si ce sont des fichiers source, vous pouvez compiler votre programme comme d’habitude.
Votre copie de travail est votre zone de travail privée : Subversion n’intégrera jamais les modifications d’autres personnes, ni ne rendra vos modifications disponibles à d’autres, à moins que vous ne le lui demandiez spécifiquement.
Après avoir fait quelques modifications des fichiers de votre copie de travail et vérifié qu’elles sont correctes, Subversion vous offre quelques commandes pour publier vos modifications vers les autres personnes travaillant avec vous sur le projet (en écrivant sur le repository).
Si d’autres personnes publient leurs modifications, Subversion vous offre des commandes pour fusionner ces modifications avec votre répertoire de travail (en lisant depuis le repository).
Une copie de travail contient également des fichiers supplémentaires, créés et maintenus par Subversion, pour l’aider dans ces opérations.
En particulier, chaque répertoire de votre copie de travail contient un sous-répertoire nommé .svn, aussi appelé le répertoire administratif de la copie de travail.
Les fichiers dans chaque répertoire administratif aident Subversion à reconnaître les fichiers contenant des modifications non publiées, et les fichiers trop vieux par rapport aux modifications des autres.
Un repository classique de Subversion contient souvent les fichiers (ou code source) pour plusieurs projets ; généralement, chaque projet est un sous-répertoire dans l’arborescence du repository.
Dans cette configuration, la copie de travail correspond en général à une sous-arborescence du repository.
Par exemple, supposez que vous ayez un repository contenant deux projets, paint et calc.
Chaque projet se situe dans le répertoire de niveau supérieur, comme montré en Figure 2-6.
Pour obtenir une copie de travail, vous devez faire un check out des sous-arborescences du repository.
(Le terme check pourrait faire penser à un verrouillage ou une réservation de ressources, mais ce n’est pas le cas ; il crée simplement une copie privée pour vous.)
Par exemple, si vous faites un check out /calc, vous obtiendrez une copie de travail comme ceci :
$ svn checkout http://svn.example.com/repos/calc A calc A calc/Makefile A calc/integer.c A calc/button.c $ ls -a calc Makefile integer.c button.c .svn/
La suite des lettres A indique que Subversion ajoute des éléments à votre copie de travail.
Vous avez maintenant une copie personnelle du répertoire /calc du repository, avec une entrée supplémentaire –.svn– qui contient des informations supplémentaires nécessaires à Subversion, comme nous l’avons vu.
Imaginez que vous effectuiez une modification sur button.c.
Comme le répertoire .svn se souvient des modifications de date et de contenu sur le fichier, Subversion peut savoir que vous avez modifié le fichier.
Cependant, Subversion ne rend pas vos modifications publiques tant que vous ne lui demandez pas de le faire.
La publication de vos modifications est plus connue sous le terme de commit (ou check in).

Figure 2-6. Le système de fichier du repository
Pour publier vos modifications vers les autres, vous pouvez utiliser la commande commit de Subversion :
$ svn commit button.c Sending button.c Transmitting file data . Committed revision 57.
Maintenant, vos modifications sur button.c ont été copiées vers le repository ; si un autre utilisateur effectue un check out de /calc, il verra les modifications que vous avez apportées dans la dernière version du fichier.
Supposez que vous ayez une collaboratrice, Sally, qui récupère une copie de travail de /calc au moment même où vous l’avez faite.
Quand vous effectuez un commit de vos modifications sur button.c, la copie de travail de Sally reste inchangée ; Subversion ne fait que modifier les copies de travail à la demande de l’utilisateur.
Pour mettre son projet à jour, Sally peut demander à Subversion de mettre à jour sa copie de travail, en utilisant la commande update de Subversion.
Ceci intègre vos modifications à la copie de travail de Sally, ainsi que toutes celles qui ont été commitées depuis qu’elle a effectué son check out.
$ pwd /home/sally/calc $ ls -a .svn/ Makefile integer.c button.c $ svn update U button.c
Les URLs du RepositoryOn peut accéder aux repositories de Subversion par différentes méthodes : Pour la plupart, les URLs de Subversion utilisent une syntaxe standard permettant d’utiliser des noms de serveur et des numéros de port dans l’URL. $ svn checkout file:///path/to/repos ... $ svn checkout file://localhost/path/to/repos ... De plus, les utilisateurs du schéma file: sur la plateforme Windows doivent utiliser une syntaxe standard non officielle pour accéder aux repositories situés sur la même machine, mais sur un disque différent que le disque de travail courant du client. C:\> svn checkout file:///X:/path/to/repos ... C:\> svn checkout "file:///X|/path/to/repos" ... Avec la deuxième syntaxe, vous devez mettre des doubles quotes autour de l’URL afin que le caractère “barre verticale” ne soit pas interprété comme un caractère pipe. Notez qu’une URL utilise ordinairement des caractères slash même si la forme native (qui n’est pas une URL) sous Windows utilise des anti-slash. Table 2-1. URLs d’accès au repository
|
La sortie de la commande svn update indique que Subversion a mis à jour le contenu de button.c.
Notez que Sally n’a pas eu besoin de spécifier les fichiers à mettre à jour ; Subversion utilise les informations dans le répertoire .svn, et d’autres informations dans le repository, pour décider quels fichiers ont besoin d’être mis à jour.
Révisions
Une opération svn commit peut publier les modifications intervenues sur n’importe quel nombre de fichiers ou répertoires en une seule transaction atomique.
Dans votre copie de travail, vous pouvez modifier le contenu des fichiers ; créer, supprimer, renommer et copier des fichiers et des répertoires ; puis effectuer un commit pour valider l’ensemble des modifications comme une seule unité.
Dans le repository, chaque commit est traité en tant que transaction atomique : soit toutes les modifications sont prises en compte, soit aucune.
Subversion essaie de garder cette atomicité même en cas de plantage de l’application ou du système, problèmes réseaux, et d’autres actions utilisateur.
Chaque fois que le repository accepte un commit, il crée un nouvel état de l’arborescence de fichiers appelé une révision.
A chaque révision est assignée un nombre entier unique, plus grand que le nombre de la dernière révision.
La révision initiale d’un repository nouvellement créé est numérotée à 0, et n’est constituée que d’un répertoire racine vide.
La Figure 2-7 illustre une façon intéressante de visualiser le repository.
Imaginez un tableau de nombres de révision, commençant à 0 et s’étalant de gauche à droite.
Chaque nombre de révision possède une arborescence de fichiers, et chaque arborescence est une vue de l’état du repository après chaque commit.

Figure 2-7. Le repository
Nombres de Révision GlobaleContrairement à d’autres systèmes de gestion de version, les nombres de révisions utilisés par Subversion s’appliquent à l’arborescence toute entière, pas seulement aux fichiers individuels. |
Il est important de noter que les copies de travail ne correspondent pas toujours à une seule révision du repository ;
elles peuvent contenir plusieurs révisions différentes.
Par exemple, supposez que vous effectuiez un check out depuis le repository dont la révision la plus récente est 4 :
calc/Makefile:4 integer.c:4 button.c:4
A ce moment, cette copie de travail correspond exactement à la révision 4 du repository.
Cependant, supposez que vous modifiiez button.c, et effectuiez un commit des modifications.
En supposant qu’aucun autre commit n’ait été fait, votre commit créera la révision 5 au niveau du repository, et votre copie de travail ressemble à cela :
calc/Makefile:4 integer.c:4 button.c:5
Supposez qu’à ce moment, Sally effectue un commit d’une modification sur integer.c, créant par là une révision 6.
Vous utilisez svn update pour mettre votre copie de travail à jour ainsi :
calc/Makefile:6 integer.c:6 button.c:6
Les modifications de Sally sur integer.c apparaissent sur votre copie de travail, et votre modification existe toujours dans button.c.
Dans cet exemple, le texte du Makefile est identique dans les révisions 4, 5 et 6, mais Subversion marque votre copie de travail comme une révision 6, pour indiquer qu’elle est toujours valable.
Ainsi, après avoir effectué une mise à jour depuis la racine de votre copie de travail, le fichier correspond exactement à la révision du repository.
Comment les Copies de Travail Suivent le Repository
Pour chaque fichier dans le répertoire de travail, Subversion enregistre deux informations essentielles dans la partie administrative .svn/ :
- la révision sur laquelle est basée votre fichier de travail (on l’appelle la révision de travail du fichier)
- la dernière date à laquelle la copie locale a été mise à jour par le repository.
Par cette information, obtenue en communiquant avec le repository, Subversion peut dire dans lequel des quatre états suivants se trouve le fichier de travail :
- Non modifié, et actualisé
- Le fichier est inchangé dans répertoire de travail, et aucune modification sur ce fichier n’a été validée vers le repository depuis sa révision de travail.
Un svn commit, ou un svn update du fichier ne feront rien. - Modifié localement, et actualisé
- Le fichier a été modifié dans le répertoire de travail, et aucune modification sur ce fichier n’a été validée vers le repository depuis sa révision de base.
Il existe des modifications ; donc un svn commit de ce fichier effectuera une publication des modifications, mais un svn update du fichier ne fera rien. - Nom modifié, et obsolète
- Le fichier n’a pas été modifié dans le répertoire de travail, mais il l’a été dans le repository.
Le fichier devra être à terme mis à jour, pour le synchroniser avec la révision publique.
Un svn commit du fichier ne fera rien, mais un svn update du fichier récupérera les dernières modifications dans votre copie de travail. - Modifié localement, et obsolète
- Le fichier a été modifié à la fois dans le répertoire de travail et dans le repository.
Un svn commit du fichier échouera et affichera une erreur (car obsolète).
Le fichier devrait d’abord être mis à jour ; un svn update essaiera de fusionner les modifications publiques avec les modifications locales.
Si Subversion ne peut pas effectuer la fusion de façon automatique, c’est l’utilisateur qui devra résoudre les conflits.
Ceci peut paraître beaucoup de travail pour suivre les modifications, mais la commande svn status vous montrera l’état de chaque élément de votre copie de travail.
Pour plus d’informations sur cette commande, voyez “svn status”.
Les Limites des Révisions Mixtes
En principe, Subversion essaie d’être aussi souple que possible.
Une de ces possibilités est d’avoir une copie de travail contenant des révisions de différents numéros.
De prime abord, il n’est pas évident de voir pourquoi cette flexibilité peut être considérée comme un avantage.
Après un commit, la révision de travail des fichiers et répertoires des fichiers commités est plus récente que le reste de la copie de travail.
C’est un peu chaotique.
Comme démontré précédemment, la copie de travail peut toujours être ramenée à une seule révision en utilisant svn update.
Pourquoi quelqu’un souhaiterait-il délibérément différentes révisions de travail ?
En considérant que votre projet est suffisamment complexe, vous découvrirez qu’il peut être nécessaire parfois de revenir à un état antérieur de vos copies de travail ; vous verrez comment dans le chapitre 3.
Peut-être voudriez-vous tester une version antérieure d’un sous module, contenue dans un sous-répertoire, ou encore examiner un certain nombre d’anciennes versions d’un fichier dans le contexte de l’arborescence actuelle.
Quelle que soit la façon dont vous créez un mixte de numéros de révisions dans votre copie de travail, il existe des limitations à cette flexibilité.
Premièrement, vous ne pouvez pas effectuer de commit sur la suppression d’un fichier ou répertoire qui n’est pas à jour.
Si une nouvelle version de l’élément existe dans le repository, votre requête sera rejetée pour vous éviter de détruire accidentellement des modifications que vous n’auriez pas vues.
Deuxièmement, vous ne pouvez pas effectuer de commit des modifications sur les metadata d’un répertoire, à moins qu’il ne soit à jour.
Vous verrez comment attacher des propriétés à un élément en Chapitre 6.
La révision de travail d’un répertoire définit un ensemble spécifique d’entrées et de propriétés, et donc effectuer un commit d’une propriété sur un répertoire obsolète pourrait détruire les propriétés que vous n’auriez pas vues.
Conclusion
Nous avons vu un certain nombre de concepts fondamentaux de Subversion dans ce chapitre :
- Nous avons introduit les notions de repository central, de copie de travail du client et de tableau d’arborescence de révision du repository.
- Nous avons donné des exemples simples d’utilisation de Subversion par deux collègues pour publier et recevoir les modifications l’un de l’autre, en utilisant le modèle copier-modifier-fusionner.
- Nous avons évoqué la façon dont Subversion suit et gère l’information dans la copie de travail.
Maintenant, vous devriez avoir une bonne idée de la façon dont fonctionne Subversion dans les cas généraux d’utilisation.
Fort de cette connaissance, vous devriez être prêt pour le chapitre suivant, qui propose une description détaillée des commandes et fonctionnalités de Subversion.

Textes originaux en anglais sur O’Reilly : Version Control with Subversion: Basic Concepts par Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato
Chargement
Commentaires récents