2010-09-12 15 views
310

In Git, c'è un modo per unire tutte le modifiche da un ramo all'altro, ma schiacciare un singolo commit allo stesso tempo?Unisci tutte le modifiche da un altro ramo come singolo commit

Spesso lavoro su una nuova funzione in un ramo separato e regolarmente eseguo commit/push, principalmente per il backup o per trasferire ciò su cui sto lavorando su un'altra macchina. Per lo più quei commit dicono "Feature xxx WIP" o qualcosa di ridondante.

Una volta che il lavoro è finito e voglio unire nuovamente il ramo WIP in master, vorrei scartare tutti quei commit intermedi, e solo un singolo commit pulito.

C'è un modo semplice per farlo?

In alternativa, che ne dici di un comando che esegue lo schiacciamento di tutti i commit su un ramo dal punto in cui è stato diramato?

risposta

403

Un'altra opzione è git merge --squash <feature branch> poi finalmente fare un git commit.

Da Git merge

--squash

--no-squash

Produrre l'albero e l'indice di lavoro stato come se una vera e propria fusione accaduto (tranne che per l'unione informazioni), ma in realtà non fanno un commit o spostare il HEAD, né registrare $GIT_DIR/MERGE_HEAD per causare t il successivo comando git commit per creare un unione commit. Ciò consente di creare un singolo commit sopra il ramo corrente il cui effetto è lo stesso di che unisce un altro ramo (o più nel caso di un polipo).

+0

Cool feature! I love git. While I ' Lo userò sicuramente in futuro, ti consiglio comunque di imparare come rebase -i: è una buona abilità da avere, nel caso in cui tu volessi davvero renderli più di un solo commit –

+2

A parola di cautela: funziona, ma il messaggio di commit predefinito include il log del ramo che viene unito. Il problema è che sembra simile al formato che normalmente si vede dove l'intero testo mostrato non diventa parte del messaggio di commit, ma in Quindi se non vuoi tutto questo, devi rimuovere tutto manualmente dal tuo messaggio di commit. Dovrei averlo provato prima di usarlo ... –

+5

Quello, e, sii avvisato che il ramo non essere visto come unito. h ttp: //stackoverflow.com/questions/19308790/git-branch-merged-no-merged-and-squash-option – rxgx

-5

È possibile eseguire questa operazione con il comando "rebase". Chiamiamo i rami "principale" e "funzione":

git checkout feature 
git rebase main 

Il comando rebase ripete tutti i commit su "funzione", come un commit con un genitore uguale a "main".

È possibile eseguire git merge main prima di git rebase main se "principale" è stato modificato da quando è stata creata la "funzione" (o dall'ultima unione). In questo modo, hai ancora la tua cronologia completa in caso di conflitto di fusione.

Dopo il rebase, è possibile unire la vostra ramo principale, che dovrebbe sfociare in una fusione fast-forward:

git checkout main 
git merge feature 

vedere la pagina rebase di Understanding Git Conceptually per una buona panoramica

+0

Questo non ha funzionato per me. Ho appena creato un semplice repository di test, con un ramo WIP e ho provato quanto sopra e ho ottenuto conflitti di fusione (anche se non avevo apportato alcuna modifica al master). –

+0

Se la funzione è stata creata da main (git checkout -b feature main) e hai avuto una fusione recente da main, non dovresti ottenere conflitti dal rebase – NamshubWriter

+0

OK, provalo di nuovo. Questa volta non ho avuto conflitti, ma la storia non è stata schiacciata. –

19

Prova git rebase -i master su il tuo ramo di funzionalità. È quindi possibile modificare tutti, tranne uno "Seleziona" in "Squash" per combinare i commit. Vedi squashing commits with rebase

Infine, è possibile eseguire l'unione dal ramo principale.

+5

Sì, funziona, ma non voglio il fastidio di rebase interattivo. Voglio solo tutto dal momento che il ramo è appiattito. –

+2

+1 Questo rende una cronologia pulita. È molto più facile identificare e gestire i commit come singole patch, schede, storie, ecc. – rxgx

165

Trovato! Unire comando ha un --squash un'opzione

git checkout master 
git merge --squash WIP 

a questo punto tutto è fusa, possibilmente in conflitto, ma non commesso. Così ora posso:

git add . 
git commit -m "Merged WIP" 
+0

cosa fa il 'git add .'? –

+0

@MichaelPotter Aggiunge tutti i file e le modifiche –

+0

'git add .' aggiunge tutti i file non ignorati nella directory corrente, sarei cauto nel prendere i file indesiderati in questo modo. –

-1

git merge --squash <feature branch> è una buona opzione .La "git commit" ti dice tutto ramo di caratteristica commettere un messaggio con la vostra scelta di tenerlo.

Per meno unione unione.

git merge do x times --git reset HEAD^--soft quindi git commit.

Rischio: i file cancellati potrebbero tornare indietro.

0

Volevo distruggere tutti i commit nel mio master in uno solo. Ho provato questo senza successo:

$ git checkout --orphan new_master 
$ git merge --squash master 
fatal: Squash commit into empty head not supported yet 

Quindi ho fatto questo:

$ tar cf /tmp/git.tar --exclude .git . 
$ git checkout --orphan new_master 
$ tar xf /tmp/git.tar 
$ git commit -m "Initial commit" 

, che ha funzionato bene.

Problemi correlati