2009-11-12 19 views
6

Lasciatemi spiegare il problema in dettaglio.Come unire un ramo ad un altro ramo in GIT?

Ho un ramo git principale su cui ho creato un nuovo ramo laterale bug10101010, ora non voglio unire il bug10101010 al main. Fin qui tutto è buono. Ora ho un ramo diverso dello stesso prodotto, denominato legacy. Non voglio unire il bug10101010 al ramo legacy in GIT.

Qualche idea?

Non riesco a unirlo direttamente, poiché il ramo bug10101010 è derivato dal ramo principale e nell'eredità ho bisogno solo del diff tra il ramo bug10101010 e il suo ramo genitore.

+0

@Priyank: Sono d'accordo, la patch è più semplice. Ma il metodo che descrivo non è complesso. Illustra anche la facilità con cui è possibile clonare un repository e realizzare qualsiasi operazione Git che si desidera, a condizione che non si stia spingendo da lì. – VonC

risposta

2

Questo è difficile da fare. Git salva la cronologia di unione e se "cherrypick" e punta a un commit in bug10101010 come genitore (indicando che hai fatto un'unione) Git assumerà che tutti i commit prima di quello (fino al punto in cui sono stati divisi) sono stati uniti come bene. Darti problemi quando vuoi fare una fusione "reale".

D'altra parte è possibile semplicemente generare manualmente una patch da quello (e solo da quello) commit specifico. Ma questo ti darà anche dei problemi quando successivamente realizzerai l'unione "reale", poiché tenta di applicare due volte il commit manuale.

Ma poi di nuovo, dal momento che un ramo si chiama "Legacy", sospetto che tu non abbia intenzione di fare quella vera unione comunque, nel qual caso sei praticamente libero di farlo comunque.

Ecco un interesting blog post on the topic.

+0

Grazie per il link meraviglioso. Quindi, qual è la vostra raccomandazione, e come fare quanto sopra. O lasciatemi riformulare la domanda: ho bisogno della possibilità di creare transazioni specifiche per i bug che sono sempre unite al main, ma ha bisogno della capacità di riprodurre queste transazioni su altri rami a volontà. –

+0

Cosa intendi con "always merged to main"? Un ramo di bug specifico dovrebbe solo essere unito al ramo principale una volta sola. Se la mia risposta generale, abbinata al link del blog e alla documentazione generale su git, non ti porta da nessuna parte, potresti considerare di aggiornare la tua domanda originale specificando in dettaglio il flusso di lavoro specifico a cui miri un po 'di più. Potrei essere in grado di aiutare allora. – Mizipzor

+0

Le domande sono le stesse, il bug10101010 del ramo è unito al principale, poiché tutte le correzioni dei bug devono essere presenti nel ramo principale. Ma come potresti unire le modifiche specifiche nel fatto nel ramo bug10101010 rispetto al suo genitore al ramo legacy. Come si suggerisce di generare manualmente una patch e applicare la stessa cosa, ma facendo ciò sto perdendo la possibilità di tenere traccia che queste modifiche provengono da questo ramo. –

1

Utilizzare git-diff e quindi git-apply?

+0

come faresti, quindi, che ciò che hai unito proveniva dal ramo bug10101010, che in pratica è solo una transazione. Inoltre non è diretto. Ho bisogno della possibilità di specificare solo il nome del ramo e unire le modifiche. –

+0

L'idea è anche creare transazioni di bug (usando piccoli rami) e rieseguire quelle transazioni, senza sforzo, ovunque (qualsiasi ramo). Creare una patch e unire lo stesso, può essere fatto anche in CVS/SVN, quindi non è più necessario spostarsi su Git. –

+0

Se il ramo è una transazione, dopo che il suo scopo è terminato, il ramo può essere rimosso in modo efficace e quindi è sufficiente registrare che la patch è una correzione per bugXXXXXXXXX essere sufficiente? Dal momento che il punto della transazione è incapsulare le modifiche, la somma totale delle quali può essere tracciata come aggregata? – Amber

6

È necessario utilizzare git rebase --onto qui e specificare un intervallo.
(vedi git rebase man page:

trapianto di un ramo argomento basa su un ramo all'altro, far finta che si biforcuta il ramo argomento da quest'ultimo ramo, usando rebase --onto

.).

Ovviamente questo sposterebbe il ramo bug10 in cima al ramo legacy, che non è quello che si desidera/necessario.

Quindi, una soluzione potrebbe essere quella di fare che REBASE in un repo clonato, quindi unire che 'rafforzata' legacy ramo (quello nel repository clone, con i bug10 modifiche su di esso) al locale e corrente legacy ramo (quello che si desidera modificare, lasciando solo bug10).

Ora:

  • questo comporta un repo supplementare (che può portare a limitazioni di spazio su disco)
  • nel complesso, questo è abbastanza equivalente a definire un cerotto e applicarlo a legacy ramo, per cui la altre risposte (patch) sono valide (e più semplici).
  • l'unico vantaggio che vedo in questo metodo è la possibilità di definire un ambiente legacy in cui si rebase ciò che si vuole (come i bug10 commit), prima di spingere solo quel ramo legacy al tuo repo originale (che non avrebbe spingere bug10, poiché la sua storia sarebbe stata interamente riscritta!)

Volevo solo vedere se funziona, quindi ... Proviamo questo approccio.
(Git1.6.5.1, su un vecchio XP SP2, con una sessione di PowerShell 1.0 a causa del Start-Transcript command)


PS D:\> mkdir git 
PS D:\> cd git 
PS D:\git> mkdir tests 
PS D:\git> cd tests 
PS D:\git\tests> git init mainRepo 

mi piace come io non ho più per rendere la directory git repo per prima cosa, quindi digita git init! Since 1.6.5:

"git init" hanno imparato a mkdir/chdir in una directory quando dato un argomento in più (vale a dire "git init this").

Questo è FANTASTICO!

Creiamo 3 file, per 3 diversi scopi.
(Per motivi di esempio, terrò il file modifiche separano per sportello: nessun conflitto durante unione o rebase qui.)

PS D:\git\tests> cd mainRepo 
PS D:\git\tests\mainRepo> echo mainFile > mainFile.txt 
PS D:\git\tests\mainRepo> echo contentToBeFixed > toBeFixedFile.txt 
PS D:\git\tests\mainRepo> echo legacyContent > legacy.txt 
PS D:\git\tests\mainRepo> git add -A 
PS D:\git\tests\mainRepo> git ci -m "first commit" 
PS D:\git\tests\mainRepo> echo firstMainEvol >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "first evol, for making 1.0" 
PS D:\git\tests\mainRepo> git tag -m "1.0 legacy content" 1.0 

A questo punto, un git log --graph --oneline --branches rendimenti:

* b68c1f5 first evol, for making 1.0 
* 93f9f7c first commit 

Costruiamo un ramo legacy

PS D:\git\tests\mainRepo> git co -b legacy 
PS D:\git\tests\mainRepo> echo aFirstLegacyEvol >> legacy.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a first legacy evolution" 

torniamo al padrone, fare un altro commit, che verrà etichettare " 2.0" (! Un rilascio che avrà bisogno di un po 'di bug-fixing)

PS D:\git\tests\mainRepo> git co -b master 
PS D:\git\tests\mainRepo> git co master 
PS D:\git\tests\mainRepo> echo aMainEvol >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a main evol" 
PS D:\git\tests\mainRepo> echo aSecondMainEvolFor2.0 >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a second evol for 2.0" 
PS D:\git\tests\mainRepo> git tag -m "main 2.0 before bugfix" 2.0 

Abbiamo:

* e727105 a second evol for 2.0 
* 473d44e a main evol 
| * dbcc7aa a first legacy evolution 
|/ 
* b68c1f5 first evol, for making 1.0 
* 93f9f7c first commit 

Ora facciamo un bug10 bug-fixing ramo:

PS D:\git\tests\mainRepo> git co -b bug10 
PS D:\git\tests\mainRepo> echo aFirstBug10Fix >> toBeFixedFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a first bug10 fix" 
PS D:\git\tests\mainRepo> echo aSecondBug10Fix >> toBeFixedFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a second bug10 fix" 

Aggiungiamo un commit finale sul ramo principale

PS D:\git\tests\mainRepo> git co master 
PS D:\git\tests\mainRepo> echo anotherMainEvol >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "another main evol" 

stato finale della nostra repo principale:

* 55aac85 another main evol 
| * 47e6ee1 a second bug10 fix 
| * 8183707 a first bug10 fix 
|/ 
* e727105 a second evol for 2.0 
* 473d44e a main evol 
| * dbcc7aa a first legacy evolution 
|/ 
* b68c1f5 first evol, for making 1.0 
* 93f9f7c first commit 

In questa fase, non farà alcuna ulteriore manipolazione in mainRepo. Lo clonerò solo per fare alcuni test. Se falliscono, posso sempre tornare a questo repo e clonarlo di nuovo.

Il primo clone è in realtà obbligatorio, al fine di eseguire il nostro git rebase --onto

PS D:\git\tests\mainRepo> cd .. 
PS D:\git\tests> git clone mainRepo rebaseRepo 
PS D:\git\tests> cd rebaseRepo 

Abbiamo bisogno di due dei rami mainRepo nella nostra repo clonato:

PS D:\git\tests\rebaseRepo> git co -b bug10 origin/bug10 
PS D:\git\tests\rebaseRepo> git co -b legacy origin/legacy 

Diamo REBASE solo bug10 (che è tutto impegna dopo il tag 2.0 fino a HEAD della filiale bug10):

PS D:\git\tests\rebaseRepo> git co bug10 
PS D:\git\tests\rebaseRepo> git rebase --onto legacy 2.0 
First, rewinding head to replay your work on top of it... 
Applying: a first bug10 fix 
Applying: a second bug10 fix 

A questo punto bug10 è stato riprodotto in cima legacysenza tutte le altre commit intermedi.
Ora è possibile inoltrare rapidamente HEAD di legacy nella parte superiore del ramo ripetuto bug10.

PS D:\git\tests\rebaseRepo> git co legacy 
Switched to branch 'legacy' 
PS D:\git\tests\rebaseRepo> git merge bug10 
Updating dbcc7aa..cf02bfc 
Fast forward 
toBeFixedFile.txt | Bin 38 -> 104 bytes 
1 files changed, 0 insertions(+), 0 deletions(-) 

Il contenuto segui ciò che abbiamo bisogno:

  • Noi abbiamo tutti i contenuti legacy:

 

PS D:\git\tests\rebaseRepo> type legacy.txt 
legacyContent 
aFirstLegacyEvol 

 

  • il contenuto del ramo main c'è solo fino 1.0 tag (root per legacy ramo), e non ulteriormente.

 

PS D:\git\tests\rebaseRepo> type mainFile.txt 
mainFile 
firstMainEvol 

 

  • ei bug10 correzioni sono qui:

 

PS D:\git\tests\rebaseRepo> type toBeFixedFile.txt 
contentToBeFixed 
aFirstBug10Fix 
aSecondBug10Fix 

 

Questo è tutto.
L'idea è quella di tirare che 'rafforzata' legacy filiale nella vostra repo originale, che avrà ancora il suo bug10 immutato (vale a dire ancora a partire dal tag 2.0, e non riprodotti ovunque come abbiamo fatto sul rebaseRepo.
In questo repo clonato, rintraccio il ramo origin/legacy, al fine di unire su di esso il ramo legacy di un'altra fonte remota: il rebaseRepo.

PS D:\git\tests\rebaseRepo> cd .. 
PS D:\git\tests> git clone mainRepo finalRepo 
PS D:\git\tests> cd finalRepo 

PS D:\git\tests\finalRepo> git co -b legacy origin/legacy 

In questo repository originale (Ho solo clonarono che per evitare di perdere lo stato del mainRepo, nel caso avevo alcuni altri esperimenti da fare), dichiarerò rebaseRepo come un telecomando, e recuperare i suoi rami.

PS D:\git\tests\finalRepo> git remote add rebasedRepo D:/git/tests/rebaseRepo 
PS D:\git\tests\finalRepo> type D:\git\tests\finalRepo\.git\config 
[remote "origin"] 
    fetch = +refs/heads/*:refs/remotes/origin/* 
    url = D:/git/tests/mainRepo 
[branch "master"] 
    remote = origin 
    merge = refs/heads/master 
[branch "legacy"] 
    remote = origin 
    merge = refs/heads/legacy 
[remote "rebasedRepo"] 
    url = D:/git/tests/rebaseRepo 
    fetch = +refs/heads/*:refs/remotes/rebasedRepo/* 

PS D:\git\tests\finalRepo> git fetch rebasedRepo 
remote: Counting objects: 8, done. 
remote: Compressing objects: 100% (6/6), done. 
remote: Total 6 (delta 3), reused 0 (delta 0) 
Unpacking objects: 100% (6/6), done. 
From D:/git/tests/rebaseRepo 
* [new branch]  bug10  -> rebasedRepo/bug10 
* [new branch]  legacy  -> rebasedRepo/legacy 
* [new branch]  master  -> rebasedRepo/master 

Ora possiamo aggiornare legacy senza toccare a bug10:

PS D:\git\tests\finalRepo> git merge rebasedRepo/legacy 
Updating dbcc7aa..4919b68 
Fast forward 
toBeFixedFile.txt | Bin 38 -> 104 bytes 
1 files changed, 0 insertions(+), 0 deletions(-) 

È possibile ripetere la procedura tutte le volte che vuoi, ogni volta nuove bug10 commit devono essere riprodotti in cima ad un vecchio legacy filiale, senza includere tutti i commit intermedi.

+0

Devo dire WoW !, ma sono quasi confuso con i passaggi e sembra così complesso per un principiante come me. Vado solo con la modalità patch manuale. git etichetta etichetta diff ~ e poi git apply, mi sembra facile. –

+0

Alla fine di questo il ramo master non ha le modifiche bug10, giusto?Ho pensato che il poster originale (e io) volevo avere il bug10 sia nell'eredità che nel ramo principale? – huggie

+0

@huggie l'OP ha menzionato "I wan't", che, più di quattro anni fa, devo aver interpretato in modo diverso. – VonC

Problemi correlati