Cosa rende alcuni sistemi di controllo delle versioni migliori nella fusione?

Ho sentito dire che molti dei VCS distribuiti (git, mercurial, ecc.) Sono migliori di quelli tradizionali come Subversion. Cosa significa questo? Che tipo di cose fanno per rendere la fusione migliore? Queste cose potrebbero essere fatte in un VCS tradizionale?

Domanda bonus: il livello di tracciamento delle missioni di SVN 1.5 è a livello del campo di gioco?

La maggior parte delle risposte sembra essere su Subversion, quindi qui ne hai una su Git (e altri DVCS).

Nel sistema di controllo della versione distribuita quando unisci un ramo in un altro, crei un nuovo merge commit , che ricorda come hai risolto un’unione e ricorda tutti i genitori di un’unione . Questa informazione era semplicemente carente in Subversion precedente alla versione 1.5; per questo dovevi usare strumenti aggiuntivi come SVK o svnmerge. Questa informazione è molto importante quando si effettua un’unione ripetuta.

Grazie a queste informazioni, i sistemi di controllo della versione distribuiti (DVCS) possono trovare automaticamente antenati comuni (o antenati comuni), noti anche come base di unione, per due rami qualsiasi. Dai un’occhiata al grafico ASCII delle revisioni qui sotto (spero che non sia stato stravolto in modo orribile),

 --- O --- --- * * ---- M --- * --- * --- 1
      \ /
        \ * --- --- A / - * ---- 2

Se vogliamo unire il ramo ‘2’ al ramo ‘1’, l’antenato comune che vorremmo usare per generare l’unione sarebbe la versione (commit) segnata ‘A’. Tuttavia, se il sistema di controllo della versione non registrava informazioni sui genitori di unione (‘M’ è l’unione precedente delle stesse diramazioni), non sarebbe in grado di trovare che è commit ‘A’ e troverà commit ‘O’ come antenato comune (merge base) invece … che ripeterebbe già le modifiche incluse e comporterebbe un conflitto di fusione di grandi dimensioni.

Il sistema di controllo delle versioni distribuito doveva farlo bene, cioè dovevano fare unire molto facilmente (senza dover marcare / etichettare unire i genitori e fornire informazioni di unione manualmente), perché il modo per ottenere qualcun altro per ottenere il codice nel progetto non doveva concedere l’accesso al commit, ma estrarre dal proprio repository: ottenere il commit dall’altro repository ed eseguire un’unione.

È ansible trovare informazioni sulla fusione in Subversion 1.5. in Subversion 1.5 Note di rilascio . Problemi noti: sono necessarie diverse (!) Opzioni per unire il ramo nel tronco piuttosto che unire il tronco al ramo, ovvero. non tutti i rami sono uguali (nei sistemi di controllo delle versioni distribuite sono [di solito] tecnicamente equivalenti).

Le funzionalità di unione di SVN sono decenti e gli scenari di fusione semplici funzionano bene, ad esempio release branch e trunk, dove il trunk tiene traccia dei commit sull’RB.

Gli scenari più complessi si complicano velocemente. Ad esempio, iniziamo con un ramo stable ( stable ) e un trunk .

Vuoi provare una nuova funzione e preferisci basarla su stable poichè è, beh, più stabile del trunk , ma vuoi che tutti i tuoi commit vengano propagati al trunk , mentre il resto degli sviluppatori sta ancora sistemando le cose in cose stable e in via di sviluppo sul trunk .

Quindi crei un ramo demo e il grafico risultante dalla fusione è il seguente:

  • stable -> demo -> trunk (tu)
  • stable -> trunk (altri sviluppatori)

Ma cosa succede quando unisci le modifiche da stable a demo , quindi unisci demo a trunk , mentre per tutto il tempo anche gli altri sviluppatori si stanno unendo nel trunk ? SVN si confonde con la fusione da stable viene unita due volte nel trunk .

Ci sono modi per aggirare questo problema, ma con git / Bazaar / Mercurial questo semplicemente non accade: si rendono conto se i commit sono già stati uniti perché identificano ogni commit attraverso i percorsi di fusione necessari.

Il tracciamento di unione in 1.5 è migliore di nessun tracciamento unione, ma è ancora molto un processo manuale. Mi piace il modo in cui registra quali rev sono e non sono unite, ma non è affatto perfetto.

Unisci ha una bella finestra di dialogo in 1.5. Puoi scegliere quali revisioni desideri unire singolarmente o l’intero ramo. Quindi si triggers l’unione che si verifica localmente (e prende FOREVER) quando quindi si fornisce una serie di file da leggere. È necessario controllare logicamente ciascun file per il comportamento corretto (preferibilmente eseguendo i test unitari sui file) e se si hanno conflitti, è necessario risolverli. Una volta che sei felice, fai un commit del tuo cambiamento e a quel punto il ramo è considerato unificato.

Se lo fai in modo frammentario, SVN ricorderà ciò che hai detto in precedenza che hai unito, consentendoti di unire. Ho trovato il processo e il risultato di alcune delle unioni per essere strani a dir poco però …

Questi sistemi di controllo delle versioni possono fare meglio perché hanno più informazioni.

SVN pre-1.5, insieme alla maggior parte dei VCS prima dell’ultima generazione, in realtà non ricorda che hai unito due commit ovunque. Ricorda che i due rami condividono un antenato comune molto indietro quando si diramano per la prima volta, ma non sa di più recenti fusioni che potrebbero essere utilizzate come base comune.

Comunque non so nulla di SVN post 1.5, quindi forse hanno migliorato questo.

Risposta frettolosa: perché alcuni linguaggi di programmazione sono migliori di testo / matematica rispetto ad altri?

Vera risposta: perché devono essere. i VCS distribuiti fanno molto di là che si uniscono in un punto in cui nessuno degli autori del codice in conflitto può modificare manualmente l’unione perché l’unione viene eseguita da una terza parte. Di conseguenza, lo strumento di unione deve farlo correttamente la maggior parte del tempo.

In contratto con SVN stai facendo qualcosa di funky (e sbagliato?) Se finisci per fondere qualcosa in cui non hai scritto una parte o l’altra.

La maggior parte dei VCS può sostituire l’unione con qualsiasi cosa tu chieda loro di usare, quindi non c’è (in teoria) nulla che impedisca a SVN di utilizzare i motori di fusione GIT / mercurial. YMMV