2015-03-28 2 views
20

La maggior parte dei flussi di lavoro di git che ho visto suggeriscono di eliminare un branch dopo che è stato fuso in master. Ad esempio, questo gitflow suggerisce quanto segue:perché dovrei eliminare i rami delle funzioni quando sono uniti al master

# Incorporating a finished feature on develop 
$ git checkout develop 
Switched to branch 'develop' 
$ git merge --no-ff myfeature 
Updating ea1b82a..05e9557 
(Summary of changes) 
$ git branch -d myfeature 
Deleted branch myfeature (was 05e9557). 
$ git push origin develop 

Perché dovrei cancellare il ramo? Sono anche curioso di sapere cosa fare quando in seguito verrà scoperto un bug introdotto dalla funzione: dovrei creare di nuovo il ramo con lo stesso nome, correggere il bug, unirmi al master e cancellare nuovamente il ramo?

+1

Perché la funzione è finita. Quale sarebbe la necessità di mantenere il ramo, in tal modo ingombrando il risultato del ramo git -a ecc? –

+0

@OliverCharlesworth history –

+0

@ Z.Khullah - I commit sarebbero ancora nella storia. –

risposta

33

Qualcosa di importante da realizzare è che i rami Git non sono altro che un'etichetta che punta a un commit. Branching in Git è letteralmente ramificato. Ecco quello che un repository appare come se feature diramava master quando master stato un commit B.

A - B - C - F - H [master] 
    \ 
     D - E - G - I[feature] 

Vedi? Ramo attuale Quando si git merge feature in master, si ottiene questo.

A - B - C - F - H - J [master] 
    \   /
     D - E - G - I [feature] 

E una volta che la storia git branch -d feature ramo rimane!

A - B - C - F - H - J [master] 
    \   /
     D - E - G - I 

J ha i genitori H e I. J non può esistere senza di loro, è cotto in come funziona Git. Non posso esistere senza G. G non può esistere senza E. E così via. Il ramo deve rimanere

J è un commit merge che in genere conterrà il nome del ramo da unire. È come qualsiasi altro commit, quindi puoi anche aggiungere più informazioni ad esso, come un link al tuo tracker di problemi.

git merge --no-ff viene utilizzato per impedire a Git di eseguire un "avanzamento rapido" e di perdere la cronologia del ramo. Ciò accade se non è stato eseguito alcun lavoro su master da quando è stato creato il ramo. Un fast-forward sembra così.

A - B[master]- D - E - G - I [feature] 

git checkout master 
git merge feature 

A - B - D - E - G - I [feature] [master] 

Da master è un antenati del feature, non è richiesta alcuna unione. Git può semplicemente spostare l'etichetta master. La cronologia del tuo ramo è andata persa, sembra che D, E, G e I siano stati tutti fatti come singoli commit sul master. git merge --no-ff dice a Git di non farlo mai, per eseguire sempre l'unione.

In futuro, quando viene rilevato che un errore è stato introdotto in G, chiunque sfoglia il repository può vedere che è stato eseguito come parte del ramo, guardare avanti per trovare il commit di unione e ottenere informazioni sul ramo da lì.

Anche così, perché eliminare il ramo?Due ragioni. In primo luogo, ingombrerà la tua lista di rami con rami secchi.

In secondo luogo, e più importante, impedisce di riutilizzare il ramo. La ramificazione e la fusione sono complicate. Le filiali di funzioni monouso e di breve durata semplificano il processo assicurandovi di reinserire il ramo sempre nel master una volta. Questo elimina molti problemi tecnici e di gestione. Quando unisci un ramo, è fatto. Se devi risolvere un problema introdotto in quel ramo, consideralo come un bug in master e crea un nuovo ramo per risolverlo.

Sfortunatamente, git log giace all'utente e presenta una rappresentazione lineare della cronologia che non è lineare. Per risolvere questo problema, utilizzare git log --graph --decorate. Questo disegnerà linee come nei miei esempi sopra e ti mostrerà ogni ramo e tag su ogni commit. Avrai una visione molto più accurata del repository.

Se sei su un Mac, GitX visualizzerà il repository per te. gitk è la versione generica.

+0

grazie per la tua risposta! Puoi spostare la parte che inizia con _why delete the branch_ prima che la spiegazione di cosa sia un branch git così che qualcuno che cerca la stessa risposta ottenga la risposta proprio in alto :). Anche la risposta di 'VonC' è molto utile, forse potresti incorporare parte della sua risposta nella tua risposta per renderla una fonte completa di informazioni. Grazie! –

+0

@Maximus IMO senza capire come funzionano i rami Git, il mio ragionamento per l'eliminazione del ramo non ha senso. Per quanto riguarda la risposta di VonC, non vedo cosa ci sia in lui che non ho coperto; potresti elaborare? – Schwern

+0

Probabilmente hai ragione, forse perché so tutto ciò che non ho visto come conoscenza pre-richiesta. Trovo molto utile questa parte della risposta di VonC: _Perché la cronologia del ramo myfeature rappresenta tutti i commit intermedi fatti per implementare la mia caratteristica. Questa strategia mantiene solo un commit in master e dimentica i passaggi intermedi, che ha senso per i rami longeva, _ –

1

Poiché la cronologia di succursale myfeature rappresenta tutti i commit intermedi eseguiti per implementare myfeature.

Questa strategia mantiene un solo commit in master e dimentica i passaggi intermedi, il che ha senso per i rami longeva, come ho spiegato in "Why does git fast-forward merges by default?".

Il messaggio di commit del commit eseguito (unito) in master dovrebbe rendere chiaro che è stato fatto per l'implementazione di 'myfeature'.

Se è necessario ripararlo, è possibile riutilizzare il nome del ramo (poiché è stato eliminato prima).

+0

. Cosa intendi per rami di breve durata? Ci sono differenze rispetto ai rami delle funzionalità? Inoltre, a quanto ho capito, le informazioni sul ramo devono essere memorizzate nel commit di unione quando il ramo di funzione viene unito in master? –

+0

Puoi anche dare un'occhiata al commento che ho lasciato per la tua risposta [qui] (http://stackoverflow.com/a/29296584/2545680)? –

+1

@Maximus http://stackoverflow.com/a/2850413/6309 illustra un ramo shot-live (solo pochi commit si fondono rapidamente nel master), al contrario di un ramo long-live, in cui verranno eseguiti molti commit (con prove ed errori) prima di essere unito * alla fine * a padroneggiare: in quest'ultimo caso, è più semplice mantenere un solo commit in master. – VonC