Perché ramificare e fondere è più facile in Mercurial che in Subversion?


92

Gestire più unioni su rami in Subversion o CVS è solo una di quelle cose che devono essere sperimentate. È straordinariamente più facile tenere traccia di branch e unioni in Mercurial (e probabilmente in qualsiasi altro sistema distribuito) ma non so perché. Qualcun altro lo sa?

La mia domanda nasce dal fatto che con Mercurial puoi adottare una pratica di lavoro simile a quella del repository centrale di Subversions / CVS e tutto funzionerà perfettamente. Puoi fare più fusioni sullo stesso ramo e non avrai bisogno di frammenti di carta infiniti con numeri di commit e nomi di tag.

So che l'ultima versione di Subversion ha la capacità di tenere traccia delle fusioni in rami in modo da non ottenere lo stesso grado di seccatura, ma è stato uno sviluppo enorme e importante da parte loro e ancora non fa tutto ciò che farebbe il team di sviluppo piace fare.

Deve esserci una differenza fondamentale nel modo in cui funziona tutto.

Risposte:


115

In Subversion (e CVS), il repository è prima di tutto. In git e mercurial non esiste realmente il concetto di repository allo stesso modo; qui i cambiamenti sono il tema centrale.

+1

La seccatura in CVS / SVN deriva dal fatto che questi sistemi non ricordano la genitorialità dei cambiamenti. In Git e Mercurial, non solo un commit può avere più figli, ma può anche avere più genitori!

Ciò può essere facilmente osservato utilizzando uno degli strumenti grafici, gitko hg view. Nell'esempio seguente, il ramo n. 2 è stato biforcato dal n. 1 al commit A e da allora è stato unito una volta (in M, unito al commit B):

o---A---o---B---o---C         (branch #1)
     \       \
      o---o---M---X---?       (branch #2)

Nota come A e B hanno due figli, mentre M ha due genitori . Queste relazioni vengono registrate nel repository. Supponiamo che il manutentore del ramo n. 2 ora voglia unire le ultime modifiche dal ramo n. 1, può emettere un comando come:

$ git merge branch-1

e lo strumento saprà automaticamente che la base è B - perché è stata registrata nel commit M, un antenato della punta di # 2 - e che deve unire tutto ciò che è accaduto tra B e C. CVS non registra questa informazione , né SVN prima della versione 1.5. In questi sistemi, il grafico sarebbe simile a:

o---A---o---B---o---C         (branch #1)
     \    
      o---o---M---X---?       (branch #2)

dove M è solo un gigantesco commit "schiacciato" di tutto ciò che è accaduto tra A e B, applicato sopra M. Nota che dopo che l'azione è stata compiuta, non è rimasta traccia (tranne potenzialmente nei commenti leggibili dall'uomo) di dove M ha avuto origine da, né da quanti commit sono stati collassati insieme, rendendo la storia molto più impenetrabile.

Peggio ancora, effettuare una seconda unione diventa un incubo: si deve capire quale base fusione era al momento della prima unione (e uno ha per sapere che c'è stata una stampa in primo luogo!), Poi presente che informazioni allo strumento in modo che non tenti di riprodurre A..B sopra M. Tutto questo è abbastanza difficile quando si lavora in stretta collaborazione, ma è semplicemente impossibile in un ambiente distribuito.

Un problema (correlato) è che non c'è modo di rispondere alla domanda: "X contiene B?" dove B è una correzione di bug potenzialmente importante. Quindi, perché non registrare queste informazioni nel commit, dato che è noto al momento della fusione!

P.-S. - Non ho esperienza con le capacità di registrazione di unione di SVN 1.5+, ma il flusso di lavoro sembra essere molto più artificioso rispetto ai sistemi distribuiti. Se è davvero così, probabilmente è perché - come menzionato nel commento sopra - l'attenzione è rivolta all'organizzazione del repository piuttosto che alle modifiche stesse.


6
SVN 1.5+ metterebbe effettivamente una proprietà SVN nel commit di unione M che elenca i commit uniti che contiene, in altre parole AB. Quindi hai le stesse informazioni.
Simon D

Tipo. Tecnicamente, il monitoraggio della fusione di SVN è simile a ciò che Git chiama "selezione delle ciliegie", con una magia aggiuntiva per renderlo più facile per l'utente; è semanticamente diverso da quello che fanno Git, Hg e Bzr quando si fondono. Immagino che non faccia molta differenza nella pratica finché non ti interessa il DAG ( eagain.net/articles/git-for-computer-scientists ).
Damien Diederen

2
Guai che non ci sia il pulsante +100. Grazie.
Charlie Flowers

Presumo che la funzionalità SVN 1.5 di cui parli sia l'uso della svn:mergeinfoproprietà?
MatrixFrog

@ MatrixFrog: Sì, è proprio quello che svn:mergeinfofa.
sleske

12

Perché Subversion (almeno la versione 1.4 e precedenti) non tiene traccia di ciò che è stato unito. Per Subversion, l'unione è fondamentalmente la stessa di qualsiasi commit mentre su altri controlli di versione come Git, ciò che è stato unito viene ricordato.


7

Non toccato da nessuna delle risposte già fornite, Hg ha offerto capacità di unione superiori perché utilizza più informazioni durante l'unione delle modifiche ( hginit.com ):

Ad esempio, se modifico un po 'una funzione e poi la sposto da qualche altra parte, Subversion non ricorda davvero quei passaggi, quindi quando arriva il momento di unire, potrebbe pensare che una nuova funzione sia appena apparsa di punto in bianco . Mentre Mercurial ricorderà queste cose separatamente: funzione modificata, funzione spostata, il che significa che se hai cambiato anche un po 'quella funzione, è molto più probabile che Mercurial unirà con successo le nostre modifiche.

Naturalmente, anche ricordare ciò che è stato unito per ultimo (il punto affrontato dalla maggior parte delle risposte fornite qui) è un'enorme vittoria.

Entrambi i miglioramenti, tuttavia, sono discutibili poiché subversion 1.5+ memorizza ulteriori informazioni di unione sotto forma di proprietà di sovversione: queste informazioni disponibili, non c'è motivo ovvio per cui subversion merge non possa implementare l'unione con successo come Hg o Git. Non so se lo fa, però, ma sembra certamente che gli sviluppatori di Subversion siano sulla buona strada per aggirare questo problema.


4

Suppongo che questo potrebbe essere parzialmente dovuto al fatto che Subversion ha l'idea di un server centrale insieme a una cronologia assoluta delle revisioni. Mercurial è veramente distribuito e non ha alcun riferimento a una linea temporale assoluta. Ciò consente ai progetti Mercurial di formare gerarchie di rami più complicate per l'aggiunta di funzionalità e cicli di test per sottoprogetto, tuttavia i team ora devono mantenere molto più attivamente il controllo delle unioni per rimanere aggiornati poiché non possono semplicemente aggiornare e farcela .


3

In Subversion (e CVS), il repository è prima di tutto. In git e mercurial non esiste realmente il concetto di repository allo stesso modo; qui i cambiamenti sono il tema centrale.

Non ho pensato molto a come implementarlo, ma la mia impressione (basata su un'amara esperienza e molte letture) è che questa differenza è ciò che rende la fusione e la ramificazione molto più semplice nei sistemi non basati su repository.


1

Ho solo esperienza con Subversion ma posso dirti che la schermata di unione in TortoiseSVN è orribilmente complicata. Fortunatamente includono un pulsante di marcia a secco in modo che tu possa vedere se lo stai facendo bene. La complicazione sta nella configurazione di ciò che vuoi unire a dove. Una volta che hai impostato la configurazione per l'unione, l'unione generalmente funziona correttamente. Quindi è necessario risolvere tutti i conflitti e quindi eseguire il commit della copia di lavoro unita nel repository.

Se Mercurial può rendere più semplice la configurazione della fusione, allora posso dire che renderebbe la fusione del 100% più semplice di Subversion.

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.