Résoudre des conflits

De temps en temps , vous aurez un conflit au moment de mettre à jour/fusionner vos fichiers avec le référentiel ou lorsque vous migrerez votre copie de travail vers une autre URL. Il y a deux sortes de conflits:

Conflit de fichier

Un conflit sur un fichier arrive si deux (ou plus) développeurs changent les mêmes lignes d'un fichier.

Conflits dans l'arborescence

Un conflit dans l'arborescence arrive quand un développeur déplace/renomme/supprime un fichier ou un dossier, qu'un autre développeur a aussi déplacé/renommé/supprimé voire juste modifié.

Conflit de fichiers

Un conflit de fichier arrive quand 2 développeurs our plus modifient un même fichier. Dans la mesure où Subversion ne sait rien de votre projet, il laisse la résolution des conflits à la charge des développeurs. Dès qu'un conflit est détecté, vous devriez ouvrir le fichier en question, et chercher les lignes commençant par <<<<<<<. La zone en conflit est marquée de cette manière:

	<<<<<<< nom_de_fichier
		vos modifications
	=======
		code fusionné depuis le référentiel
	>>>>>>> révision
	

De plus, pour chaque conflit Subversion place trois fichiers dans votre répertoire:

nom_du_fichier.ext.mine

C'est votre fichier comme il a existé dans votre copie de travail avant que vous mettiez à jour votre copie de travail - c'est-à-dire sans marqueurs de conflit. Ce fichier a vos derniers changements et rien d'autre.

nom_du_fichier.ext.rOLDREV

C'est le fichier qui était la révision de BASE avant que vous mettiez à jour votre copie de travail. C'est-à-dire le fichier que vous avez extrait avant de faire votre dernière édition.

nom_du_fichier.ext.rNEWREV

C'est le fichier que votre client de Subversion venait de recevoir du serveur quand vous avez mis à jour votre copie de travail. Ce fichier correspond à la révision de tête du référentiel.

Vous pouvez soit lancer un outil externe de fusion / un éditeur de conflit avec TortoiseSVNÉditer les conflits soit utiliser un autre éditeur pour résoudre le conflit manuellement. Vous devrez décider à quoi devrait ressembler le code, faites les changements nécessaires et sauvegardez le fichier.

Exécutez ensuite la commande TortoiseSVNRésolu... et livrez vos modifications au référentiel. Veuillez noter que la commande de résolution ne résout pas vraiment le conflit. Il supprime juste les fichiers nom_du_fichier.ext.mine et nom_du_fichier.ext.r*, pour vous permettre de livrer vos changements.

Si vous avez des conflits avec des fichiers binaires, Subversion n'essaye pas de fusionner les fichiers lui-même. Le fichier local reste inchangé (exactement comme la dernière fois que vous l'avez modifié) et vous avez des fichiers nom_du_fichier.ext.r*. Si vous voulez renoncer à vos changements et garder la version du référentiel, utilisez simplement la commande Revenir en arrière. Si vous voulez garder votre version et écraser la version du référentiel, utilisez la commande Résolu..., livrez ensuite votre version.

Vous pouvez utiliser la commande Résolu... pour plusieurs fichiers si vous faites un clic droit sur le dossier parent et sélectionnez TortoiseSVNRésolu... Cela affichera une boîte de dialogue listant tous les fichiers en conflit dans ce dossier et vous pouvez choisir lesquels marquer comme résolus.

Conflits dans l'arborescence

Un conflit dans l'arborescence est causé quand un développeur déplace/renomme/supprime un fichier ou un répertoire, qu'un autre développeur a également déplacé/renommé/supprimé ou juste modifé. Plusieurs situations peuvent générer un conflit d'arborescence, et chacune a une solution différente.

Dans Subversion, lorsque qu'un fichier est supprimé, il l'est aussi localement, de ce fait, même s'il génère un conflit d'arborescence, aucune action de résolution de conflit de ne peut être effectuée grâce au menu contextuel du click droit. Utilisez la fenêtre Vérifier les Modifications à la place pour pouvoir accéder aux options Edition des conflits.

TortoiseSVN peut aider à trouver les endroits où fusionner les modifications, mais cela ne résoudra pas tous les conflits.Souvenez vous qu'après une mise à jour la base de travail contiendra la révision des éléments tels qu'ils étaient au moment de la mise à jour. Si vous annulez une modification après avoir fait une mise à jour l'élément reviendra à la version du référentiel, pas à l'état dans lequel était l'élément avant que vous fassiez vos modifications.

Suppression locale, édition de la mise à jour

  1. Le développeur A modifie Foo.c et en fait la livraison

  2. Le développeur B a renommé simultanément Foo.c en Bar.c dans sa copie de travail, ou simplement supprimé Foo.c ou son répertoire parent.

Une mise à jour de la copie de travail du développeur B mène à un conflit dans l'arborescence:

  • Foo.c a été supprimé de la copie de travail, mais est marqué comme étant en conflit d'arborescence.

  • Si le conflit vient d'un renommage plus que d'une suppression alors Bar.c est marqué comme ajouté, mais ne contient pas les modification du développeur A.

Le développeur B doit maintenant choisir s'il veut conserver les modifications du développeur A. Dans le cas d'un renommage de fichier, il peut fusionner les modifications de Foo.c dans le fichier renommé Bar.c. Pour des suppressions de fichier ou de répertoire il peut choisir de garder l'élément avec les modifications du développeur A et annuler la suppression. Ou, en ne faisant que marquer le conflit comme étant résolu, il annule les modifications du développeur A.

La fenêtre d'édition de conflits offre la possibilité de fusionner les changements si elle peut trouver le fichier original de celui renommé en Bar.c. Dépendant d'où la mise à jour à été invoqué, il n'est pas toujours possible de trouver le fichier source.

Modification locale, suppression dans la mise à jour

  1. Le développeur A renomme Foo.c en Bar.c et envoie les modifications au dépôt.

  2. Le développeur B modifie Foo.c dans sa copie de travail.

Ou dans le cas d'un déplacement de répertoire ...

  1. Le développeur A déplace le réperetoire parent FooFolder vers BarFolder et soumet celui-ci au dépôt.

  2. Le développeur B modifie Foo.c dans sa copie de travail.

Une mise à jour de la copie de travail du développeur B mène à un conflit dans l'arborescence. Pour un simple conflit de fichier :

  • Bar.c est ajouté dans la copie de travail avec le statut 'normal'.

  • Foo.c est marqué comme ayant été ajouté (avec historique) et étant en conflit dans l'arborescence.

Pour un conflit de répertoire:

  • Bar.c est ajouté dans la copie de travail avec le statut 'normal'.

  • Foo.c est marqué comme ayant été ajouté (avec historique) et étant en conflit dans l'arborescence.

    Foo.c est marqué comme modifié.

Le développeur B doit à présent décider de garder la réorganisation du développeur A et de fusionner ses changement dans le fichier correspondant dans la nouvelle architecture, ou simplement annuler les modifications du développeur A et garder le fichier local.

Pour fusionner ses modifications locales avec la réorganisation, le développeur B doit d'abord trouver quel est le nouveau nom du fichierFoo.c dans le référentiel. Cela peut être fait en utilisant la fenêtre de commentaires. A présent les modifications doivent être réintégrées à la main dans le mesure où il n'y a aucun outil existant pour simplifier ce processus. Dès que les modifications ont été répercutées, le chemin conflictuel est redondant et peut donc être supprimé. Dans ce cas utilisez le bouton Supprimer dans la fenêtre de résolution de conflits pour faire le nettoyage et marquer le conflit comme résolu.

Si le développeur B décide que les modifications du développeur A étaient mauvaises alors elle doit choisir le bouton Garder dans la fenêtre de résolution des conflits. Cette action a pour effet de marquer le conflit du fichier/répertoire comme résolu, mais les modifications du développeur A doivent être retirées à la main. De nouveau la fenêtre de commentaires aide à trouver ce qui a été déplacé.

Suppression locale, suppression dans la mise à jour

  1. Le développeur A renomme Foo.c en Bar.c et envoie les modifications au dépôt

  2. Le développeur B renomme Foo.c en Bix.c

Une mise à jour de la copie de travail du développeur B mène à un conflit dans l'arborescence:

  • Bix.c est marqué comme ajouté avec l'historique.

  • Bar.c est ajouté dans la copie de travail avec le statut 'normal'.

  • Foo.c est marqué comme étant supprimé et étant en conflit dans l'arborescence.

Pour résoudre ce conflit, le développeur B doit trouver à quel fichier renommé/déplacé correspond la version conflictueuse de Foo.c dans le référentiel. Ce peut être fait en utilisant la fenêtre de log.

Le développeur B doit alors décider quel nouveau nom de Foo.cgarder - celui du développeur A ou celui issu du renommage qu'il a lui même effectué.

Dès que le développeur B a résolu manuellement le conflit, l'arborescence des conflits doit être marquée comme résolue grâce au bouton approprié dans la fenêtre d'édition des conflits.

Copie locale incomplète, modification dans la mise à jour

  1. Le développeur A travaillant sur le tronc modifie Foo.c et en fait la livraison au dépôt.

  2. Le développeur B travaillant sur une branche renomme Foo.c en Bar.c et en fait la livraison au dépôt

Une fusion des modifications du tronc du développeur A dans la branche de copie de travail du développeur B conduit à un conflit dans l'arborescence:

  • Bar.c est déjà dans la copie de travail avec le statut 'normal'.

  • Foo.c est marqué comme manquant dans l'arborescence des conflits.

Pour résoudre ce conflit, les développeurs B doit marquer le fichier comme résolu dans la fenêtre de résolution de conflits, lequel sera retiré de la liste des conflits. Le développeur B doit alors décider s'il faut copier le fichier manquant Foo.c depuis le référentiel, ou fusionner Foo.c avec le fichier renommé Bar.c ou simplement s'il faut ignorer les changements en marquant le conflit comme étant résolu et ne rien faire d'autre.

Notez que si vous copiez le fichier manquant depuis le référentiel et que vous le marquez comme résolu, votre copie sera de nouveau retirée. Vous devez résoudre d'abord le conflit.

Modification locale, suppression dans la fusion

  1. Le développeur A travaillant sur le tronc renomme Foo.c en Bar.c et l'envoie au dépôt

  2. Le développeur B travaillant sur une branche modifie le fichier Foo.c et l'envoie au dépôt.

Il y a des cas équivalents pour les déplacements de répertoire, mais ce n'est pas encore détecté dans Subversion 1.6 ...

  1. Le développeur A travaillant sur le tronc déplace le dossier parent FooFolder vers BarFolder et l'envoie au dépôt.

  2. Le développeur B travaillant sur une branche modifie Foo.c dans sa copie de travail.

Une fusion des modifications du tronc du développeur A dans la branche de copie de travail du développeur B conduit à un conflit dans l'arborescence:

  • Bar.c est marqué comme étant ajouté.

  • Foo.c est marqué comme ayant été modifié et étant en conflit dans l'arborescence.

Le développeur B doit à présent décider de garder la réorganisation du développeur A et de fusionner ses changement dans le fichier correspondant dans la nouvelle architecture, ou simplement annuler les modifications du développeur A et garder le fichier local.

Pour fusionner ses modifications locales avec les autre remaniements, le développeur B doit trouver à quel fichier renommé/déplacé correspond la version conflictueuse de Foo.c dans le dépôt. Cela peut être fait en utilisant la fenêtre de commentaires du fichier source. L'éditeur de conflit ne montre que les commentaires relatifs à la copie de travail puisqu'il ne sait pas quel chemin a été utilisé lors de la fusion, donc vous devrez le découvrir vous même. Les modifications doivent alors être fusionnées à la main puisqu'il n'existe actuellement aucun moyen d'automatiser ou de simplifier ce processus. Une fois que les changement ont été effectués, le chemin conflictueux est superflu et peut être supprimé. Dans de cas, utilisez le bouton Supprimer dans la fenêtre d'édition de conflits pour marquer le conflit comme étant résolu.

Si le développeur B décide que les modifications du développeur A étaient mauvaises elle doit alors choisir le bouton Garder dans la fenêtre de résolution de conflit. Cette action marque le conflit du fichier/répertoire comme étant résolu, mais le développeur A doit reporter ses modifications à la main. La fenêtre de commentaires du fichier source de la fusion aide à détecter ce qui a été déplacé.

Suppression locale, suppression dans la fusion

  1. Le développeur A travaillant sur le tronc renomme Foo.c en Bar.c et l'envoie au dépôt

  2. Le développeur B travaillant sur une branche renomme Foo.c en Bix.c et envoie les modifications au dépôt

Une fusion des modifications du tronc du développeur A dans la branche de copie de travail du développeur B conduit à un conflit dans l'arborescence:

  • Bix.c est marqué comme étant dans un état normal (non modifé).

  • Bar.c est marqué comme ajouté avec son historique.

  • Foo.c est marqué comme manquant et générant une erreur dans l'arborescence.

Pour résoudre ce conflit, le développeur B doit trouver quel fichier renommé/déplacé correspond à la version conflictueuse de Foo.c dans le référentiel. Ce peut être fait en utilisant la fenêtre de commentaires pour les sources fusionnées. L'éditeur de conflit ne montre que les commentaires relatifs à la copie de travail puisqu'il ne sait pas quel chemin a été utilisé lors de la fusion, donc vous devrez le découvrir vous même.

Le développeur B doit alors décider quel nouveau nom de Foo.cgarder - celui du développeur A ou celui issu du renommage qu'il a lui même effectué.

Dès que le développeur B a résolu manuellement le conflit, l'arborescence des conflits doit être marquée comme résolue grâce au bouton approprié dans la fenêtre d'édition des conflits.

Other tree conflicts

There are other cases which are labelled as tree conflicts simply because the conflict involves a folder rather than a file. For example if you add a folder with the same name to both trunk and branch and then try to merge you will get a tree conflict. If you want to keep the folder from the merge target, just mark the conflict as resolved. If you want to use the one in the merge source then you need to SVN delete the one in the target first and run the merge again. If you need anything more complicated then you have to resolve manually.