2011-10-18 14 views
10

Nota: Non sto cercando di riavviare l'argomento se Mercurial o Git sono migliori, ho solo una domanda tecnica che io, come utente Mercurial, non capisco. Inoltre, non sono sicuro se SO sia il posto giusto per porre una simile domanda, ma è la relativa programmazione è.Perché Git non memorizza il nome del ramo come parte del commit?

Ci sono state molte discussioni su come i due sistemi di controllo di versione Git e Mercurial differiscono l'uno dall'altro dal punto di vista dell'utente (ad esempio e http://felipec.wordpress.com/2011/01/16/mercurial-vs-git-its-all-in-the-branches/) e la principale differenza è la gestione dei rami. Ho letto molte di queste discussioni, ma continuo a pormi questa domanda:

Perché Git non memorizza il nome del ramo come parte del commit?

Non vedo davvero una buona ragione per non farlo; significa che i dati non possono semplicemente svanire perché non vi è alcun riferimento (tag, ramo o altro) che vi si attesti.

Vedo archiviare il ramo nel commit come un grande vantaggio per Mercurial, perché ciò rende più difficile la perdita di dati.

Il punto principale della folla Git in favore del modello di branching di Git, che è possibile semplicemente eliminare i rami, non impedisce a Git di memorizzare il nome del ramo come parte di ogni commit: Se i commit di un ramo sono cancellati , così come i riferimenti a quel ramo. Inoltre, non interferirà con l'argomento "branching a buon mercato": le filiali non saranno più costose da gestire. E non penso che lo storage aggiuntivo necessario dovrebbe essere motivo di preoccupazione: sono solo un paio di byte per commit.

+0

Sono confuso, quando perdi dati al momento? – Useless

+1

Non ce l'ho, ma è possibile: per quanto ho capito, una testina staccata sarà raccolta dalla spazzatura quando non si punta un tag o un ramo. –

+1

@danielkullmann: raccolta dei rifiuti, sì, ma non prima di almeno due settimane: http://stackoverflow.com/questions/5772192/git-how-can-i-reconcile-detached-head-with-master-origin – VonC

risposta

14

Uno dei fonte definitiva su rami per Git e Mercurial è la domanda SO:

"Git and Mercurial - Compare and Contrast"

Nei riferimenti Git (filiali, filiali remote-tracking e tag) risiedono al di fuori DAG di impegna.

(che permette di gestire spazi dei nomi diversi per quanto riguarda i rami, per le filiali locali e remoti)

Hai un concetto simile con Mercurial con rami segnalibro (che può essere spinto/tirato).

Nota che in Git, i dati non "svaniscono" perché non c'è riferimento: hai ancora il reflog per recuperare quei commit senza referenze.

Perché Git non memorizza il nome del ramo come parte del commit?
Io non vedo una buona ragione per non fare che

L'idea è quella di separare ciò che è cambiato (i commit) dal perché m cioè dal contesto del cambiamento (il nome del ramo).
Poiché è possibile un ramo fast-forward merge, il commit da un ramo può essere parte di un altro in qualsiasi momento.

Ecco perché Jakub Narębski in discussione il progetto di Mercurial "rami con nome" (con nomi filiali incorporate nei metadati di modifiche), in particolare con un globale namespace , non molto adatto per un sistema di controllo di versione distribuito .

Si crea un ramo per isolare uno sforzo di sviluppo (vedere "When should you branch?"), ma con un DVCS, tale sforzo di sviluppo (l'insieme di commit) deve essere pubblicato sotto qualsiasi nome di ramo. Quale contesto locale (nome della filiale) è stato definito potrebbe non essere valido una volta pubblicato su un altro repository di Git.

+0

+1 Grazie, è stato estremamente illuminante! –

+0

Trovo preoccupante quando la gente dice "non temere, che non svanirà, è nel riflusso". Il reflog è temporaneo. Svanisce. Dopo che è scomparso, come si arriva alle parti non referenziate del grafico di commit? –

+0

@DonHatch svanisce? Solo dopo 90 giorni per impostazione predefinita. Se hai davvero bisogno di queste informazioni dopo 90 giorni, suppongo che tu possa ottenerle da un backup del tuo repository. – VonC

8

Il modello di funzionamento di base di Mercurial è molto semplice, rami anonimi che formano un grafico aciclico diretto (DAG), e in quanto tali i nomi delle filiali hanno poca importanza e si avranno a che fare molto meno. I branch nominati sono principalmente per scopi organizzativi (release branch, ecc.), Per i quali direi che uno spazio dei nomi globale ha più senso o almeno è meno discutibile.

Git ha un modello di ramificazione più complicato e gestito rispetto a Mercurial, dove anche le tue modifiche locali sono trattate come un ramo con nome separato, e di fronte a una tale pletora di rami nominati devi introdurre spazi dei nomi per gestirli. Per la stessa ragione, Git ha il concetto di fusioni veloci, qualcosa che non si applica a Mercurial perché in primo luogo non avresti creato un ramo separato.

Entrambi questi concetti aggiungono complessità extra e allo stesso tempo bloccano funzionalità utili come la memorizzazione del nome del ramo insieme al commit. Questo perché non è possibile archiviare i rami con namespace senza spazio globale e git non ne ha.

Il difetto nell'argomento per gli spazi dei nomi a cui VonC fa riferimento sopra è che presuppone che ci sia un problema se entrambi creiamo un ramo chiamato 'x'. Non c'è, proprio come non c'è alcun problema quando si crea un ramo con nome, lo si fonde e successivamente ne viene creato un altro con lo stesso nome. Un nome ben scelto descrive ciò che il ramo fa indipendentemente da chi sia l'autore, e se hai bisogno di differenziare di più l'autore è memorizzato insieme al nome del ramo, e tutto ciò è permanente.

Penso che sia stata una buona decisione del progetto Mercurial memorizzare il nome del ramo insieme al commit. Proprio come il messaggio di commit e l'autore, il contesto del lavoro (il ramo) è meta-informazione importante e utile. Rende molto più facile vedere il flusso dei changeset quando ispeziona la cronologia, perché puoi vedere il contesto in cui sono stati creati. In Git ho sperimentato che senza queste informazioni, la storia diventa rapidamente un pasticcio di linee umide che è difficile da fare teste o code di Penso che avere questo vale il compromesso di non avere spazio dei nomi.

Penso che si possa dire che la differenza filosofica è che Mercurial tratta i rami denominati come metadati permanenti che forniscono alcune informazioni aggiuntive su una linea di commit, mentre per i rami Git c'è un sistema di gestione senza versioni per gli sviluppatori in cima a il DAG. Mercurial ha anche questi sotto il nome di "segnalibri" (a partire dalla versione 1.8 una caratteristica di base), ma sono davvero più uno strumento di monitoraggio e trattati come etichette anziché rami.

+0

Grazie, molto interessante! –

Problemi correlati