Da quanto ho capito, SVN è 'facile da ramificare. Difficile da unire '. Perché? C'è differenza nel modo in cui si fondono?
Da quanto ho capito, SVN è 'facile da ramificare. Difficile da unire '. Perché? C'è differenza nel modo in cui si fondono?
Risposte:
Si prega di consultare la mia risposta Stack Overflow per una situazione molto concreta in cui Mercurial (e Git) si fondono senza problemi e in cui Subversion presenta un falso conflitto. La situazione è un semplice refactoring eseguito su un ramo in cui si rinominano alcuni file.
Per quanto riguarda la risposta di tdammer, ci sono una serie di equivoci:
Subversion, Mercurial e Git tengono traccia delle istantanee del progetto a livello di repository. Chiamarli versioni , revisioni o changeset non fa differenza. Sono tutte istantanee logicamente atomiche di un insieme di file.
La dimensione dei tuoi commit non fa differenza quando si tratta di unire. Tutti e tre i sistemi si fondono con l'algoritmo di fusione standard a tre vie e gli input per tale algoritmo sono
Non importa come sono state create le due versioni di diramazione. Puoi aver usato 1000 piccoli commit dalla versione precedente o puoi aver usato 1 commit. Tutto ciò che conta è la versione finale dei file. (Sì, questo è sorprendente! Sì, molte guide DVCS sbagliano terribilmente.)
Solleva anche alcuni punti positivi sulle differenze:
Subversion ha qualche "voodoo", dove è possibile unire da /trunk
in, diciamo, /branches/foo
. Mercurial e Git non usano questo modello - i rami sono invece modellati direttamente nella storia. La storia diventa quindi un grafico aciclico diretto invece di essere lineare. Questo è un modello molto più semplice di quello utilizzato da Subversion e questo elimina una serie di casi angolari.
Puoi facilmente ritardare un'unione o persino consentire a qualcun altro di gestirla. Se hg merge
ti dà un sacco di conflitti, puoi chiedere al tuo collega di farlo hg pull
da te e poi ha lo stesso identico stato. Quindi può hg merge
e forse è più bravo a risolvere i conflitti di te.
Questo è molto difficile con Subversion in cui è necessario aggiornare prima di poter eseguire il commit. Non puoi semplicemente ignorare le modifiche sul server e continuare a impegnarti nel tuo ramo anonimo. In generale, Subversion ti costringe a giocare con una sporca copia di lavoro quando lo fai svn update
. Questo è un po 'rischioso poiché non hai archiviato le modifiche in modo sicuro. Git e Mercurial ti consentono di eseguire prima il commit, quindi di aggiornare e unire, se necessario.
La vera ragione per cui Git e Mercurial sono più bravi a fondersi rispetto a Subversion è una questione di implementazione. Ci sono conflitti di ridenominazione che Subversion semplicemente non può gestire, anche se è chiaro quale sia la risposta corretta. Mercurial e Git gestiscono quelli facilmente. Ma non vi è alcun motivo per cui Subversion non sia in grado di gestirli - l'essere centralizzato non è certamente il motivo.
trunk
in SVN. Con un DVCS puoi impegnarti senza condividere, ma in SVN svn commit
influenzerai direttamente gli altri che lavorano nello stesso ramo. Anche se noi due lavoriamo in una filiale in SVN, non posso impegnare il mio lavoro senza dovermi fondere immediatamente con il tuo lavoro. Ciò rende i commit un po 'spaventosi - che è una proprietà spaventosa per un sistema di controllo versione! :-)
Il problema principale risiede nel modo in cui questi sistemi rappresentano una struttura di directory con versione.
Il concetto di base di Subversion attorno al quale ruota l'intero sistema è quello di una versione (o, in svn lingo, "revisione"): un'istantanea di un file a un certo punto. Fintanto che la cronologia è perfettamente lineare, tutto va bene, ma se è necessario unire le modifiche da due linee di sviluppo indipendenti, svn deve confrontare le versioni correnti di entrambi e quindi fare un confronto a tre vie tra l'ultima versione condivisa e le due versioni di testa. Le linee che appaiono cambiate in una delle teste, ma non nell'altra, possono essere facilmente risolte; le linee che si discostano esattamente allo stesso modo in entrambe le teste sono più difficili, ma di solito realizzabili; linee che si discostano in modi diversi sono ciò che fa dire a svn "Non riesco a capirlo, umano, per favore risolvilo per me."
Al contrario, git e mercurial tengono traccia dei changeset piuttosto che delle versioni. L'intero repository è un albero di changeset, ognuno a seconda di un parent, in cui un changeset parent può avere un numero qualsiasi di figli e la radice dell'albero rappresenta una directory vuota. In altre parole, git / hg dice "prima non avevo niente, poi è stata applicata questa patch, poi quella patch, ecc.". Quando è necessario unire due linee di sviluppo, git / hg non solo conosce l'aspetto di ogni testa e l'aspetto dell'ultima versione comune, ma sa anche come è avvenuta la transizione, consentendo una fusione molto più intelligente.
Un'altra cosa che semplifica l'unione in un DVCS è una conseguenza indiretta della separazione dei concetti di commit e pushe di consentire qualsiasi tipo di fusione incrociata tra due cloni dello stesso repository in qualsiasi momento. Con svn, le persone tendono a eseguire il commit di grandi changeset con modifiche spesso non correlate, poiché un commit è anche un aggiornamento del repository centrale che interessa tutti gli altri membri del team; se commetti una versione non funzionante, tutti si arrabbieranno con te. Poiché la maggior parte delle configurazioni coinvolge un server svn in rete, il commit comporta anche il pumping dei dati sulla rete, il che significa che il commit introduce un notevole ritardo nel flusso di lavoro (specialmente quando la tua copia di lavoro è obsoleta e devi prima estrarla). Con git e mercurial, il commit avviene localmente e, poiché entrambi sono molto efficienti nella gestione dei filesystem locali, di solito termina all'istante. Di conseguenza, le persone (una volta abituate) commettono piccole modifiche incrementali e, quando funziona, spingere una dozzina circa si impegna in una volta sola. Quindi, quando arriva il momento della fusione, SCM ha molte più informazioni dettagliate da seguire e può fare un lavoro migliore risolvendo i conflitti in modo sicuro e automatico.
E poi ci sono i bei dettagli che rendono le cose ancora più facili:
hg mv
o hg addremove --similarity...
), mentre Git usa l'euristica, ma entrambi gestiscono le ridenominazioni . Posso avere un conflitto tra alberi anche con 1 differenza di stringa nei file uniti! Devi riapprendere alcuni aspetti di Subversion, scusa.
rename a b
come copy a b; remove a
ed entrambi lo fanno in un commit atomico. La differenza nel comportamento di unione deriva dalla diversa gestione dei casi angolari e da Subversion che consente più fusioni rispetto a Mercurial e Git. Infine, Git rileva i nomi durante l'unione e il tempo di log - stiamo pensando di aggiungere anche questo in Mercurial.