Question

Je me sers Mercurial pendant un certain temps, et il y a un « fait » qui est donné à plusieurs reprises.

En fait, il m'a frappé en regardant une vidéo réalisée par FogCreek hier, cette vidéo: Fog Creek Kiln. Déverrouiller la puissance de DVCS pour votre entreprise qu'il semble y avoir quelque chose qui ne fonctionne pas pour moi ici

Vers 1h39 dans cette vidéo et au-delà, il fait un point de dire que, bien que d'autres systèmes de contrôle de version pistes révisions (ie. Instantanés), DVCS » comme changesets piste Mercurial (ie. Ce qui se passait entre les instantanés.)

Cela leur donne un avantage dans des scénarios à la fusion, et il montre un exemple. Si vous déplacez une fonction dans une branche, et de changer la même fonction dans une autre branche, Mercurial est capable de fusionner cela.

Et je l'ai vu ailleurs mentionné, bien que je ne trouve pas de lien direct maintenant.

Cela ne semble pas fonctionner pour moi.


Edit: Ceci est un problème avec la valeur par défaut "beyondcompare3" configuration de l'outil de fusion pour TortoiseHg. J'ai ajouté la configuration ci-dessous à mon dossier Mercurial.ini, et maintenant il fonctionne comme prévu. Bien sûr, il va punt à l'outil GUI si elle ne peut pas autoMerge, mais maintenant la fusion décrite dans cette question passe ici sans invites et fait exactement la bonne chose hors de la boîte

[ui]
merge = bc3

[merge-tools]
bc3.executable = C:\Program Files (x86)\Beyond Compare 3\bcomp.exe
bc3.args = $local $other $base $output /automerge /reviewconflicts /closescript
bc3.priority = 1
bc3.premerge = True
bc3.gui = True

Pour tester cela, je me suis engagé ce fichier à un référentiel:

void Main()
{
    Function1();
    Function2();
}

public void Function1()
{
    Debug.WriteLine("Function 1");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}

Ensuite, dans deux changesets parallèles différentes ramifications à partir de celui-ci, je l'ai fait les deux modifications suivantes:

  1. je me suis déplacé la fonction Fonction1 au fond du fichier
  2. J'ai changé le message à l'intérieur Fonction1

J'ai ensuite essayé de fusionner, et Mercurial me donne une fenêtre de conflit de fusion, en essayant de comprendre ce que je faisais.

En fait, il essaie de changer le texte Function2, qui est maintenant dans la position qui était Fonction1 avant qu'il ne soit déplacé.

Ce ne devait pas arriver!


Voici les fichiers source pour reproduire mon exemple:

fichier batch pour la production du référentiel:

@echo off

setlocal

if exist repo rd /s /q repo
hg init repo
cd repo

copy ..\example1.linq example.linq
hg commit -m "initial commit" --addremove --user "Bob" --date "2010-01-01 18:00:00"

copy ..\example2.linq example.linq
hg commit -m "moved function" --user "Bob" --date "2010-01-01 19:00:00"

hg update 0
copy ..\example3.linq example.linq
hg commit -m "moved function" --user "Alice" --date "2010-01-01 20:00:00"

Les 3 versions du fichier, example1.linq, example2.linq et example3.linq:

Example1.linq:

<Query Kind="Program" />

void Main()
{
    Function1();
    Function2();
}

public void Function1()
{
    Debug.WriteLine("Function 1");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}

Example2.linq:

<Query Kind="Program" />

void Main()
{
    Function1();
    Function2();
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}

public void Function1()
{
    Debug.WriteLine("Function 1");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

Example3.linq:

<Query Kind="Program" />

void Main()
{
    Function1();
    Function2();
}

public void Function1()
{
    Debug.WriteLine("Function 1b");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}
Était-ce utile?

La solution

Eh bien, vous touchez actuellement l'un de la limitation de, essentiellement, TOUT VCS courant (DVCS ou non, il n'a pas d'importance).

La chose est que VCS sont en langue agnostique, la base de leur algorithme de fusion est une diff textuelle. Cela signifie qu'ils sont à la recherche de ce changement et ce qui est le lié contexte .
L'important est le contexte ici. Il n'y a rien de plus que quelques lignes avant et après les modifications apportées.

Cela signifie qu'ils sont vraiment mal à traiter avec le code de réorganisation à l'intérieur d'un même fichier, parce que vous êtes vissant essentiellement tout le contexte dans lequel ils peuvent compter.
En règle générale, dans votre exemple, en changeant les deux fonctions, non seulement complètement inversé le contexte entre les deux changesets, mais pire encore, en ayant pas de lignes supplémentaires après la dernière fonction, vous avez réduit le contexte implicite du dernier changement, ce qui diminue les chances qu'un algorithme de fusion a pu comprendre ce que vous avez vraiment fait.

Je sais actuellement seulement un outil de comparaison, à partir msft, XML, qui essaie de faire face à la sémantique de votre changement et non seulement sa représentation textuelle.
Je sais aussi que les gars de PlasticSCM tentent de mettre en œuvre cette fonctionnalité pour certaines langues grand public, mais il est vraiment un endroit où il y a place à l'amélioration.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top