2014-11-05 6 views
5

L'immagine qui sotto è presa da SourceTree. Ho creato un semplice repository git con alcuni commit in esso. Per ogni commit, il commento dice quale ramo ero su quando ho fatto il commit.Perché i diagrammi di git branching non tracciano i rami "correttamente"?

An arguably suboptimal commit diagram

Come si può vedere, il diagramma ad albero è (forse) non ottimali in quanto i commit al master non sono tutti dello stesso colore, né sono in una sola corsia. Perchè è questo?

(I diagrammi albero disegnato da GitHub e BitBucket sembrano soffrire di problemi simili, quindi non è solo SourceTree.)

Ovviamente non importa molto in questo semplice esempio, ma in alcuni dei miei progetti che usa una variante di git-flow, ed è spesso difficile tenere traccia di ognuna delle "nuotate" di git-flow quando osservi il diagramma ad albero. In parte, questo è dovuto al fatto che il diagramma ad albero non mantiene nel tempo ogni corsia da bagno dello stesso colore.

Il mio sospetto è che il diagramma ad albero sia (probabilmente) subottimale perché il repository git in realtà non contiene informazioni sufficienti per disegnare il diagramma ad albero nel modo in cui lo voglio. In particolare, quando due commit sono figli di un commit comune (es. Quando si dirama), git non sa se il commit padre è "sullo stesso ramo" come figlio 1 o figlio 2. Oppure, in un altro modo, non lo fa Non so quale bambino fosse il ramo e quale fosse la continuazione del tronco. Ho ragione?

+0

I commit per dominare _are_ tutto in un'unica corsia: la corsia che passa da blu a viola al commit 94f458e. Per quanto riguarda il motivo per cui sono di un colore diverso, questa è una domanda per il codice sorgente più di Stack Overflow. Forse lo sviluppatore ha scelto di considerare il percorso dell'ultimo commit cronologicamente recente come il percorso di liberazione? Invia una richiesta di funzionalità per modificarla in base al nome del percorso. –

+0

Quando ho detto "corsia", intendevo come "colonna". E quello che vorrei sarebbe se tutti i commit to master fossero in una singola colonna e quelli da rilasciare fossero in un'altra colonna. Voglio dire, se hai dato a un umano il DAG, i puntatori di ramo e le colonne di commit, probabilmente non disegnerebbero il diagramma ad albero come sopra disegnato. –

+0

Mentre è vero, git non * richiede * agli utenti di fornire informazioni sufficienti per disegnare il dag con swimlanes corretti, un disegno migliore può essere dedotto in molti casi usando i messaggi di commit come suggerimenti. Ad esempio, i messaggi di unione in genere iniziano "Unisci ramo" B "in A"; in questi casi, è chiaro quali dovrebbero essere i nomi dei due rami di origine per i piani per le spiagge. Gli utenti possono facilmente aggiungere ancora più chiarezza; per esempio, ogni volta che creo un ramo, inserisco un commit vuoto iniziale in "Crea ramo" B "da" A "". I programmi di disegno grafico potrebbero fare un * molto * migliore lavoro nel prendere questi suggerimenti. –

risposta

2

Come hanno alluso altre risposte, questa è semplicemente la natura di Git: Un commit git non contiene alcuna informazione su quale ramo era attivo dall'utente al momento del commit. (E questa informazione non può essere dedotta in modo affidabile dalle informazioni che git mantiene, che ovviamente include il DAG.) Questa è stata una scelta progettuale fatta dagli autori di git. Mercuriale, al contrario, fa memorizzare un nome di ramo con ogni commit. I sostenitori di Git sostengono che questa è una cosa negativa, perché scoraggia la creazione di rami, eventualmente temporanei, per provare le cose, e inoltre le collisioni dei nomi delle filiali possono facilmente sorgere. Vedi, ad esempio, The Differences Between Mercurial and Git.

I sostenitori di Mercurial sostengono che memorizzare il nome del ramo con ogni commit è una buona cosa, perché rende più facile mantenere una cronologia interpretabile. Quel Mercurial memorizza un nome di ramo con ogni commit sembra essere il motivo principale per cui l'autore di Why I Like Mercurial More Than Git preferisce Mercurial su Git.

+0

Mercurial memorizza il nome del ramo in ogni commit, se si utilizzano i rami denominati di Mercurial. In alternativa si può lavorare con i segnalibri di Mercurial, se si desidera un comportamento simile a git. –

3

In git "rami" sono implementati come puntatore a un changeset.

Significa che un particolare changeset può "appartenere" a più rami contemporaneamente.

Detto questo, viene risolto in runtime e dopo aver eliminato un ramo (o modificato il grafico in qualsiasi altro modo), non è possibile stabilire quale ramo è stato inizialmente commesso.

Nel tuo caso il set di modifiche 94f458e appartiene sia a master sia a release quindi il grafico è perfettamente corretto.

+1

Sembra che tu sia sostanzialmente d'accordo con ciò che ho scritto nell'ultimo paragrafo della domanda. Tranne che non vedi il comportamento attuale di git come meno utile di quanto potrebbe essere ipoteticamente. Su questo, non sarei d'accordo: posso immaginare un ipotetico VCS che mantiene le informazioni che git attualmente getta via, e posso immaginare che l'informazione sia utile in alcune impostazioni. Come, ad esempio, questo. –

+0

Scusa se sembro sgradevole. Apprezzo davvero che tu abbia trovato il tempo di rispondere alla domanda! –

+0

@Adam L. Taylor: beh, git non tiene traccia delle informazioni su quale ramo è stato commesso il changeset. Mercurial sì. – zerkms

0

I commit non sono rami "on". I rami non sono altro che nomi utili a livello locale per i commit che ti interessano. Ciò che conta è la struttura della storia nel repository. Concentrati su quello. Commits 94f e 18d fanno entrambi parte della cronologia di entrambi i rami, sono antenati di entrambi i commit release e master fare riferimento a.

Se la tua utilità aveva disegnato master a sinistra, il suo commit sarebbe stato disegnato in blu e tutti quelli unici per l'ascendenza di release sarebbero stati magenta.

Questo è più o meno ciò che @zerkms ha detto (e ho aumentato la sua), solo da un altro punto di vista.

+0

"Se la tua utilità aveva disegnato il master a sinistra, il suo commit sarebbe stato disegnato in blu e tutti quelli unici per l'ascendenza di rilascio sarebbero stati magenta." Sì, è esattamente come vorrei che fosse disegnato. E sembra discutibilmente un difetto di design in git che non mantiene abbastanza informazioni per disegnare l'albero nel modo in cui mi piacerebbe che fosse disegnato. –

+0

Si scopre che è possibile ottenere un bel po 'perdendo la nozione che "ramo" è una sorta di astrazione pesante, invece di vedere i nomi dei rami come nient'altro che etichette mobili sul grafico del commit nel repository. I commit stessi sono solo dei commit. – jthill