2015-02-09 21 views
11

Quando lavoro su due funzioni diverse (su due diversi rami creati dal master ) è piuttosto fastidioso che non avrò la cronologia di commit quando procedo con l'unione.Mantieni cronologia dei commit dopo un 'git merge'

Spiegherò meglio. Quando finisco di lavorare su Branch-A, lo unisco nel master. E va bene, se io git log vedo tutti i commit che ho fatto su Branch-A.

Invece, quando finisco di lavorare su Branch-B e cerco di unire al maestro (dopo che Branch-A è già stata fusa), devo specificare un messaggio di commit per la fusione (mentre per il primo ramo non mi è stato chiesto nulla). E dopo la fusione per padrone, se digito git log, non riesco a vedere i commit del Branch-B nella storia della mia padrone ramo

Diciamo che ho

**Branch A** 

commit 09b2unfas9d781n2e 
    Add more stuff 

commit 8uj8masd89jas898a 
    Add stuff 

**Branch B** 

commit 09b2unfas9d781n2e 
    Add feature setting 

commit 8uj8masd89jas898a 
    Add feature 

finisco di avere

**Master** 

commit 6hf6h8hd871udjkdn 
Merge: 09b2un 34osd6 
    Merge branch 'Branch-B' into master 

commit 09b2unfas9d781n2e 
    Add more stuff 

commit 8uj8masd89jas898a 
    Add stuff 

commit 34osd62dhc91123j8 
    I'm a previous commit from 'master'. 
    The last one before branching... 

mentre vorrei o btain qualcosa come:

**Master** 

commit 09b2unfas9d781n2e 
    Add feature setting 

commit 8uj8masd89jas898a 
    Add feature 

commit 09b2unfas9d781n2e 
    Add more stuff 

commit 8uj8masd89jas898a 
    Add stuff 

commit 34osd62dhc91123j8 
    I'm a previous commit from 'master'. 
    The last one before branching... 

... che sarebbe riflettere più esattamente la storia dei commit eseguiti.

Non capisco perché riesca a mantenere la cronologia da uno solo dei due rami.

Come posso mantenere tutto chiaro senza quelli unione commit che nasconde/omette la cronologia reale dei commit uniti?

risposta

0

Utilizzare rebase anziché merge. Dal tutorial:

Se si esamina il registro di un ramo ricalcolato, sembra un storia lineare: sembra che tutto il lavoro è accaduto in serie, anche quando originariamente accaduto in parallelo.

immagino che le modifiche dal tuo Branch-B non possono essere unite utilizzando fast-forward si fonde con il master. In questi casi un three-way-merge è fatto:

Invece di limitarsi a spostare il puntatore ramo in avanti, Git crea un nuovo snapshot che deriva da questo tre vie unione e automaticamente crea un nuovo commit che punti ad esso. Questo è indicato come un unione commit ed è speciale in quanto ha più di un genitore.

Rifare sempre i miei commit prima di inviarli nello master per mantenere la cronologia lineare.

11

Sembra che la prima unione sia stata un avanzamento rapido e la seconda era un'unione a tre vie.

Spiegazione

Git ha due versioni di fusione: fast-forward e tre vie. (Esistono altre versioni, ma non è quello che è successo qui.) Il comportamento predefinito consiste nel fare un'unione avanti veloce quando possibile, e altrimenti fare un'unione a tre.

Un'unione di avanzamento rapido (è possibile forzare questo comportamento con l'opzione --ff-only, che causerà l'unione non riuscita quando l'avanzamento veloce è impossibile) può avvenire quando il commit che viene unito ha la posizione corrente del ramo nella sua storia. Per esempio:

A - B - C - D <-master 
      \ 
       E - F - G <- branch-a 

Excecuting git merge (con le impostazioni predefinite) si tradurrà in

A - B - C - D - E - F - G <- branch-a <-master 

Potrai anche non avere la possibilità di modificare l'unione impegnarsi perché non c'è nessuno. Tuttavia, una volta che questo accade, il vostro altro ramo si divergere da padrone (e non solo essere davanti):

A - B - C - D - E - F - G <-master 
        \ 
        E1 - E2 <- branch-b 

Pertanto, Git non può semplicemente spostare il puntatore del maestro G-E2 perché che sbarazzarsi dei cambiamenti che sono stati effettuati in F e G. Invece avviene un'unione a tre vie, che crea un commit che ha due genitori e ha anche un messaggio di commit. Ora, il master può essere spostato su questo commit. (Si noti che in questa situazione, padrone e ramo-B non puntare allo stesso commit.

A - B - C - D - E - F - G - H <-master 
        \  /
        E1 - E2 <- branch-b 

Se si vuole avere una storia lineare, allora avete bisogno di usare rebase, ma essere avvertiti che se qualcuno ha altro visto che il tuo ramo si impegna, ciò potrebbe portare a problemi che vanno oltre lo scopo di questa risposta. L'uso di rebase comporterà due passaggi, rebasing e quindi l'unione rapida. Quindi, invece di unire, esegui quanto segue su branch-b , git rebase master.Questo crea nuovi commit che sono copie dei vecchi commit, cioè lo stesso set di modifiche, le informazioni dell'autore e il messaggio, ma le nuove informazioni sul committer e la storia del genitore (io chiamo i commit E1 'ed E2' nell'illustrazione a indica che sono solo copie.) T egli vecchi commit esisterà fino a quando sono garbage collection, ma non sarà raggiungibile a meno che non si guarda al reflog.)

A - B - C - D - E - F - G <-master 
        \  \ 
        E1 - E2 \ 
          E1' - E2' <- branch-b 

Esecuzione git checkout master; git merge --ff-only branch-b sarà ora avanzare rapidamente le modifiche in master, è dando così una storia lineare.

A - B - C - D - E - F - G - E1' -E2' <-master <- branch-b 
+0

Ho bisogno di unire 'master' in' branch-b' quando ho dei cambiamenti in entrambi. Come posso riscrivere 'branch-b' come se fosse stato avviato da commit' G', non 'E'? Ma continua la storia del commit di 'branch-b' e commetti le modifiche a' branch-b' che sono conflitti. Supponendo che io sia solo uno che sa di 'branch-b'. – hlcs

+0

Nvm è esatto 'git rebase master'. – hlcs

Problemi correlati