Ce billet était parti pour être une critique du livre Subversion, Pratique du développement collaboratif avec SVN mais je pense qu'il est finalement plus intéressant de prendre un exemple concrêt comme il est suggéré dans le titre du livre, l'apprentissage de Subversion passe surtout par la pratique. Ayant quelques petits scripts à mon actif, c'était le moment où jamais de m'y mettre !
Introduction
Si vous ne savez pas ce qu'est Subversion, ce billet présente peu d'intérêt pour vous mais c'est toujours intéressant de savoir que ça existe au cas où vous pourriez en avoir besoin. Subversion est un réécriture de CVS dont le principe est la gestion des versions concurrentes (la réécriture a permis de nombreuses améliorations). Cela permet l'édition d'un même fichier par plusieurs personnes en même temps et la gestion de la traçabilité des modifications (qui a fait quoi et quand en gros). Un serveur possède donc une version commune et chaque développeur travaille sur sa propre version locale qu'il syncronise avec le serveur le plus souvent possible pour éviter les conflits avec les autres développeurs en précisant à chaque fois la nature de la modification effectuée. C'est bien sûr beaucoup plus puissant mais l'idée de base est là.
Critique du livre
Rapidemment quand même, ce livre est tout ce qu'il y a de plus fonctionnel, il permet de se familiariser avec les commandes usuelles à travers de nombreux exemples. J'ai choisi ce livre car je voulais connaître les bonnes pratiques au niveau de l'organisation du code dans un dépôt. C'est toujours intéressant avant de se lancer dans de gros projets et on trouve difficilement de la documentation là-dessus (alors que toutes les commandes le sont, elles sont même directement en téléchargement sur le site d'Eyrolles ce qui est pratique si vous cherchez une commande sans avoir le livre sous les yeux).
L'ouvrage est court mais traite toutes les questions que je me posais, de la création/gestion d'un projet à l'administration du serveur, en passant par l'utilité des branches de livraison et l'intégration d'un code tiers. Le seul léger manque est l'interfaçage avec Trac dont l'auteur ne fait même pas mention, ce serait d'ailleurs un ajout intéressant pour une prochaine édition. Heureusement il existe un tutoriel en anglais très bien fait sur le site officiel si vous souhaitez aller plus loin (un tutoriel a même été rédigé en français sur Destination Linux).
Qu'est ce qui est « subversionable » ?
A peu près tout, même les binaires, mais encore faut-il que ça présente un intérêt. On stocke en général tout ce qui ne peut être généré dans le cas d'un projet de développement (par exemple vos fichiers compilés si vous possédez les sources c'est clairement inutile... sauf si votre projet est énorme bien sûr), mais certains y placent leurs sauvegardes, leur documentation, voire la totalité de leur /home, tout est possible, à vous de voir si c'est intéressant pour vous !
Personnellement, et dans le cadre de cet exemple, je n'y intègrerais que mes scripts python et plus particulièrement mon parser de fichiers PDB. Il peut être intéressant d'y placer vos fichiers de configuration système si vous avez passé du temps à les personnaliser (par exemple vos .* dans votre home :-)).
Création du dépôt
Mon script actuel se situe dans :
$ ll projects/PDBParser/
total 628 -rw-r--r-- 1 david david 101008 2006-04-20 12:00 1CDLA.pdb
-rw-r--r-- 1 david david 450198 2005-10-12 00:25 1SDK.pdb
-rw-r--r-- 1 david david 17992 2004-12-31 01:25 COPYING
-rw------- 1 david david 9168 2006-04-20 13:14 PDBParser.py
-rw------- 1 david david 3056 2006-04-20 13:20 README
-rw-r--r-- 1 david david 10253 2006-04-20 13:20 README.html
On va donc considérer que c'est ma copie locale de travail. Les fichiers *.pdb sont des données, COPYING contient la licence et README.html est généré à partir de README avec rst2html.
Pour l'exemple, je vais placer mon dépôt ou repository Subversion en local aussi à l'adresse suivante (assurez vous que ce dossier existe et que vous ayez les droits pour le faire) :
$ mkdir /home/david/work/svn/repository $ svnadmin create /home/david/work/svn/repository/
Et effectuer l'import initial de mon code :
$ svn import -m "Import initial du script" projects/PDBParser/ file:///home/david/work/svn/repository/PDBParser/trunk
Ajout projects/PDBParser/README.html
Ajout projects/PDBParser/1SDK.pdb
Ajout projects/PDBParser/1CDLA.pdb
Ajout projects/PDBParser/COPYING
Ajout projects/PDBParser/PDBParser.py
Ajout projects/PDBParser/READMERévision 1 propagée.
Petite vérification du statut de ma copie locale :
$ svn status projects/PDBParser
? projects/PDBParser/README.html
? projects/PDBParser/1SDK.pdb
? projects/PDBParser/1CDLA.pdb
? projects/PDBParser/COPYING
? projects/PDBParser/PDBParser.py
? projects/PDBParser/README
! projects/PDBParser
Aïe, en fait il faut d'abord que ce dossier soit considéré comme une copie locale donc supprimons son contenu et récupérons ce que nous venons de placer sur le dépôt :
$ rm projects/PDBParser/* $ svn checkout file:///home/david/work/svn/repository/PDBParser/trunk projects/PDBParser
A projects/PDBParser/README.html
A projects/PDBParser/1SDK.pdb
A projects/PDBParser/1CDLA.pdb
A projects/PDBParser/COPYING
A projects/PDBParser/PDBParser.py
A projects/PDBParser/README
Révision 1 extraite.
Ok, ça a marché, j'ai maintenant bien une copie locale de ce qui se trouve dans mon dépôt. Je peux commencer à travailler.
Ah non, j'ai dit que le README.html était généré via README donc inutile de le stocker dans le dépôt :
$ svn propedit svn:ignore projects/PDBParser/
Préciser *.html dans le fichier qui s'ouvre et le message suivant confirme sa prise en compte :
Nouvelle valeur définie pour la propriété 'svn:ignore' sur 'projects/PDBParser'
On enchaîne avec sa suppression :
$ svn remove -m "Suppression de README.html car il est généré automatiquement" projects/PDBParser/README.html
svn: Opération locale sans propagation (commit), pas de message
$ svn commit -m "Mise à jour de la suppression de README.html" projects/PDBParser/
Envoi projects/PDBParser
Révision 2 propagée.
Mise à jour et release
Maintenant que l'on a une copie locale fonctionnelle, passons à la modification du code. Prennez de bonnes habitudes en commençant par :
$ svn update projects/PDBParser
histoire d'être sûr d'avoir la dernière version du dépôt (dans notre cas c'est inutile mais si vous travaillez à plusieurs c'est primordial !).
Ok, je vais maintenant ajouter à la documentation une ligne indiquant la façon dont celle-ci est générée. Vous pouvez vérifier ce qui a été modifié via :
$ svn diff projects/PDBParser
Le retour dépend de vos modifications, c'est en général assez verbeux, si vous souhaitez juste connaître les fichiers ayant été modifiés :
$ svn status projects/PDBParser
M projects/PDBParser/README.html
M projects/PDBParser/README
Le fichier README.html a aussi été modifié mais il ne devrait pas être mis à jour dans le dépôt puisqu'il est normalement ignoré. Allons-y pour le commit du code ajouté :
$ svn commit -m "Ajout de la méthode de génération de la doc" projects/PDBParser/
Envoi projects/PDBParser/README
Envoi projects/PDBParser/README.html
Transmission des données ..
Révision 3 propagée.
Manifestement la propriété ignore a été ignorée... étrange, bon soit passons à la suite, je suis sûr qu'un gentil gourou se manifestera en commentaires ;-).
Vous pouvez à tout moment vérifier ce qu'il s'est passé sur votre projet grâce à :
$ svn log projects/PDBParser
Ok, j'ai une nouvelle version et j'ai décidé de faire une release de mon script. Il va pour cela falloir créer une branche de livraison et comme j'en suis à la version 3 on va l'appeler branche-livraison-3.1 et la placer dans repository/branches (on commence par créer les répertoires en question) :
$ svn mkdir -m "Création des branches" file:///home/david/work/svn/repository/PDBParser/branches $ svn mkdir -m "Création de la branche de livraison 3.1" file:///home/david/work/svn/repository/PDBParser/branches/branche-livraison-3.1 $ svn copy -m "Branche de livraison 3.1 créée après correction du README" file:///home/david/work/svn/repository/PDBParser/trunk file:///home/david/work/svn/repository/PDBParser/branches/branche-livraison-3.1
Différence entre les branches et les livraisons ?
C'est assez simple, une branche est créée pour pouvoir être modifiée en cas de bug dans la version de la branche. En revanche, un tag de livraison est placé lorsque l'on veut connaître l'état du code à un instant t donné. Ainsi la branche 3.1 va être dans un premier temps taguée 3.1 puis s'il y a correction d'un bug mineur, pouvoir ensuite être taguée par exemple 3.1.1 et ainsi de suite.
Une fois la branche crée, il suffit de la taguer pour obtenir une livraison. On crée pour cela le répertoire de repository/tags, puis la marque de livraison que l'on appelera livraison-3.1 :
$ svn mkdir -m "Création des tags" file:///home/david/work/svn/repository/PDBParser/tags $ svn copy -m "Livraison 3.1 créée après correction du README" file:///home/david/work/svn/repository/PDBParser/branches/branche-livraison-3.1 file:///home/david/work/svn/repository/PDBParser/tags/livraison-3.1
Il suffit ensuite de récupérer cette copie où l'on veut (créer le dossier avant) pour créer l'archive :
$ svn checkout file:///home/david/work/svn/repository/PDBParser/tags/livraison-3.1/trunk current/PDBParser-3.1
Et voila, plus qu'à compresser tout ça (sans les répertoires cachés ça fait plus pro).
Bon après je pourrais écrire des pages et des pages sur comment corriger un bug dans une branche particulière, switcher entre vos différentes versions, etc... mais tout a déjà été résumé dans un excellent bouquin :-). Le prochain livre commenté sera très certainement Zope, troisième édition mais c'est un pavé de 800 pages donc ça prend du temps (surtout qu'il est plutôt dense !). D'ici là de nouveaux tutoriaux pour le framework web Django devraient arriver.
Export et sauvegardes
Je viens de me rendre compte qu'il manquait une chose essentielle : l'export du dépôt pour effectuer une sauvegarde ! Avec Subversion, les propagations sont atomiques, les modifications sont soit complètement propagées, soit complètement annulées pour assurer la cohérence du système au même titre qu'une base de données. Mais attention justement, il ne faut pas faire une simple sauvegarde du dossier contenant le dépôt mais un dump du dépôt pour sauvegarder des données cohérentes même en cas de mise à jour par un autre utilisateur au même instant.
Une sauvegarde complète s'effectue donc simplement :
$ svnadmin dump work/svn/repository/ > svn_repos.20060707
* Révision 0 déchargée.
* Révision 1 déchargée.
* Révision 2 déchargée.
* Révision 3 déchargée.
* Révision 4 déchargée.
* Révision 5 déchargée.
* Révision 6 déchargée.
* Révision 7 déchargée.
* Révision 8 déchargée.
Il est préférable pour des sauvegardes quotidiennes si vous avez un dépôt conséquent de faire des sauvegardes incrémentales (option --incremental de svnadmin dump) pour ne pas tout sauver à chaque fois.
En cas de problème, il suffit de créer un nouveau dépôt et de recharger vos données :
$ svnadmin create /home/david/work/svn/repository2/ $ svnadmin load /home/david/work/svn/repository2/repository2 < svn_repos.20060707
Et toutes les transactions sont effectuées dans votre nouveau dépôt. N'oubliez jamais qu'on regrette de ne pas faire de sauvegarde que lorsqu'on perd ses données... un petit script automatique prend une heure à trouver/adapter/mettre en place mais peut sauver des heures et des heures de développement, et ça n'arrive malheureusement pas qu'aux autres ! Au même titre que le célèbre "No test, no commit", je serais tenté d'écrire "No backup, no admin".
Commentaires
S.F. le 06/07/2006 :
Ça peut paraître assez cruel, mais ... quel intérêt pour un usage personnel ? git, mercurial ou même bazaar-ng, des scm décentralisés, me semblent plus adaptés.
gigigan le 06/07/2006 :
je suis utilisateur de CVS pour phplister et subversion m'intéresse,
je suis impatient de lire la suite de l'article.
vdemeester le 06/07/2006 :
Ah mon dieux, david a les même lectures que moi !!!
Je confirme, livre petit en taille mais très complet en contenu :D
David, biologeek le 07/07/2006 :
@S.F. : je ne connaissais pas ces solutions mais quel intérêt par rapport à Subversion ? (j'ai rapidement consulté leurs sites sans trouver de raison vraiment transcendante). L'intérêt que je trouve à Subversion c'est que je pourrait tôt ou tard mettre un accès http ou ssh à mon dépôt si je souhaite rendre des projets publics. Voire même interfacer tout ça avec Trac si je veux un gestion des tiquets. Et puis ça me permet de me familiariser avec svn, ce qui me semble plus utile pour la suite.
PiTiLeZarD le 07/07/2006 :
L'intérêt d'un versionning system, c'est surtout le backup incrémental ! Quand tu code ou quand tu fais des docs ... A chaque mise à jour tu as la possibilité de revenir en arrière !
Tu proposes alors à mon avis, ce qu'il manque c'est la création d'un repository a partir de rien et en deamon avec utilisateur qui va bien ;) J'ai fais un truc du genre au boulot, il faudrait que je le couche sur l'écran (on peut plus dire sur papier maintenant ...)
En tout cas c'est intéressant ;)
Nicolas Steinmetz le 07/07/2006 :
Merci pour avoir signalé l'existence de mon tutoriel sur subversion :-)
David, biologeek le 07/07/2006 :
@PiTiLeZarD : s/que je le couche sur l'écran/que je le blogue restons sérieux, on est dans le web2.0 ou bien ? :p
@Nicolas : aucun soucis, c'est la suite naturelle de ce tutoriel.
Nicolas Steinmetz le 07/07/2006 :
Effectivement, ton billet est plus complet car mes projets de dev ne m'ont pas encore amené à avoir besoin de branches et tags... :-/
Un jour, j'y arriverais ;-)
S.F. le 08/07/2006 :
L'intérêt de ces systèmes est qu'il est décentralisé et donc ne dépend pas d'un serveur. Ça veut dire que tu n'as pas de serveur à installer, que tu peux bosser sans connexion internet (vachement pratique pour coder dans le train, git diff et git commit sont 100% offline), et tu peux toujours les publier sur le net, comme le font entre autre cairo et dbus, et comme je vais le faire avec git pour mathusalem. Je ne sais pas s'il y a un équivalent à trac pour ces systèmes cependant (je ne m'y suis pas intéressé). Plusieurs contributeurs peuvent avoir leur propre dépôt local, et ensuite merger leurs modifications en récupérant le contenu des dépôts publics des autres contributeurs, en s'envoyant des patches, ou même sur un serveur central (c'est possible, en tout cas avec git)
Ensuite, mercurial et bazaar sont écrits en python ;-)
David, biologeek le 08/07/2006 :
@Nicolas : non avant de le compléter je pensais que le mien était une introduction au tiens qui traite de Trac, bon maintenant on va dire qu'ils sont complémentaires :)
@S.F. : intéressant, pas dans la cas précis où c'est juste pour une personne (donc peu de risque d'être offline de sa propre machine) mais pour certains projets et surtout certains développeurs ça peut être bien. Parce que si j'ai bien compris le principal intérêt c'est de pouvoir coder offline ?
Bruno Michel le 08/07/2006 :
@David : tu pars du principe qu'une personne n'a qu'une seule machine, mais ce n'est pas le cas de tout le monde. J'ai, par exemple, un ordinateur fixe et un ordinateur portable. Je n'ai pas toujours accès à mon fixe depuis mon ordinateur portable. Et inversement, mon ordinateur portable n'est que rarement allumé quand je suis sur mon ordinateur fixe. Par contre, avec un seule machine, utiliser svn ou un scm décentralisé revient au même...
Sinon, pour Trac, il est possible de l'interfacer avec d'autres scm. Voir par là pour plus d'infos : projects.edgewall.com/tra...
didine le 13/07/2006 :
Je voudrais installer SVN (sur Dapper biensûr) pour gérer le développement d'une application.
Comment pourrais-je faire (si SVN le permet) pour gérer les fichiers de DEV et ceux de PROD ?
Par exemple un serveur de développement (mes développeurs pourront updater et commiter leurs versions locales sur ce serveur) avec écriture seule sur le serveur de production depuis lequel mes clients (serveurs sur lesquels mon application tourne) pourront updater leurs versions (lecture seule).
Merci :)
NiCoS le 20/07/2006 :
"Comment pourrais-je faire (si SVN le permet) pour gérer les fichiers de DEV et ceux de PROD ?"
Via les branches/tags ?
La version de dev = version courante du dépôt SVN
Version de prod = une branche du dépôt SVN
Pour les machines de prod, elles font un checkout ou un export à partir de la branche qui les intéresse...
David, biologeek le 20/07/2006 :
Oups, j'avais oublié ce commentaire, merci NiCoS pour cette réponse pertinente.
@Bruno Michel:
> J'ai, par exemple, un ordinateur fixe et un ordinateur portable.
Oui, c'est mon cas aussi, je vais regarder de plus près les solutions proposées.
Loïc d'Anterroches le 09/08/2006 :
L'exclusion d'un fichier avec le propedit ne fonctionne que si le fichier n'est pas déjà dans le dépôt. Comme le .html est déjà dedans, il sera toujours inclu. Il faut d'abord le supprimer et le recréer sans l'inclure pour qu'ensuite il ne soit pas pris en compte.
David, biologeek le 09/08/2006 :
Merci pour cette précision Loïc, au plaisir de te lire :-).
L@u le 14/11/2006 :
Salut,
Personellement, j'avais fait une petite étude des produits scm opensource ... et il y en a pas mal.
Finalement, j'ai choisi SVN car à l'époque (6 mois), c'était le produit le plus abouti, le plus stable, le plus diffusé, et le mieux intégré (plugin dans Eclipse, etc ...).
Cependant, c'est loin d'être mon favori et j'adorerai bazaar avoir une plus grosse diffusion et plus de plugin et d'outil pour une meilleure IHM.
Dans l'attente, SVN est pas mal (perso je n'ai pas besoin de commit sans connexion au serveur), et j'arrive à faire ce que je veux assez facilement.
habib le 12/04/2007 :
Bonjour,
je suis étudiant en rédaction technique, et je voulais savoir si on peut contourner un peu l'usage de svn pour une utilisation ds la rédaction technique, c à d quand plusieurs rédacteurs travail sur la meme doc notament en FM (framemaker) ou .odt , est ce qu'il ya possibilité de controler les versions...
merci d'avance
David, biologeek le 12/04/2007 :
Bonjour,
Il me semble que les .odt sont des simples archives (.tar ou .tar.gz je sais plus) donc ça doit être possible en réarchivant/désarchivant à chaque commit (avec des hooks particuliers pour automatiser). Enfin ça reste pas évident à mon avis...
Si vous pouvez travailler sur du texte brut pour ensuite le mettre en forme c'est beaucoup plus simple.
La Case de l'Onc' Tom le 24/04/2007 :
Livres : Javascript, Subversion, CSS
Je vous l’annonce, depuis janvier 2007 je suis boulimique. Boulimique mais d’informations, de connaissances et de savoir. S’il y a bien un univers qui ne pardonne pas à ceux qui se contentent des acquis, c’est bien celui dR...
BastNic's Blog le 14/06/2007 :
Utilisation de bazaar par l'exemple, mise en place d'un répertoire partagé de travail sur Code Igniter
Bazaar est un gestionnaire de version, un VCS en anglais : Version Control System. Si jamais vous ignorez ce qu'est un gestionnaire de version je ne peux que vous conseiller de vous renseigner sur ce qu'est un gestionnaire de version (la définition
Ciccio le 09/02/2009 :
Ici (http://www.sourceslist.netsons.org), vous pouvez trouver un site entièrement consacré aux sources.list pour Ubuntu, Debian, Linux Mint, OpenSuse. Chaque sources.list contient plus de 180 dépôts. En outre il y a une version textual e une version debian qui est mis à jour automatiquement chaque fois que vous ajourez votre ditro. (sudo apt-get dist-upgrade)
Alex le 11/04/2009 :
L'url è changé: http://www.sourceslist.eu