Conseguenze dell'utilizzo dell'innesto in Mercurial


98

Recentemente ci sono state diverse domande sul saltare le modifiche durante la manutenzione dei rami di rilascio in Mercurial. Per esempio:

Da quando è stato introdotto nella 2.0, mi sono chiesto se utilizzare graftper evitare questo problema. Dato un albero di revisione come questo:

A---B---C---D---E---F---G---H---I---J

Supponiamo di dover creare un ramo di rilascio che salti la modifica di Evil E.

hg update -r D
hg graft "F::J"

dandoci:

A---B---C---D---E---F---G---H---I---J
             \
              --F'--G'--H'--I'--J'
  • Q1: cosa è appena successo qui? Posso capire che transplantavrebbe generato patch F::Je poi le avrebbe applicate D, ma graftsi dice che usi l'unione a 3 vie piuttosto che le patch. Allora ....... come funziona? Perché è meglio?

Diciamo che ora lo aggiusto Ee lo unisco nel mio ramo di rilascio.

                  --E2-----------------
                 /                     \
A---B---C---D---E---F---G---H---I---J---M1
             \                            \
              --F'--G'--H'--I'--J'---------M2--

M1 è una fusione lineare; niente di speciale lì. M2 sta unendo rami che hanno modifiche "uguali" (o almeno equivalenti).

  • Q2: È questo merge solo una normale fusione a 3 vie utilizzando D, J'e M1?
  • D3: Mercurial ha memorizzato / utilizzato informazioni aggiuntive sull'operazione di innesto per facilitare l'unione?

E infine...

  • D4: Quali sono i potenziali problemi con un flusso come questo?

Risposte:


119

Quando esegui l'aggiornamento De l'innesto F::J, Mercurial esegue una serie di unioni. Inizierà con questa unione:

M = three_way_merge(local=D, other=F, base=E)

Se scriviamo +dper il delta tra gli stati Ce D, allora iniziamo con:

        +d     +e     +f
---- C ---- D ---- E ---- F ----

Ruota il grafico di 90 gradi in senso orario e l'unione a tre vie sopra ha questo aspetto:

    -e  
  .---- D
 /
E
 \
  '---- F
    +f

Cioè, fingiamo di aver iniziato Ee applicato l'opposto di -earrivare a D. Penso come la patch inversa di +e. A partire dal Esiamo anche andati a dichiarare Fcon il delta normale +f. Non c'è niente di strano - abbiamo tutti gli stati ( D, E, e F) nel repository già. Quindi visto in questo modo, è chiaro che possiamo unire De F.

La fusione è una questione di "completare il diamante". Quindi troviamo un nuovo stato Mche è un mix di De Fe dove la differenza da Da Mè simile a +fe la differenza da Fa Mè simile a -e. Assomiglia a questo:

    -e     +f'
  .---- D ----.
 /             \
E               M
 \             /
  '---- F ----'
    +f     -e'

Il +fdelta è diventato +f'e il -edelta è diventato -e'. Questo è solo un normale merge a tre vie, ma l'effetto è interessante: abbiamo applicato Fsul Dposto di E!

Dopo l'unione, il secondo genitore di Mto Fviene eliminato:

    -e     +f'
  .---- D ----.
 /             \
E               M
 \
  '---- F
    +f

Per ribadire: abbiamo copiato l '"effetto" di Fsu D, ovvero abbiamo trovato una delta ( +f') applicata per Ddare lo stesso effetto di quando è +fstata applicata E. Possiamo raddrizzare un po 'il grafico per ottenere:

       +f'
--- D ---- M
     \
      '---- E ---- F
        +e     +f

Il risultato è che Fviene innestato Dutilizzando l'intera macchina a tre vie.

  • Q1: cosa è appena successo qui? Allora ....... come funziona? Perché è meglio?

    A1: Usare le fusioni è meglio delle patch poiché il meccanismo di unione tiene conto di cose come le ridenominazioni.

  • D2: Questa unione è solo una normale unione a 3 vie usando D, J 'e M1?

    A2: Sì, l'innesto non altera la topologia del grafo.

  • D3: Mercurial ha memorizzato / utilizzato informazioni aggiuntive sull'operazione di innesto per facilitare l'unione?

    A3: No.

  • D4: Quali sono i potenziali problemi con un flusso come questo?

    A4: Dal punto di vista della fusione dovrebbe funzionare bene. Duplicherà un po 'di storia che potrebbe creare confusione per le persone.


4
Ottima domanda, ottima risposta :). +1 a entrambi!
Laurens Holst

Grazie Martin. È un pensiero piuttosto stravagante da parte di chiunque sia arrivato con questo. Ho l'idea, ma ho bisogno di elaborare il caso generale. Immagino che valga indipendentemente dal percorso tra i nodi da / verso cui stai innestando?
Paul S

3
@PaulS: Penso che tutto ciò che devi sapere è che l'innesto può copiare i changeset in giro in un modo più robusto di quanto possa fare il trapianto. Robusto nel senso che le ridenominazioni vengono gestite e che puoi risolvere i conflitti in uno strumento di unione. I dettagli sono nelle strane fusioni che fa, ma si spera che non sia essenziale da capire per l'uso quotidiano dell'innesto! :-)
Martin Geisler

3
No, ma sono un idiota per cercare di capire cose di cui non ho bisogno ;-) Ho lavorato su un esempio più generale usando comunque il tuo come base.
Paul S

@PaulS Se è così, ho quasi paura di dirtelo ... ma puoi cercare Darcs e la sua teoria delle patch. Il trucco sopra relativo alla rotazione del grafico di 90 gradi mi ricorda molto come si parla di patch di pendolarismo durante l'unione. Roba piuttosto pelosa :-)
Martin Geisler

6

Q1: aiuta quando ci sono conflitti. Puoi quindi usare il tuo solito strumento di unione (per me sono i marcatori di conflitto in linea, che modifico con la modalità smerge di Emacs).

D2: È una normale unione.

Q3: No.

Q4: Penso che sia brutto avere due rami quasi identici.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.