This text is a work in progress—highly subject to change—and may not accurately describe any released version of the Apache™ Subversion® software. Bookmarking or otherwise referring others to this page is probably not such a smart idea. Please visit http://www.svnbook.com/ for stable versions of this book.

Cycle de travail de base

Subversion dispose de nombreuses fonctionnalités, d'options, d'avertissements et de garde-fous. Mais dans une utilisation au jour le jour, vous n'utilisez qu'un petit nombre d'entre eux. Dans cette section, nous passons en revue l'utilisation quotidienne de Subversion.

Le cycle de travail typique ressemble à ceci :

  1. Mettre à jour votre copie de travail, par l'utilisation de la commande svn update.

  2. Faire des changements. Les changements les plus courants seront des modifications du contenu des fichiers existants. Parfois, vous aurez besoin d'ajouter, supprimer, copier ou déplacer des fichiers et des dossiers ; les commandes svn add, svn delete, svn copy et svn move prennent en charge ces modifications structurelles de la copie de travail.

  3. Examiner les changements effectués. Les commandes svn status et svn diff sont là pour passer en revue les modifications que vous avez apportées à votre copie de travail.

  4. Annuler des changements. Personne n'est parfait, aussi lorsque vous passez en revue vos modifications, vous pouvez constater des erreurs. Parfois, le plus simple est de repartir de zéro. La commande svn revert rétablit un fichier ou un dossier dans son état initial.

  5. Résoudre les conflits (fusionner les modifications). Dans le temps qu'il vous faut pour réaliser et passer en revue vos modifications, d'autres utilisateurs effectuent et publient peut-être des modifications également. Vous voulez sûrement intégrer leurs changements dans votre copie de travail pour éviter qu'ils ne deviennent « périmés » quand vous voudrez les publier. Une fois encore, la commande svn update prend cette opération en charge. Si des conflits apparaissent sur votre copie locale, vous devrez les résoudre à l'aide de la commande svn resolve.

  6. Propager les changements. La commande svn commit transmet vos modifications au dépôt et, si elles sont acceptées, créeront une nouvelle version de toutes les choses que vous avez modifiées. Maintenant, les autres aussi peuvent voir votre travail !

Mettre à jour votre copie de travail

Si vous travaillez sur un projet donné qui est modifié par des copies de travail multiples, vous voudrez mettre à jour votre copie locale pour recevoir toutes les modifications qui ont pu être faites par les autres copies de travail depuis votre dernière mise à jour. Ce peut être des modifications que les autres membres de l'équipe de projet ont faites, ou simplement des modifications que vous avez faites vous-même sur un autre ordinateur. Afin de protéger vos données, Subversion ne vous autorise pas à publier des changements sur des fichiers ou des dossiers qui ne sont pas à jour. Il est donc toujours mieux d'avoir les dernières versions de tous les fichiers et dossiers des projets sur lesquels vous travaillez avant d'apporter vous-même des modifications.

Utilisez svn update pour synchroniser votre copie de travail avec la dernière version présente dans le dépôt :

$ svn update
Mise à jour de '.' :
U  truc.c
U  machin.c
Actualisé à la révision 2.
$

Dans cet exemple, il se trouve que quelqu'un a apporté des modifications à truc.c ainsi qu'à machin.c depuis votre dernière mise à jour et Subversion vient de répercuter ces modifications dans votre copie de travail.

Lorsque le serveur envoie des modifications vers votre copie de travail via svn update, un code, sous forme de lettre, est affiché à côté de chaque élément pour vous permettre de savoir quelles actions Subversion a effectuées pour mettre votre copie de travail à jour. Pour en savoir plus sur le sens de ces lettres, exécutez svn help update ou reportez-vous à svn update (up) dans Guide de référence de svn : le client texte interactif.

Apporter des modifications à votre copie de travail

Vous pouvez à présent vous mettre au travail et apporter des modifications à votre copie de travail. Vous pouvez effectuer deux types de modifications : les modifications de fichiers et les modifications de dossiers. Vous n'avez pas à prévenir Subversion que vous voulez modifier un fichier ; faites vos modifications avec un éditeur de texte, un traitement de texte, un logiciel de dessin ou n'importe quel autre outil que vous utilisez d'habitude. Subversion détecte automatiquement quels fichiers ont été modifiés et, en plus, il traite les fichiers binaires tout aussi facilement et aussi efficacement que les fichiers textes. Les modifications dans l'arborescence sont différentes ; cela comprend l'ajout et la suppression de fichiers, le renommage de fichiers ou de dossier ainsi que la copie ou le déplacement de fichiers ou dossiers vers un nouvel emplacement. Pour les modifications d'arborescence, les opérations de Subversion consistent à « marquer » la suppression, l'ajout, la copie ou le déplacement des fichiers et dossiers. Ces modifications prennent effet immédiatement sur votre copie de travail mais aucun ajout ou suppression n'interviendra sur le dépôt avant que vous ne les propagiez.

Voici un aperçu des cinq sous-commandes Subversion les plus utilisées pour faire des modifications sur l'arborescence :

svn add TRUC

Marque le fichier, le dossier ou le lien symbolique TRUC pour ajout. Lors de la prochaine propagation, TRUC devient un fils de son dossier parent. Notez que si TRUC est un dossier, tout ce qui se trouve à l'intérieur de TRUC est marqué pour ajout. Si vous ne désirez ajouter que TRUC lui-même, passez l'option --depth empty.

svn delete TRUC

Marque le fichier, le dossier ou le lien symbolique TRUC pour suppression. Si TRUC est un fichier ou un lien, il est immédiatement supprimé de votre copie de travail. Si TRUC est un dossier, il n'est pas supprimé, mais Subversion le marque pour suppression. Quand vous propagez vos modifications, TRUC est complètement supprimé de votre copie de travail et du dépôt. [6]

svn copy TRUC MACHIN

Crée un nouvel élément MACHIN par duplication de TRUC et marque automatiquement MACHIN pour ajout. Lorsque MACHIN est ajouté au dépôt, lors de la prochaine propagation, son historique est enregistré (comme ayant été créé à partir de TRUC). svn copy ne crée pas de dossiers intermédiaires, à moins que vous ne lui passiez l'option --parents.

svn move TRUC MACHIN

Cette commande équivaut exactement à svn copy TRUC MACHIN; svn delete MACHIN. C'est-à-dire que MACHIN est marqué pour ajout en tant que copie de TRUC et que TRUC est marqué pour suppression. svn move ne crée pas de dossiers intermédiaires, à moins que vous ne lui passiez l'option --parents.

svn mkdir TRUC

Cette commande équivaut exactement à mkdir TRUC; svn add TRUC. C'est-à-dire qu'un nouveau dossier nommé TRUC est créé et marqué pour ajout.

Examiner les changements apportés

Une fois vos modifications apportées, vous devez les intégrer au dépôt. Avant de le faire, il est souvent utile de jeter un coup d'œil sur ces modifications pour savoir exactement ce que vous avez changé. En examinant les modifications avant de les intégrer au dépôt, vous pouvez rédiger un commentaire de propagation, c'est-à-dire une description à l'attention des utilisateurs des changements propagés, ce commentaire étant conservé avec les données dans le dépôt. Éventuellement, vous verrez que vous avez modifié un fichier par inadvertance et cela vous donne une chance de revenir sur ces modifications avant de les propager au dépôt. En outre, c'est une bonne occasion de passer en revue et d'examiner les modifications avant de les publier. Vous pouvez obtenir une vue d'ensemble des modifications que vous avez faites en utilisant la commande svn status et voir le détail de ces changements en utilisant svn diff.

Avoir une vue d'ensemble des changements effectués

Pour avoir une vue d'ensemble des changements que vous avez effectués, utilisez la commande svn status. C'est certainement la commande Subversion que vous utiliserez le plus.

[Astuce] Astuce

Parce que l'affichage produit par la commande cvs status était tellement verbeux et parce que la commande cvs update ne faisait pas qu'une mise à jour mais affichait également l'état des changements effectués localement, la plupart des utilisateurs de CVS ont appris à utiliser cvs update pour propager leurs modifications. Dans Subversion, les opérations de mise-à-jour et d'examen des changements sont complètement séparées. Reportez-vous à la section intitulée « Distinction entre les commandes status et update » pour plus de détails.

Si vous lancez svn status sans argument à la racine de votre copie de travail, Subversion détecte toutes les modifications effectuées sur les fichiers et sur l'arborescence.

$ svn status
?       gribouillage.c
A       bazar/pognon
A       bazar/pognon/nouveau.h
D       bazar/vieux.c
M       machin.c

Dans le format d'affichage par défaut, svn status affiche sept colonnes de caractères, suivis par plusieurs espaces, suivis par un nom de fichier ou de dossier. La première colonne indique le statut du fichier ou du dossier et/ou son contenu. Les codes les plus utilisés sont :

? élément

Le fichier, dossier ou lien symbolique élément n'est pas suivi en versions.

A élément

Le fichier, dossier ou lien symbolique élément est marqué pour ajout au dépôt.

C élément

Le fichier élément est dans un état de conflit. C'est-à-dire que des modifications ont eu lieu dans le dépôt depuis votre dernière mise à jour et ces modifications interfèrent avec les modifications que vous avez effectuées sur votre copie de travail (et la mise à jour n'a pas résolu ce conflit). Vous devez résoudre ce conflit avant de propager vos changements vers le dépôt.

D élément

Le fichier, dossier ou lien symbolique élément est marqué pour suppression (Deletion en anglais).

M élément

Le contenu du fichier élément a été modifié.

Si vous spécifiez un chemin à svn status, vous obtenez uniquement les informations relatives à ce chemin :

$ svn status bazar/poisson.c
D      bazar/poisson.c

svn status possède aussi une option --verbose (-v) pour la rendre plus verbeuse : elle affiche alors le statut de tous les éléments de votre copie de travail, même ceux qui n'ont pas subi de modification :

 
$ svn status -v
M               44        23    sally     LISEZMOI
                44        30    sally     INSTALL
M               44        20    harry     machin.c
                44        18    ira       bazar
                44        35    harry     bazar/truite.c
D               44        19    ira       bazar/poisson.c
                44        21    sally     bazar/divers
A                0         ?     ?        bazar/divers/bitoniau.h
                44        36    harry     bazar/divers/tartempion.c

C'est la « version longue » de l'affichage de svn status. Les lettres de la première colonne ont la même signification que précédemment, mais la deuxième colonne indique le numéro de révision de travail de l'élément. Les troisième et quatrième colonnes indiquent le numéro de la révision dans laquelle a eu lieu le changement le plus récent et qui l'a effectué.

Aucune des commandes citées ci-dessus n'induit de connexion vers le dépôt : elles comparent les métadonnées de la zone administrative et les horodatages avec la copie de travail. Parfois, il peut être utile de voir quels éléments de la copie de travail ont été modifiés dans le dépôt depuis la dernière mise à jour de la copie de travail. À cette fin, svn status propose l'option --show-updates (-u) qui effectue une connexion au dépôt et ajoute les informations sur les éléments périmés :

$ svn status -u -v
M      *        44        23    sally     LISEZMOI
M               44        20    harry     machin.c
       *        44        35    harry     bazar/truite.c
D               44        19    ira       bazar/poisson.c
A                0         ?     ?        bazar/divers/bitoniau.h
État par rapport à la révision   46

Notez les deux astérisques : si vous lanciez la commande svn update, vous recevriez les changements relatifs à LISEZMOI et truite.c. Cela vous procure des informations particulièrement intéressantes, puisque l'un des éléments a fait l'objet de modifications de votre part (le fichier LISEZMOI) ; vous devez faire une mise à jour et récupérer les changements effectués sur LISEZMOI avant de propager les vôtres, sinon le dépôt rejettera votre propagation en la considérant comme périmée (le sujet est approfondi plus tard).

svn status peut afficher beaucoup plus d'informations sur les fichiers et dossiers de votre copie de travail que ce que nous venons de voir ici. Pour obtenir une description exhaustive de svn status et de ses modes d'affichage, lancez svn help status ou reportez-vous à svn status (stat, st) dans Guide de référence de svn : le client texte interactif.

Voir en détail les modifications que vous avez effectuées localement

La commande svn diff offre une autre façon d'examiner vos changements. En lançant la commande svn diff dans le dossier racine de votre copie de travail et sans argument, Subversion affiche les changements que vous avez apportés dans les fichiers lisibles par les humains de votre copie de travail. Il affiche ces changements au format diff unifié, un format qui décrit les changements par des « morceaux » (hunks ou snippets en anglais) du contenu des fichiers, où chaque ligne de texte est préfixée par un code sur un caractère : une espace signifie que la ligne n'a pas été modifiée ; un signe moins (-) signifie que la ligne a été supprimée du fichier ; et un signe plus (+) signifie que la ligne a été ajoutée au fichier. Dans le contexte de svn diff, les préfixes respectivement + et - montrent le contenu des lignes respectivement avant et après vos modifications.

Voici un exemple :

$ svn diff
Index: truc.c
===================================================================
--- machin.c	(révision 3)
+++ machin.c	(copie de travail)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>
 int main(void) {
-  printf("Soixante-quatre tranches de fromage...\n");
+  printf("Soixante-cinq tranches de fromage...\n");
 return 0;
 }
Index: LISEZMOI
===================================================================
--- LISEZMOI	(révision 3)
+++ LISEZMOI	(copie de travail)
@@ -193,3 +193,4 @@
+Pense-bête : passer au pressing.
Index: bazar/poisson.c
===================================================================
--- bazar/poisson.c	(révision 1)
+++ bazar/poisson.c	(copie de travail)
-Bienvenue dans le fichier 'poisson'.
-Plus d'informations seront disponibles prochainement.
Index: bazar/divers/machin.h
==================================================================
--- bazar/divers/bitoniau.h	(révision 8)
+++ bazar/divers/bitoniau.h	(copie de travail)
+Voici un nouveau fichier pour
+écrire sur les petites choses.

La commande svn diff produit ces lignes en comparant vos fichiers de travail aux copies « originales » en cache dans la zone administrative. Les fichiers marqués pour ajout sont affichés comme toute section de texte ajoutée, et les fichiers marqués pour suppression sont affichés comme toute section de texte supprimée. L'affichage de svn diff est compatible avec le programme patch — et encore davantage avec l'introduction de la commande svn patch dans Subversion 1.7. Les commandes patch lisent et appliquent des correctifs (patches en anglais), c'est-à-dire des fichiers qui décrivent les modifications appliquées à un ou plusieurs fichiers. Ainsi, vous pouvez partager les modifications que vous avez faites sur votre copie de travail avec quelqu'un d'autre sans propager ces modifications, mais seulement en créant un fichier correctif obtenu par la redirection de l'affichage de svn diff.

$ svn diff > fichier-correctif
$

Subversion utilise son propre moteur de calcul de différences, qui produit par défaut des résultats au format diff unifié. Si vous désirez obtenir les différences dans un autre format, spécifiez un programme de comparaison externe en utilisant l'option --diff-cmd et en fournissant les paramètres que vous voulez à l'aide de l'option --extensions (-x). Par exemple, pour obtenir les différences entre votre version locale du fichier et l'original de truc.c au format « contexte » et en ignorant la casse des caractères, vous pouvez lancer la commande suivante :

$ svn diff --diff-cmd /usr/bin/diff -x "-i" truc.c
…
$

Annuler des changements sur la copie de travail

Supposons qu'en examinant la sortie de svn diff, vous vous rendiez compte que tous les changements effectués sur un fichier donné sont erronés. Peut-être auriez-vous dû laisser le fichier tel quel, ou bien peut-être qu'il serait plus facile de reprendre les changements depuis le début. Vous pourriez éditer à nouveau le fichier et défaire tous les changements. Vous pourriez essayer de trouver une copie du fichier tel qu'il était avant les changements et copier son contenu à la place de votre fichier modifié. Vous pourriez essayer d'appliquer les changements à l'envers en utilisant svn patch - --reverse-diff ou depuis le système d'exploitation avec patch -R. Et il existe probablement encore d'autres méthodes.

Heureusement, avec Subversion annuler son travail et repartir de zéro ne nécessite pas autant d'acrobaties. Vous avez juste à utiliser la commande svn revert:

$ svn status LISEZMOI
M       LISEZMOI
$ svn revert LISEZMOI
'LISEZMOI' réinitialisé
$

Dans cet exemple, Subversion ramène le fichier dans son état d'avant les modifications en le remplaçant par la copie de l'original stockée dans la zone d'administration. Mais notez aussi que svn revert peut annuler n'importe quelle opération. Par exemple, vous pouvez décider que, après tout, vous ne voulez pas ajouter tel fichier :

$ svn status truc
?      truc

$ svn add truc
A         truc

$ svn revert truc
'truc' réinitialisé

$ svn status truc
?      truc
$

Ou, si vous avez enlevé un fichier du suivi de versions par erreur :

$ svn status LISEZMOI

$ svn delete LISEZMOI
D       LISEZMOI
$ svn revert LISEZMOI
'LISEZMOI' réinitialisé
$ svn status LISEZMOI

$

La commande svn revert est le parachute des gens imparfaits. Elle peut vous faire gagner un temps et une énergie considérables que vous auriez dépensé autrement à faire des corrections manuelles, voire à récupérer une copie de travail vierge juste pour retrouver un environnement de travail propre.

Résoudre les conflits

Nous avons déjà vu que svn status -u est capable de prévoir les conflits, mais il reste à savoir gérer ces conflits. Des conflits peuvent survenir à chaque fois que vous voulez fusionner ou intégrer (dans le sens le plus général) des modifications en provenance du dépôt dans votre copie de travail. Vous savez désormais que la commande svn update génère ce type de situation ; la fonction essentielle de cette commande est de mettre à jour votre copie de travail en y intégrant toutes les modifications effectuées depuis votre dernière mise à jour. Comment Subversion vous rend-il compte de ces conflits et comment pouvez-vous les gérer ?

Supposons que vous lanciez svn update et que le résultat suivant apparaisse :

$ svn update
Mise à jour de '.' :
U  INSTALL
G  LISEZMOI
Conflit découvert dans 'machin.c'.
Sélectionner : (p) report, (df) diff complet, (e) édite, (m) fusion,
        (mc) my side of conflict, (tc) their side of conflict,
        (s) voir toutes les options:

Les codes U (qui veut dire « mis à jour », updated en anglais) et G (qui veut dire fusionné, merGed en anglais) ne doivent pas vous inquiéter, les fichiers correspondants ayant absorbé sans problème les modifications venant du dépôt. Les fichiers notés U ne contenaient aucun changement local mais ont été mis à jour à partir de changements présents dans le dépôt. Le fichier marqué G avait subi des changements localement, mais les changements en provenance du dépôt ont pu être appliqués sans affecter les changements locaux.

Ce sont les quelques lignes suivantes qui sont intéressantes. D'abord, Subversion vous avertit que sa tentative pour fusionner les modifications en provenance du serveur dans le fichier local machin.c, il a détecté que certains changements interfèrent avec les vôtres quelqu'un a peut-être modifié la même ligne que vous. Quelle qu'en soit la raison, Subversion marque immédiatement le fichier comme étant dans un état de conflit. Ensuite, il vous demande ce que vous voulez faire pour résoudre ce conflit, vous proposant de choisir une action de manière interactive. Les options les plus utilisées sont affichées, mais vous pouvez voir toutes les options possibles en tapant s :

…
Select: (p) postpone, (df) show diff, (e) edit file, (m) fusion,
        (mc) my side of conflict, (tc) their side of conflict,
        (s) show all options: s

  (e)  - change merged file in an editor  [edit]
  (df) - show all changes made to merged file
  (r)  - accept merged version of file

  (dc) - show all conflicts (ignoring merged version)
  (mc) - accept my version for all conflicts (same)  [mine-conflict]
  (tc) - accept their version for all conflicts (same)  [theirs-conflict]

  (mf) - accept my version of entire file (even non-conflicts)  [mine-full]
  (tf) - accept their version of entire file (same)  [theirs-full]

  (m)  - use internal merge tool to resolve conflict
  (l)  - launch external tool to resolve conflict  [launch]
  (p)  - mark the conflict to be resolved later  [postpone]
  (q)  - postpone all remaining conflicts
  (s)  - show this list (also 'h', '?')
Words in square brackets are the corresponding --accept option arguments.

Select: (p) postpone, (df) show diff, (e) edit file, (m) fusion,
        (mc) my side of conflict, (tc) their side of conflict,
        (s) show all options:

Regardons brièvement ce que recèle chaque option avant de les détailler :

(e) edit

Ouvrir le fichier en conflit avec votre éditeur de texte favori, qui est spécifié dans la variable d'environnement EDITOR.

(df) diff-full

afficher les différences entre la révision de base et le fichier en conflit au format diff unifié.

(r) resolved

Après édition du fichier, indiquer à Subversion que vous avez résolu les conflits à l'intérieur du fichier et qu'il doit accepter son contenu actuel ; en bref, vous avez « résolu » le conflit.

(dc) display-conflict

Afficher toutes les parties du fichier en conflit, en ignorant les modifications qui ont réussi à être fusionnées.

(mc) mine-conflict

ignorer les changements envoyés par le serveur qui entrent en conflit avec vos modifications locales pour le fichier concerné. Cependant, accepter et fusionner toutes les parties qui n'engendrent pas de conflit.

(tc) theirs-conflict

Ignorer les modifications locales qui engendrent des conflits avec la version envoyée par le serveur pour le fichier concerné. Cependant, conserver toutes les parties qui n'engendrent pas de conflit pour ce fichier.

(mf) mine-full

Ignorer les changements envoyés par le serveur et utiliser uniquement votre version locale pour le fichier concerné.

(tf) theirs-full

Ignorer vos changements sur le fichier concerné et utiliser la version envoyée par le serveur.

(p) postpone

Laisser le fichier en état de conflit, conflit que vous devrez résoudre après la fin de la mise à jour.

(l) launch

Lancer un programme externe pour résoudre le conflit. Ceci nécessite un peu de préparation en amont.

(s) show all

Afficher la liste de toutes les commandes que vous pouvez utiliser dans la résolution interactive des conflits.

Nous allons maintenant passer en revue chaque commande, en les classant par fonctionnalité.

Voir les lignes en conflit de façon interactive

Avant de décider comment résoudre un conflit de manière interactive, il est probable que vous vouliez examiner le détail des lignes en conflit. Deux des commandes accessibles via l'invite interactive de gestion des conflits répondent à ce besoin. La première est la commande df (pour diff-full en anglais), qui affiche toutes les modifications locales du fichier ainsi que les zones en conflit :

…
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: df
--- .svn/text-base/sandwich.txt.svn-base      mar. 11 déc. 2007, 21:33:57
+++ .svn/tmp/tempfile.32.tmp     mar. 11 déc. 2007, 21:34:33
@@ -1 +1,5 @@
-Achète-moi un sandwich.
+<<<<<<< .mien
+Va chercher un hamburger.
+=======
+Apporte-moi un taco !
+>>>>>>> .r32
…

La première ligne du diff correspond à ce que contenait la copie de travail dans l'ancienne version (la révision BASE), la ligne suivante correspond à vos modifications et la dernière ligne contient les modifications reçues du serveur (la révision HEAD la plupart du temps).

La deuxième commande est similaire à la première mais dc(display conflict en anglais) affiche uniquement les zones en conflits, pas toutes les modifications apportées au fichier. En plus, cette commande utilise un format d'affichage légèrement différent qui permet de comparer facilement le contenu du fichier tel qu'il serait dans les trois états : original et non édité ; avec les modifications locales et les changements provenant du serveur qui génèrent des conflits ignorés ; uniquement les changements provenant du serveur et vos modifications locales qui génèrent des conflits ignorés.

Après avoir pris connaissance des informations fournies par ces commandes, vous être prêt à l'action suivante.

Résoudre les conflits en mode interactif

Il y a plusieurs façons de résoudre un conflit avec l'interface interactive : deux d'entre elles vous permettent de fusionner et d'adapter les modifications de manière interactive, les autres vous permettent simplement de choisir une version du fichier parmi celles proposées et de passer à la suite.

Si vous souhaitez choisir une combinaison de vos modifications locales, vous pouvez utiliser la commande « édite » (e) pour modifier manuellement dans un éditeur de texte (configuré en suivant les instructions données dans la section intitulée « Utilisation d'éditeurs externes ») le fichier avec des marqueurs indiquant les conflits. Après avoir édité le fichier et si vous êtes satisfait de vos changements, vous pouvez indiquer à Subversion que le fichier n'est plus en conflit en utilisant la commande « résolu » (r).

En dehors de quelques puristes d'Unix, l'édition manuelle de ce fichier avec votre éditeur préféré peut sembler quelque peu « bas de gamme » (voir la section intitulée « Résoudre les conflits à la main » pour une description détaillée), c'est pourquoi Subversion propose d'utiliser des outils graphiques plus évolués et spécialisés dans la fusion de documents (voir la section intitulée « Outils de fusion externes ») avec la commande « launch » (lancer en français), raccourci l).

Si vous décidez qu'il n'y a pas lieu d'effectuer de fusion et si choisir l'une ou l'autre des versions proposées du fichier vous convient, vous pouvez soit opter pour vos changements (c'est-à-dire « mien ») en utilisant la commande « mien complet » (mf) ou opter pour la version des autres collaborateurs en utilisant la commande « autre complet » (tf).

Enfin, il existe deux autres options qui offrent des compromis. Les commandes respectivement « mien-conflits » (mc) et « leur-conflits » (tc) demandent à Subversion de conserver respectivement vos modifications locales et les modifications en provenance du serveur pour tous les conflits rencontrés. Mais, au contraire de « mien complet » et « autre complet », ces commandes conservent à la fois vos modifications et les modifications en provenance du serveur dans les zones du fichier où il n'est pas détecté de conflit.

Remettre à plus tard la résolution d'un conflit

Le titre peut laisser penser à un paragraphe sur l'amélioration des relations conjugales, mais il s'agit bien toujours de Subversion, voyez plutôt. Si, lorsque vous effectuez une mise à jour, Subversion soulève un conflit que vous n'êtes pas prêt à résoudre, vous pouvez, fichier par fichier, taper p, pour remettre à plus tard la résolution du conflit. Si, lors de votre mise à jour, vous ne voulez résoudre aucun conflit, vous pouvez passer l'option --non-interactive à svn update et les fichiers en conflit seront automatiquement marqués C.

Le C indique un conflit, c'est-à-dire que les changements sur le serveur interfèrent avec les vôtres et vous devez donc choisir manuellement entre les différentes modifications après la fin de la procédure de mise à jour. Quand vous repoussez à plus tard la résolution d'un conflit, Subversion va accomplir trois actions qui vous aideront à repérer et à résoudre ce conflit :

  • Subversion affiche un C pendant la mise à jour et enregistre que le fichier est dans un état de conflit.

  • Si Subversion considère que le fichier peut être fusionné, il place dans le fichier des marqueurs de conflit (des chaînes de caractères spéciales qui dénotent les « contours » des conflits) pour mettre en exergue les zones de conflit (Subversion utilise la propriété svn:mime-type pour déterminer si un fichier peut subir une fusion contextuelle ligne par ligne ; voir la section intitulée « Type de contenu des fichiers » pour en apprendre davantage).

  • Pour chaque fichier en conflit, Subversion place trois fichiers supplémentaires non-suivis en versions dans votre copie de travail :

    nom_du_fichier.mine

    C'est votre fichier tel qu'il était dans votre copie de travail avant la mise à jour, c'est-à-dire sans les marqueurs de conflits. Ce fichier ne comporte que vos derniers changements (si Subversion considère que le fichier ne peut pas être fusionné, le fichier .mine n'est pas créé, car il serait identique à la version de travail).

    nom_du_fichier.rANCIENNE_REV

    C'est le fichier tel qu'il était à la révision BASE, avant la mise à jour de votre copie de travail. C'est donc le fichier que vous avez extrait avant de faire vos dernières modifications, ANCIENNE_REV désignant le numéro de révision de cette version de base.

    nom_du_fichier.rNOUVELLE_REV

    C'est le fichier que le client Subversion vient de recevoir du serveur via l'opération de mise à jour, où NOUVELLE_REV désigne le numéro de révision de la mise à jour demandée (HEAD, à moins d'avoir spécifié une autre révision).

Par exemple, Sally effectue un changement sur le fichier sandwich.txt mais elle ne propage pas immédiatement ses modifications. Pendant ce temps, Harry propage des changements sur ce même fichier. Sally met à jour sa copie de travail avant d'effectuer la propagation et un conflit apparaît, dont elle remet la résolution à plus tard :

$ svn update
Mise à jour de '.' :
Conflit découvert dans 'sandwich.txt'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: p
C  sandwich.txt
Actualisé à la révision 2.
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2

À partir de là, Subversion n'autorise pas Sally à propager le fichier sandwich.txt avant que les trois fichiers temporaires ne soient effacés :

$ svn commit -m "Quelques petits ajouts"
svn: Échec de la propagation (commit), détails :
svn: Arrêt de la propagation : '/home/sally/travail-svn/sandwich.txt'
                               demeure en conflit

Si vous avez remis à plus tard la résolution d'un conflit, vous devez le résoudre pour que Subversion vous autorise à propager vos changements. Vous pouvez le faire avec la commande svn resolve. Cette commande possède l'option --accept afin de spécifier votre manière de résoudre le conflit. Avant Subversion 1.8, la commande svn resolve exigeait de spécifier l'option. Dorénavant, Subversion vous autorise à ne pas la spécifier. Dans ce cas, Subversion passe en mode de résolution interactif tel que présenté dans la section précédente (voir la section intitulée « Résoudre les conflits en mode interactif »). Dans cette section, nous allons présenter l'utilisation de l'option --accept pour la résolution de conflits.

L'option --accept de la commande svn resolve demande à Subversion d'utiliser une des approches prédéfinies pour résoudre un conflit. Si vous choisissez la version du fichier que vous avez extraite avant de faire vos changements, utilisez l'argument --accept=base. Si vous préférez garder la version qui contient uniquement vos changements, utilisez l'argument --accept=mine-full. Vous pouvez aussi choisir la version la plus récente venant du serveur (et donc abandonner tous vos changements) en utilisant l'argument --accept=theirs-full. Il existe d'autres méthodes de résolution « pré-emballées ». Lisez --accept ACTION dans Guide de référence de svn : le client texte interactif pour en obtenir les détails.

Vous n'êtes pas limité à ces choix tout ou rien. Si vous comptez effectuer un mélange de vos modifications et des modifications rapatriées du serveur, fusionnez le fichier en conflit « à la main » (examinez et éditez les marqueurs de conflit dans le fichier) puis indiquez à Subversion de résoudre le conflit en gardant la version de travail dans son état actuel par la commande svn resolve avec l'argument --accept=working.

La commande svn resolve supprime les trois fichiers temporaires et retient la version du fichier que vous avez spécifié avec l'option --accept. À la fin d'exécution de la commande (en considérant bien évidemment que vous n'avez décidé de reporter la résolution du conflit), Subversion considère que le fichier n'est plus dans un état de conflit :

$ svn resolve --accept working sandwich.txt
Conflit sur 'sandwich.txt' résolu

Résoudre les conflits à la main

Résoudre les conflits à la main peut paraître quelque peu intimidant la première fois. Mais avec un peu de pratique, un enfant de cinq ans y arriverait.

Prenons un exemple. Par manque de communication entre Sally (votre collaboratrice) et vous-même, vous éditez en même temps le fichier sandwich.txt. Sally propage ses changements et, quand vous mettez à jour votre copie de travail, un conflit apparaît, que vous devez résoudre en éditant sandwich.txt. Jetons un œil à ce fichier :

$ cat sandwich.txt
Tranche de pain supérieure
Mayonnaise
Laitue
Tomate
Comté
<<<<<<< .mine
Saucisson
Mortadelle
Jambon
=======
Choucroute
Poulet rôti
>>>>>>> .r2
Moutarde
Tranche de pain inférieure

Les suites de caractères inférieur-à (<), égal(=) ou supérieur-à (>) sont des marqueurs de conflit, ils ne font pas partie des données elles-mêmes. Vous devrez en général vous assurer qu'elles ont disparu du fichier avant de propager vos modifications. Le texte entre les deux premiers marqueurs est constitué des modifications que vous avez apportées dans la zone de conflit :

<<<<<<< .mine
Saucisson
Mortadelle
Jambon
=======

Le texte entre le deuxième et le troisième marqueur est celui du fichier propagé par Sally :

=======
Choucroute
Poulet rôti
>>>>>>> .r2

Normalement, vous n'allez pas juste supprimer les marqueurs et les changements effectués par Sally (elle sera affreusement déçue quand on lui apportera un sandwich différent de ce qu'elle a commandé). Vous décrochez donc le téléphone, ou vous traversez le bureau, pour expliquer à Sally qu'on ne met pas de choucroute dans un sandwich. [7] Après vous être mis d'accord sur les changements à enregistrer, éditez votre fichier et enlevez les marqueurs de conflit.

Tranche de pain supérieure
Mayonnaise
Laitue
Tomate
Comté
Saucisson
Mortadelle
Jambon
Moutarde
Tranche de pain inférieure

Maintenant utilisez svn resolve et vous êtes paré pour propager vos changements :

$ svn resolve --accept working sandwich.txt
Conflit sur 'sandwich.txt' résolu
$ svn commit -m "Va pour mon sandwich et au diable celui de Sally !"

Soyez prudent et ne lancez svn resolve qu'une fois certain que vous avez résolu le conflit dans votre fichier : une fois les fichiers temporaires effacés, Subversion vous laisse propager le fichier même s'il contient toujours des marqueurs de conflit.

Si jamais vous êtes perdu lors de l'édition du fichier en conflit, vous pouvez toujours consulter les trois fichiers que Subversion a créé pour vous dans votre copie de travail, y compris le fichier tel qu'il était avant que vous ne lanciez la mise à jour. Vous pouvez même utiliser un outil externe interactif spécialisé dans les fusions pour examiner ces trois fichiers.

Abandonner vos modifications au profit de la révision la plus récente

Si vous faites face à un conflit et que vous décidez d'abandonner vos changements, vous pouvez lancer svn resolve --accept theirs-full CHEMIN-DU-CONFLIT, Subversion abandonne alors vos modifications et supprime les fichiers temporaires :

$ svn update
Conflit découvert dans 'machin.c'.
Sélectionner : (p) report, (df) diff complet, (e) édite,
        (h) aide pour plus d'options :
C    sandwich.txt
Actualisé à la révision 2.
$ ls sandwich.*
sandwich.txt  sandwich.txt.mine  sandwich.txt.r2  sandwich.txt.r1
$ svn resolve --accept theirs-full sandwich.txt
Conflit sur 'sandwich.txt' résolu
$

Revenir en arrière : utiliser svn revert

Si vous faites face à un conflit et qu'après examen de la situation, vous décidez d'abandonner vos changements et de repartir de zéro (peu importe en fait que ce soit après un conflit ou à n'importe quel autre moment), contentez-vous de revenir en arrière sur vos changements :

$ svn revert sandwich.txt
'sandwich.txt' réinitialisé
$ ls sandwich.*
sandwich.txt

Notez que quand vous revenez en arrière sur un fichier en conflit, vous n'avez pas besoin de lancer svn resolve.

Propager vos modifications

Enfin ! Vos modifications sont terminées, vous les avez fusionnées avec celles du serveur et vous êtes prêt à les propager vers le dépôt.

La commande svn commit envoie vos changements au dépôt. Quand vous propagez un changement, vous devez l'accompagner d'un message de propagation qui décrit ce changement. Votre message est associé à la nouvelle révision que vous créez. Si votre message est bref, vous pouvez le passer en ligne de commande en utilisant l'option --message (ou -m) :

$ svn commit -m "Nombre de tranches de fromage corrigé."
Envoi        sandwich.txt
Transmission des données .
Révision 3 propagée.

Cependant, si vous avez rédigé votre message au fur et à mesure, vous souhaitez sûrement indiquer à Subversion de récupérer le message dans un fichier en lui donnant le nom du fichier avec l'option --file (-F) :

$ svn commit -F message_de_propagation
Envoi        sandwich.txt
Transmission des données .
Révision 4 propagée.

Si vous ne spécifiez ni l'option --message ni l'option --file, Subversion lance automatiquement votre éditeur de texte favori (voir les détails de editor-cmd dans la section intitulée « Configuration générale ») pour que vous rédigiez le message de propagation.

[Astuce] Astuce

Si, au moment où vous rédigez votre message de propagation, vous décidez d'annuler la propagation, vous n'avez qu'à quitter l'éditeur de texte sans sauvegarder les changements. Si vous avez déjà sauvegardé le message, effacez le texte, sauvegardez à nouveau puis choisissez d'annuler :

$ svn commit
Attente de Emacs...Fait

Entrée du journal non modifié ou non précisé
a)nnule, c)ontinue, e)dite
a
$

Le dépôt ne sait pas si vos changements ont un sens ou pas ; il vérifie seulement que personne n'a modifié, pendant que vous aviez le dos tourné, un des fichiers que vous-même avez modifié. Si c'est le cas, la propagation toute entière échoue, affichant un message vous informant qu'un ou plusieurs de vos fichiers ne sont plus à jour :

$ svn commit -m "Ajout d'une autre règle"
Envoi        règles.txt
svn: E155011: Echec de la propagation (commit), détails :
svn: E155011: Fichier '/règles.txt' obsolète
…

Notez que le phrasé exact de ce message d'erreur dépend du protocole réseau et du serveur que vous utilisez, mais l'idée reste la même.

À ce moment là, vous devez lancer svn update, traiter les fusions ou conflits qui apparaissent et retenter une propagation.

Nous en avons terminé avec le cycle d'utilisation de base de Subversion. Subversion offre beaucoup d'autres fonctionnalités pour gérer votre dépôt et votre copie de travail, mais l'utilisation quotidienne de Subversion ne requiert pratiquement que les commandes que nous venons de voir dans ce chapitre. Intéressons-nous quand même à quelques commandes supplémentaires utilisées relativement souvent.



[6] Bien sûr, rien n'est jamais totalement supprimé du dépôt — seulement de la révision HEAD du dépôt. Vous pouvez récupérer tout ce que vous avez supprimé en extrayant (ou en mettant à jour votre copie de travail à) une révision précédente de celle dans laquelle vous avez fait la suppression. Lisez également la section intitulée « Résurrection des éléments effacés ».

[7] Et si vous commandez ça, on vous chassera de la ville à coup de baguette rassie.