git rimuove il merge commit dalla cronologia


97

La mia cronologia Git ha questo aspetto:

Storia di Git

Vorrei schiacciare i commit viola in uno solo. Non voglio vederli mai più nel mio registro di commit.

Ho provato a fare un git rebase -i 1, ma anche se 1è sul ramo blu (vedi immagine), vedo ancora ogni commit sul mio ramo viola.

Come posso rimuovere completamente il ramo viola (dal registro di commit)?


Il tuo repo è stato spinto da qualche parte che altre persone ne hanno tratto?
Schleis

Entrambi i rami sono puramente locali.
Benjamin Toueg

Risposte:


100

Do git rebase -i <sha before the branches diverged>questo vi permetterà di rimuovere l'unione commit e il registro sarà una sola linea, come si voleva. Puoi anche eliminare tutti i commit che non desideri più. Il motivo per cui il tuo rebase non funzionava era che non stavi tornando indietro abbastanza lontano.

ATTENZIONE: stai riscrivendo la cronologia in questo modo. Fare ciò con le modifiche che sono state inviate a un repository remoto causerà problemi. Consiglio di farlo solo con commit locali.


4
Anche se scelgo uno sha prima che i rami siano divergenti, vedo tutti i commit del ramo viola -_-
Benjamin Toueg

1
Sì, poi li elimini nell'editor che viene fornito git rebasee verranno rimossi.
Schleis

4
L'eliminazione dei commit ha comportato la perdita di tutte le modifiche dell'unione. Ma ho fatto un soft reset e sono stato in grado di avere qualcosa di simile a quello che volevo (l'ordine non corrisponde alle aspettative iniziali).
Benjamin Toueg

2
questa risposta è incompleta in dettaglio, da quale ramo inizi il rebase?
arrabbiato

3
Abbastanza sicuro di non voler "rimuovere" i commit. "remove" non è un'opzione in rebase, ma lo è. se elimini un commit, perderai le modifiche che ha introdotto. Vuoi schiacciare i commit.
thecoshman

70

A partire dal repository nello stato originale

Cronologia repo originale

Per rimuovere il commit di unione e schiacciare il ramo in un unico commit nella linea principale

Commit schiacciati, nessun commit di unione

Usa questi comandi (sostituendo 5 e 1 con gli SHA dei commit corrispondenti):

git checkout 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git rebase HEAD master

Per mantenere un commit di unione ma schiacciare il commit di branch in uno:

Commit schiacciati, commit di unione mantenuto

Usa questi comandi (sostituendo 5, 1 e C con gli SHA dei commit corrispondenti):

git checkout -b tempbranch 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git checkout C
git merge --no-ff tempbranch
git rebase HEAD master

Per rimuovere il commit di unione e sostituirlo con commit individuali dal ramo

Il ramo è stato spostato nella linea principale, nessun commit di unione

Basta fare (sostituendo 5 con lo SHA del commit corrispondente):

git rebase 5 master

E infine, per rimuovere completamente il ramo

Ramo rimosso completamente

Usa questo comando (sostituendo C e D con gli SHA dei commit corrispondenti):

git rebase --onto C D~ master

nel git rebase 5 mastercaso, perché non è l'ordine "ABC 1 2 3 4 5 D ..."?
Roy

1
Quel comando prende i commit che masternon hanno in comune con 5e li sovrappone 5. Il commit a Cnon fa parte del lignaggio di 5, è il primo ad essere spostato in cima 5.
Allen Luce

2
Se vuoi finire con "ABC 1 2 3 4 5 D ..." puoi fare:git rebase C 5; git rebase 5 master
Allen Luce

16

Ci sono due modi per affrontare questo problema in base a ciò che desideri:

Soluzione 1 : rimuovere i commit viola, preservando la cronologia (nel caso in cui si desideri ripristinare)

git revert -m 1 <SHA of merge>

-m 1 specifica quale linea genitore scegliere

I commit viola saranno ancora presenti nella cronologia, ma poiché sei stato ripristinato, non vedrai il codice di quei commit.


Soluzione 2 : rimuovere completamente i commit viola (modifica dirompente se il repository è condiviso)

git rebase -i <SHA before branching out>

e cancella (rimuovi le linee) corrispondenti ai commit viola.

Ciò sarebbe meno complicato se i commit non fossero stati effettuati dopo l'unione. Ulteriori commit aumentano la possibilità di conflitti durante revert/rebase.


Questo non suona bene. Lasciando da parte il fatto che è difficile dire cosa volesse fare il poster originale con i commit viola in primo luogo, se si ripristina l'unione, va bene, che farà una patch inversa delle modifiche da quel commit e lo aggiungerà come un altro commit, annullando i commit viola. È come 1 - 1 = 0. Ma se poi ridisegni i commit viola, ti lasci alle spalle la patch ripristinata, a meno che non ribassi anche quella. Se non lo fai, è come applicare -1alla tua storia, no 0, quindi ti lascerai dietro le modifiche che non desideri.

@ Cupcake, a condizione che fossero due risposte separate. Ho rivisto la risposta per essere meno confusa: P
prem

Per quanto ne so, questo non è ciò che chiede l'OP. Vuole mantenere le modifiche, ma rimuovere il rumore dal suo registro. Per questo, ha bisogno di schiacciare i commit, l'eliminazione rimuoverà le modifiche.
thecoshman

È vero, sembra che la domanda originale sia stata riformulata. Questa risposta non è per il problema degli OP.
prem

16

Per rimuovere solo un commit di unione

Se tutto ciò che vuoi fare è rimuovere un merge commit (2) in modo che sia come se non fosse mai successo, il comando è semplicemente il seguente

git rebase --onto <sha of 1> <sha of 2> <blue branch>

E ora il ramo viola non è affatto nel registro di commit del blu e hai di nuovo due rami separati. Puoi quindi schiacciare il viola in modo indipendente e fare qualsiasi altra manipolazione desideri senza che l'unione si impegni nel modo.


Di tutte le risposte, trovo che questa sia la più semplice e la più facile da fare. Grazie.
Roshambo
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.