2012-01-26 4 views
12

Supponiamo che il mio repository Git abbia inizialmente due rami: Foo e Bar.Rebase a merge commit

 
... ─ Foo 

... ─ Bar 

Creo un terzo ramo, FooBar in cui commetto l'unione degli altri due rami.

 
... ─ Foo ──┐ 
      FooBar 
... ─ Bar ──┘ 

FooBar ora è impegnato in anticipo rispetto a Foo e Bar. Successivamente, faccio ancora un po 'di lavoro, impegnando alcune volte solo su Foo.

 
... ── A ───┬── B ── C ── D ── Foo 
      FooBar 
... ─ Bar ──┘ 

La domanda è: dal momento che il primo genitore del ramo FooBar non è più Foo, posso Rebase l'unione impegnarsi nel ramo FooBar di avere di nuovo Foo e bar come i suoi due genitori? In altre parole, posso incorporare lo sviluppo in Foo nel FooBar precedentemente unito con la barra invariata?

 
... ── A ── B ── C ── D ── Foo ──┐ 
           FooBar 
... ─ Bar ───────────────────────┘ 
+0

Vedere anche [utilizzando git-replace per modificare un puntatore padre] (http://stackoverflow.com/a/3811217/90527), sebbene ciò abbia altre conseguenze. – outis

+0

Vedere anche [Come utilizzare git rebase -i dopo git merge senza rovinare tutto?] (Http://stackoverflow.com/q/4152936/90527) – outis

risposta

1

Non si poteva rebase sotto ramo FooBar senza cambiare ciò che definisce FooBar. Quello che potresti fare è unire FooBar e Foo. Quello avrebbe gli stessi contenuti che desideri.

+0

Sì, ma il punto è evitare l'unione di commit. Ecco perché voglio ribattere 'BranchFooBar'. – nccc

+0

Forse sono confuso con quello che vuoi. Tu dici di voler evitare l'unione di commit, ma sto interpretando la tua domanda nel momento in cui desideri che i risultati finali siano un commit di unione tra 'branchFoo' e' branchBar'. – Andy

+0

Hai ragione, questo non era abbastanza chiaro. Voglio evitare un commit di * 2 * unione. 'BranchFooBar' sarà sempre un merge commit, ma voglio che sia il * solo * merge commit con' BranchFoo' e 'BranchBar' come genitori. – nccc

0

Stai praticamente cercando di cancellare tutte le tracce della fusione creata in precedenza.

Se veramente si vuole buttare via tutti i commit che esiste solo nella FooBar (e nella directory di lavoro), quindi procedere come segue: in primo luogo fare git checkout FooBar, poi fare git dimenticare la sua storia e fare git reset --hard Foo (se l'intenzione di unire Bar in). Quindi si ricrea l'unione con git merge Bar.

12

Mi rendo conto che si tratta di un argomento piuttosto vecchio, ma poiché ho trovato questa domanda mentre mi trovavo di fronte a una situazione simile, potevo anche dire cosa ho usato alla fine.

git checkout FooBar 
git rebase -p --onto Foo A 

Ho provato a utilizzare i nomi della domanda originale. Nota in particolare che A indica il commit contrassegnato come A nell'arte ascii. Probabilmente utilizzeresti l'hash del commit o qualsiasi altro modo per indicare il commit in cui i rami e FooBar erano originariamente separati.

Il flag -p è anche noto come --preserve-merges e fa più o meno quello che dice.

Si noti che il ramo Bar non svolge un ruolo qui in modo che la linea di commit possa essere un ramo con nome o meno, non fa alcuna differenza.

+3

Si noti che questo non manterrà alcuna modifica apportata nel commit di unione. – Tgr

+2

Grazie, questo ci ha aiutato molto. È infatti importante notare che "A" è l'ultimo commit del ramo di destinazione che è stato ancora incluso nell'unione originale. – Dibbeke

+1

questa dovrebbe essere la risposta accettata! – wutzebaer