Che cosa significa "ramificazione gratuita" in Git?


27

Che cosa significa "ramificazione gratuita" in Git?

Lo sento molto ogni volta che viene menzionato Git rispetto ad altri sistemi di controllo della versione.

Non ho avuto l'opportunità (?) Di trattare con altri ( SVN , ecc.), Quindi in che modo la ramificazione è "costosa" negli altri?

Risposte:


28

L'affermazione che "la ramificazione è libera in git" è una semplificazione dei fatti perché non è "libera" di per sé. Guardando sotto il cofano, un'affermazione più corretta sarebbe quella di dire che la ramificazione è invece ridicolmente economica , perché le filiali sono fondamentalmente riferimenti a commit . Definisco "economicità" qui come meno sovraccarico più economico.

Scopriamo perché Git è così "economico" esaminando che tipo di spese generali ha:

Come sono implementate le filiali in git?

Il repository git, .gitprincipalmente costituito da directory con file che contengono metadati che git usa. Ogni volta che crei un ramo in git, ad esempio git branch {name_of_branch}, accadono alcune cose:

  • Viene creato un riferimento alla filiale locale in: .git/refs/heads/{name_of_branch}
  • Viene creato un registro cronologico per la filiale locale in: .git/logs/refs/heads/{name_of_branch}

È praticamente tutto, vengono creati un paio di file di testo. Se si apre il riferimento come file di testo, il contenuto sarà l'id-sha del commit a cui punta il ramo. Si noti che la ramificazione non richiede di eseguire alcun commit poiché sono un altro tipo di oggetto. Sia le filiali che i commit sono "cittadini di prima classe" e un modo è quello di pensare alla relazione branch-to-commit come aggregazione piuttosto che come composizione. Se rimuovi un ramo, i commit rimarranno comunque "penzolanti". Se hai rimosso accidentalmente un ramo, puoi sempre provare a trovare il commit con git-lost-foundo git-fsck --lost-founde creare un ramo sullo sha-id che trovi lasciato sospeso (e fintanto che git non ha ancora fatto alcuna garbage collection).

Quindi, come fa Git a tenere traccia di quale ramo stai lavorando? La risposta è con il .git/HEADfile, che sembra un po 'così se sei sul masterramo.

ref: refs/heads/master

Il cambio di diramazione modifica semplicemente il riferimento nel .git/HEADfile, quindi procede a modificare il contenuto dell'area di lavoro con quelli definiti nel commit.

Come si confronta in altri sistemi di controllo versione?

In Subversion , i rami sono directory virtuali nel repository . Quindi il modo più semplice per diramare è farlo da remoto, con un solo strato svn copy {trunk-url} {branch-url} -m "Branched it!". Ciò che SVN farà è il seguente:

  • Copia la directory di origine, ad esempio trunk, in una directory di destinazione,
  • Conferma le modifiche per finalizzare l'azione di copia.

È consigliabile eseguire questa azione in remoto sul server, poiché eseguire tale copia localmente è un'operazione lineare, con i file che vengono copiati e collegati in modo simbolico. Questa è un'operazione molto lenta , mentre farlo sul server è un'operazione a tempo costante. Si noti che anche quando si esegue il ramo sul server, la sovversione richiede un commit quando si ramifica mentre git no, il che è una differenza fondamentale. Questo è un tipo di overhead che rende SVN leggermente meno economico di Git.

Il comando per cambiare ramo in SVN , cioè svn switch, è davvero svn updatesotto mentite spoglie. Grazie al concetto di directory virtuale il comando è un po 'più flessibile in svn che in git. Le sottodirectory nell'area di lavoro possono essere disattivate per rispecchiare un altro URL repository. La cosa più vicina sarebbe usare git-submodulema usarlo è semanticamente abbastanza diverso dalla ramificazione. Sfortunatamente questa è anche una decisione di progettazione che rende un passaggio un po 'più lento in SVN che in Git in quanto deve controllare ogni directory dello spazio di lavoro su quale url remoto rispecchia. Nella mia esperienza, Git è più veloce nel cambiare ramo rispetto a SVN.

La ramificazione di SVN ha un costo in quanto copia i file e deve sempre essere resa pubblica. In git, come spiegato sopra, i rami sono "solo riferimenti" e possono essere conservati nel tuo repository locale ed essere pubblicati a tua discrezione. Nella mia esperienza, tuttavia, SVN è ancora notevolmente più economico e più performante rispetto ad esempio a ClearCase.

È solo un peccato che SVN non sia decentralizzato. È possibile disporre di più repository come mirroring di alcuni repository di origine, ma la sincronizzazione di modifiche diverse non è possibile per più repository SVN poiché SVN non ha identificatori univoci per i commit (git ha identificatori con hash basati sul contenuto del commit). Il motivo per cui ho iniziato personalmente a usare git su SVN è perché l' avvio di un repository è notevolmente più semplice ed economico in git . Concettualmente in termini di gestione della configurazione del software, ogni copia divergente di un progetto (clone, fork, area di lavoro o altro) è un "ramo" e, data questa terminologia, creare una nuova copia in SVN non è economico come Git, dove quest'ultimo ha rami "integrati".

Come altro esempio, in Mercurial , il branching è iniziato in modo leggermente diverso rispetto a un DVCS e la creazione / distruzione di rami con nome ha richiesto commit separati. Gli sviluppatori di Mercurial implementati in seguito nei segnalibri di sviluppo per imitare lo stesso modello di ramificazione di Git headssono chiamati tipse branchessono bookmarksinvece nella terminologia mercuriale.


Wow. Mille grazie per la spiegazione "costosa".
laggingreflex,

2
Dalla tua fonte: This command causes a near-instantaneous commit in the repository, creating a new directory in revision 341. The new directory is a copy of /calc/trunk.- La creazione del ramo è banale in SVN, a meno che tu non stia facendo esplicitamente una copia di ogni file.
Bobson,

@Bobson Stavo pensando di riscrivere i bit sulla ramificazione, dal momento che sto facendo un sacco di ondeggiamento a riguardo, ma il mio punto è ancora che è necessario un commit per creare un ramo mentre in Git non lo è. Nella mia modesta esperienza ho ancora la sensazione che cambiare ramo in SVN sia più lento che in Git, ma non posso indicare alcun motivo specifico per cui.
Spoike,

2
@Spoike - Commutazione, certamente. E un impegno è sicuramente richiesto. Ho fatto una modifica per chiarire il bit con cui avevo un problema. Sentiti libero di ripristinarlo se preferisci.
Bobson,


10

In Git, un ramo è solo riferimento a un commit al repository locale. La sua creazione è molto economica, nessuna rete. Non del tutto gratuito (devi digitare un comando), ma dannatamente vicino.

La ramificazione non è particolarmente costosa in SVN: è solo una copia, che è un impegno molto economico. SVN ha un modello di repository centrale, quindi è un accesso alla rete, ma non orribile.

Nel venerabile CVS, invece, la ramificazione è MOLTO costosa. Fondamentalmente, le filiali CVS comportano l'aggiunta di un tag, ma in CVS ciò significa che OGNI FILE INTERESSATO deve essere modificato. Ogni file viene riscritto per includere il nuovo tag. È orribilmente costoso. E se il tuo repository è grande, è anche terribilmente lento. In effetti, se sei su un grande progetto, è abbastanza lento che alcune persone tendono a evitare di fare rami se possono.


4
Con Git, è anche meno di un commit: un ramo è solo un'etichetta. E SVN sembra costoso come CVS, poiché entrambi copiano tutti i file.
Izkata,

8
@Izkata: se vediamo dal punto di vista dell'utente - sì, tutti i file vengono copiati, dal punto di vista dell'implementazione (e delle prestazioni) - no, viene aggiunto solo un record sulla copia.
maxim1000,

@Izkata troppo per commentare - vedi la mia risposta.
gbjbaanb,

6
@Izkata SVN crea puntatori e riferimenti, non copia tutto.
Aaron McIver il

2
Un ramo Git non è un commit, è solo un riferimento a un commit che può essere spostato liberamente in altri commit. Pensa a un repository Git solo come un albero di commit e i rami come note adesive che possono essere spostate liberamente in diversi commit su quell'albero.
40XUserNotFound

5

La ramificazione di SVN è gratuita come quella di Git. Sono solo un po 'di dati sulle pulizie che indicano dove inizia il ramo, nessuna modifica ai file memorizzati. Una 'copia' in SVN è come aggiungere un link simbolico a una directory Unix. Si noti che il ramo SVN non richiederà un viaggio di rete fino a quando non si commettono le modifiche della copia di lavoro (ma non ha molto senso avere un SCM se non si commette off-local a un certo punto).

Si noti che un ramo Git coinvolgerà anche alcune pulizie - come l'aggiunta di quel tag internamente - che dovranno essere archiviate da qualche parte quando si commette. Non è affatto un grosso problema, motivo per cui si chiama 'gratuito'.


5

È "libero" (in questo contesto "libero" significa davvero semplice e veloce e non occupa spazio) perché in alcuni sistemi di controllo delle versioni precedenti un ramo era una copia completa del codice a quel punto, quindi i rami occupavano molto spazio ed è stato facile finire con un sacco di diverse versioni completamente complete del software in circolazione, che ha poi preso la gestione. In altri non era una copia completa del codice ma ogni file doveva ancora essere modificato per un tag, quindi era lento e doloroso ("costoso").

I rami di git sono essenzialmente etichette che puntano a un commit e quindi evitano i problemi di cui sopra.


1

Un altro aspetto di "libero / economico / costoso" riguarda quanto costa in termini di risorse per gli sviluppatori affrontare le conseguenze a valle della ramificazione; vale a dire il processo di fusione dei cambiamenti dalle filiali.

E qui, fondere filiali in sistemi DVCS come Git e Mercurial è più facile che in sistemi più vecchi ... perché i sistemi DVCS fanno un lavoro molto migliore nel tracciare la cronologia delle versioni nel grafico; vale a dire dove si è verificata una precedente ramificazione. Questo rende le fusioni più accurate, riduce i conflitti inutili e ... rende la fusione soggettiva "più facile" o "meno spaventosa" per gli sviluppatori coinvolti.

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.