[Plan du site]
Vous êtes ici ---
> Le Site du Zéro
> Les tutoriels
> Non-Officiels
> Programmation
> Environnements de développement
> Gérez vos projets à l'aide du gestionnaire de versions Subversion > Les bases - Utilisations des clients > Gérer les conflits
> Lecture du tutoriel
Gérer les conflits
Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Dans ce mini-tuto, nous allons enfin apprendre à résoudre la chose la plus horrible... les conflits !
Comme nous l'avons déjà vu (mais un petit rappel ne fait jamais de mal), un conflit apparaît lorsque deux personnes (ou plus) décident de modifier un fichier au même moment. La plus rapide va
commiter son changement sans aucun problème, mais la deuxième va devoir gérer le fait que, sur le serveur, se trouve une version plus récente que celle sur laquelle elle a travaillé.
Pour vous entraîner à gérer les conflits, il faut d'abord les créer. Pour en créer un, aucun problème, il suffit de faire un update du fichier voulu à une version antérieure, de modifier le fichier et de le commiter. Le serveur ne sera pas content puisque la version sur laquelle vous avez travaillé n'est pas la plus récente au moment du commit.
Pour éviter, lorsque vous travaillez sur les conflits, qu'il se passe des choses incompréhensibles parce que vous êtes cinq à tester les conflits sur le même fichier, créez un dossier, créez un fichier dedans et remplissez-le, faites un commit, puis un deuxième avec un autre ajout de contenu, updatez à la première version du fichier (seulement la moitié du contenu) et entraînez-vous comme ça.
Maintenant que tout le monde se rappelle comment créer un conflit, je vous propose de mettre en place votre environnement et d'en créer un.
Alors, quelles sont les options qui viennent à nous pour contourner le problème (le résoudre nous-mêmes ou le laisser à quelqu'un d'autre !?

). Trois commandes en fait :
Diff
Cette commande va vous permettre de ne pas vous perdre. Vous codez plus vite que votre ombre ? Vous ne savez plus ce que vous avez modifié depuis le dernier
update ? Pas de problème,
svn diff est là pour vous expliquer ce que vous avez fait.
Code : Bash1
2 | svn diff [Target[@Rev]...] [-N] [-r Rev1:Rev2] [--force] [--summarize] [--no-diff-deleted] \
[--username login] [--password mdp] [--no-auth-cache]
|
- @Rev correspond à la révision de référence que vous voulez prendre. Il montrera les différences entre les versions du fichier en montrant ce qui a été ajouté ou supprimé par rapport à cette référence.
- -N pour non récursif (uniquement ce dossier).
- --force pour forcer la commande à s'exécuter.
- --sumarize pour qu'il n'affiche qu'un résumé.
- --no-diff-deleted pour qu'il n'affiche pas les différences pour les fichiers ayant été supprimés.
Bon, je vous ai montré la commande entière pour que vous sachiez l'utiliser, mais ce dont vous avez besoin pour voir les différences que vous avez apportées par rapport à votre dernier
update, c'est juste :
Code : Bash
Et c'est tout.
À mon grand regret, je n'ai pas trouvé d'équivalent de la commande "svn diff" pour TortoiseSVN. Mais rassurez-vous, TortoiseSVN possède un outil bien plus puissant pour comparer deux versions d'un fichier, ou bien deux fichiers différents pour les fusionner dans un troisième fichier. Ce sera vu en prochaine sous-partie.
Revert
Cette commande va enlever la plupart des modifications effectuées sur les éléments (fichiers ou dossiers) depuis le dernier
update.
Euh... ça veut dire quoi : "la plupart" ? Il ne va pas tout remettre ? C'est au petit bonheur la chance ?
Pas du tout ! Mais si vous regardez le manuel (si si, le manuel), vous verrez que cette option ne permet pas de restaurer des dossiers supprimés. Sinon, c'est du tout cuit.
On voit d'ici le problème de cette commande. Toutes vos modifications vont partir à la poubelle et vous allez gagner le droit de les refaire sur le nouveau fichier après un update.
Et oui, la vie est dure, mais c'est comme ça. Dans un projet, la plupart du temps, cette commande est utilisée parce que quelqu'un a édité un fichier binaire,".doc" par exemple, alors que ce n'était pas son tour dans le planning. Or le problème, c'est que SVN ne sait pas fusionner des fichiers binaires ! Dommage... il va donc falloir tout refaire.
La commande s'utilise comme suit (très peu d'options) :
Code : Bash1 | svn revert [CHEMIN] [--targets Fichier_darguments] [-R]
|
Resolved
Cette commande a "deux fonctions". Elle ne permet que d'indiquer qu'un conflit est résolu (comme on aurait pu s'en douter), seulement, subtilité, il y a deux façons de s'en servir.
Méthode 1
J'ai un conflit, je
me casse la tête et le résous, j'indique qu'il est résolu, je
commit.
Méthode 2
J'ai un problème, je ne m'en occupe pas parce que j'ai pas envie de refaire ce que j'ai fait et que c'était mon tour dans le planning, j'indique qu'il est résolu (même si ce n'est pas le cas), je
commit.
Pour la méthode 1, nous allons voir comment fusionner le travail, en cas de conflit, dans la prochaine sous-partie. Pour la méthode 2, vous l'aurez compris, elle permet de ne pas avoir à tout refaire soi-même, en revanche, elle donne tout à refaire à l'autre membre de l'équipe qui a
commité avant vous.
Voici son utilisation (à nouveau très peu d'options) :
Code : Bash1 | svn resolved [CHEMIN] [--targets Fichier_darguments] [-R]
|
Et TortoiseSVN
Et bien, à nouveau, pas besoin de se casser la tête.
Clic droit >> TortoiseSVN >> Revert
Clic droit >> TortoiseSVN >> Resolved
TortoiseSVN est très bien fait, il n'affiche pas les actions qu'il est impossible d'effectuer. Ainsi, s'il n'y a rien à résoudre (ni à revert) sur le fichier ou dossier cliqué, il ne vous proposera pas la commande !
Ici, nous allons apprendre à résoudre le conflit dans sa façon la plus subtile : la fusion des versions en conflit.
Pourquoi est-ce que l'on ne fait pas toujours comme ça ?
Eh bien, tout simplement parce que ce n'est pas toujours possible. Comme dit précédemment, il n'est pas possible d'user de cette méthode pour tout conflit. Elle ne fonctionnera pas avec les fichiers binaires par exemple. En revanche, elle fonctionne très bien avec les fichiers textes.
Je vais dans cette partie détailler la marche que j'ai suivie. Ça vous permettra de refaire la même pour mieux comprendre, et de vous faire utiliser un peu aussi votre esprit d'analyse.
Commençons par la création du conflit :
Code : Bash 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | >>> svn update -r 62 Fichier\ 1.txt
U Fichier 1.txt
Updated to revision 62.
>>> vim Fichier\ 1.txt
>>> svn ci -m "commit d'un conflit"
Sending Fichier 1.txt
svn: Commit failed (details follow):
svn: Your file or directory 'Fichier 1.txt' is probably out-of-date
svn: The version resource does not correspond to the resource within the transaction. Either the requested version resource is out of date (needs to be updated), or the requested version resource is newer than the transaction root (restart the commit).
>>> ls
Dossier 1 monajout.cpp testFile
Fichier 1 - Copie.txt test youpi2.txt
Fichier 1.txt test123.txt
argInfo test2
>>> svn status -u Fichier\ 1.txt
M * 62 Fichier 1.txt
Status against revision: 76
|
Et voilà, ce gentil petit message d'erreur nous explique que, contre toute attente, la version sur laquelle nous nous sommes basés pour faire nos changements n'est pas à jour par rapport au serveur (ce n'est pas la plus récente). Il va donc falloir corriger le tir.
Résolution manuelle
Regardons, au hasard, ce qui se passe si l'on tente un
update sur ce fichier (pas à jour mais modifié localement).
Code : Bash1
2
3 | >>> svn update Fichier\ 1.txt
C Fichier 1.txt
Updated to revision 76.
|
Notez le 'C' en première colonne qui nous indique que le fichier est
Conflicted (en conflit). Mais regardons un peu plus loin.
Code : Bash1
2
3
4
5
6 | >>> ls
Dossier 1 Fichier 1.txt.r76 test2
Fichier 1 - Copie.txt argInfo testFile
Fichier 1.txt monajout.cpp youpi2.txt
Fichier 1.txt.mine test
Fichier 1.txt.r62 test123.txt
|
On constate que l'
update nous a rajouté tout un tas de nouveaux "Fichier 1.txt". Parmi ces nouveaux, on trouve :
- "Fichier 1.txt", le vrai, celui sous contrôle de version, celui en conflit (tous les autres ne sont pas considérés comme étant sous contrôle de version, vous pourrez vous en persuader avec les icônes, ceux qui en ont et avec un "svn ls" pour les autres).
- "Fichier 1.txt.mine", le mien, celui que j'ai modifié.
- "Fichier 1.txt.r62", le fichier 1.txt de la révision 62 (celle sur laquelle j'ai travaillé).
- "Fichier 1.txt.r76", celui de la révision 76, la dernière révision en date lors du commit.
Un petit coup d'oeil sur ce fameux Fichier 1.txt qui est sous contrôle de version, qu'en a fait le
update ?
Code : Bash 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | >>> svn status -uv Fichier\ 1.txt
C 76 76 SdZ-Guest Fichier 1.txt
Status against revision: 76
>>> Cat Fichier\ 1.txt
[... Début du Fichier ...]
Et je fous la merde
Merci
<<<<<<< .mine
OM en force !
Création d'un conflit
=======
OM en force !
Barça en berne lol
>>>>>>> .r76
|
On voit que les deux modifications sont présentes dans ce fichier. À la fois les miennes, mais aussi celles faites par le
commit de la révision 76. Il est assez simple de comprendre comment les différences sont séparées :
- Tout ce qui est entre "<<<<<<< .mine" et "=======" sont mes modifications ;
- Tout ce qui se trouve entre "=======" et ">>>>>>> .r76" sont les modifications qui ont été commitées lors de la révision 76.
À partir de là, on garde ce que l'on veut, on remet dans l'ordre, on déclare le conflit comme
resolved (résolu) pour autoriser le
commit et on
commit.
Code : Bash1
2
3
4
5
6
7 | >>> vim Fichier\ 1.txt
>>> svn resolved Fichier\ 1.txt
Resolved conflicted state of 'Fichier 1.txt'
>>> svn ci Fichier\ 1.txt -m "resolution du conflit"
Sending Fichier 1.txt
Transmitting file data .
Committed revision 77.
|
Oui, mais ça m'a l'air très manuel cette méthode.... Il n'y a pas plus subtil ?
Eh bien, oui et non. Pour la plupart des modifications effectuées, SVN ne peut se permettre de choisir pour vous, si deux personnes on édité la même ligne (le même endroit dirons nous plutôt), quelles modifications arrivent en premier ?
Résolution automatique
En revanche il sait très bien faire le
merge (la fusion) tout seul si vous n'avez pas édité les mêmes parties d'un document.
Petit exemple.
Je prends le fichier monaj.cpp que je trouve sur le SVN au moment de la rédaction.
Citation : monaj.cppje rajoute un fichier
et je le modifie en plus
...tant pis
un ligne après
hop
J'
update sur deux
working copy (copie de travail) et j'édite sur les deux le fichier. Pour le premier, je rajoute "hop" au début du fichier (en rajoutant une ligne), pour le deuxième, je rajoute "hop" à la fin du fichier (sans rajouter de ligne).
Je
commit avec un puis avec l'autre.
Le deuxième commit me donne une erreur, donc j'
update.
Code : Bash 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | >>> svn up monaj.cpp
G monaj.cpp
Updated to revision 90.
>>> ls
Dossier 1 monaj.cpp testFile
Fichier 1 - Copie.txt test123.txt youpi2.txt
Fichier 1.txt test2
argInfo test3
>>> cat monaj.cpp
hop
je rajoute un fichier
et je le modifie en plus
...tant pis
un ligne après
hop hop
|
On voit que le fichier n'est pas 'C' pour indiquer un conflit, mais 'G' pour indiquer une fusion automatique. Et on constate qu'en effet, aucun fichier .mine, .r89, .r90 n'a été créé (comme lors d'un conflit), et que le fichier monaj.cpp a bien intégré les deux modifications faites.
Et TortoiseSVN
Utilisateurs de Windows et de TortoiseSVN, regardez bien. Qu'a-t-on fait lors de cette sous-partie ? Uniquement des
updates et des
commits. Mais vous savez déjà faire tout ça. Donc vous savez tout faire.
Quand je vous disais que l'apprentissage d'un client n'était pas compliqué, ce n'était pas pour rien. Il faut juste la théorie et hop c'est parti.
Information tout de même, pour faire un update vers une révision précédente avec TortoiseSVN, il faut faire :
Clic droit >> TortoiseSVN >> update to revision...
Pourtant, TortoiseSVN propose quand même un GROS plus : TortoiseMerge !
Eh oui, la résolution manuelle d'un conflit est quelque peu lourde : repérer les différences entre deux fichiers et tout et tout. TortoiseSVN a mis au point un outil pour le moins performant qu'est TortoiseMerge. Vous pouvez récupérer sa documentation
par ici.
Une annexe aura très certainement lieu pour apprendre à s'en servir correctement. En attendant, il faudra vous contenter de la doc.
Maintenant que l'on a vu comment le résoudre, on va voir comment l'éviter.
Ce que l'on a déjà vu
Eh oui, tout au long du tutoriel, j'ai essayé de vous sensibiliser le plus possible aux
"best practices" (les bonnes pratiques) du SVN à mettre en oeuvre pour éviter d'avoir des conflits. Petit récapitulatif :
- essayez de travailler le plus possible avec des fichiers textes et le moins possible avec des fichiers binaires ;
- faites des updates le plus souvent et régulièrement possible, et obligatoirement avant de commencer à travailler sur un fichier ;
- faites des commits réguliers, dès que vous avez fini de travailler sur un fichier (pas deux heures après), et si le travail prend du temps, un petit commit intermédiaire ne fait pas de mal et sauvegarde votre travail ;
- ayez un planning pour savoir à tout instant qui peut travailler quand sur les fichiers binaires ;
- consultez régulièrement les logs et autres informations pour ne pas faire du travail pour rien.
Il est fortement conseillé d'appliquer ces bonnes pratiques !
Lock et unlock
Il existe également deux commandes qui sont là rien que pour vous, exprès pour éviter les conflits. Il s'agit de
lock (verrouiller) et
unlock (déverrouiller).
Ces deux commandes ont un comportement très simple.
Lock va bloquer l'édition du fichier aux autres membres jusqu'à ce que vous fassiez un
unlock.
Si l'on va voir l'icône associé sous TortoiseSVN, on trouve celle-ci :

Nous avons donc un très jolie petit cadenas qui nous montre que le fichier possède un
lock.
Lors de votre commit sur l'élément verrouillé, il va vous être proposé de relâcher le verrou. C'est d'ailleurs le comportement par défaut. Donc si vous ne voulez pas libérer le verrou, il faut le préciser.
Regardons ce que cela donne pour l'utilisation sous TortoiseSVN et en ligne de commande. Pour TortoiseSVN, toujours aussi simple :
clic droit >> TortoiseSVN >>Get lock... et
clic droit >> TortoiseSVN >> Release lock.
Pour la ligne de commande :
Code : Bash1 | svn lock TARGET... [--target fichier_darguments] [-m "message"] [--force] [--force-log] [--username login] [--password mdp] [--no-auth-cache]
|
et
Code : Bash1 | svn unlock TARGET... [--target fichier_darguments] [--force] [--username login] [--password mdp] [--no-auth-cache]
|
Alors, dans ces multiples options, vous en retrouvez quelques-unes que vous connaissez déjà, on notera d'ailleurs la possibilité de mettre un message de
log sur le
lock pour le justifier, mais également quelques nouvelles options :
- --no-auth-cache permet de ne pas stoker les informations d'accès au serveur (login & mdp) dans le cache. À utiliser si vous êtes sur l'ordinateur d'un autre par exemple.
- --force-log va, comme son nom l'indique encore une fois, forcer la validité de votre message de log.
- --force, lui, force l'exécution de la commande, même si quelqu'un d'autre avait, par exemple, déjà mis un verrou sur l'élément concerné.
--force ne devrait pas être utilisée. Cette option sert si vraiment quelqu'un dans le groupe a fait une connerie, a verrouillé quelque chose qu'il n'aurait pas dû ou bien l'a fait à un moment où il n'aurait pas dû.
Maintenant, vous l'aurez compris, la chose simple à faire pour éviter les conflits est de, lorsqu'on va travailler sur un fichier, le
locker, verrouiller, pour être sûr qu'il n'y ait pas de conflit.
NON ! C'est une énorme erreur. Le lock se doit d'être utilisé avec parcimonie. Tout le but du merge automatique est de permettre à plusieurs personnes de travailler en même temps sur le même fichier. Si vous faites un lock à chaque fois, il y a une perte de productivité.
Le
lock montre son utilité lors d'un travail sur un fichier binaire, car, je le rappelle une vingtième fois, on ne sait pas fusionner les fichiers binaires. Mais en dehors de ce cas-là, il n'est et ne devrait presque jamais être utilisé.
Vous venez de voir plusieurs méthodes pour résoudre des conflits. Le tout est maintenant de les maîtriser parce que vous aller forcément faire face à des conflits dans vos projet.