Unire due rami

I rami in Git sono stati concepiti originariamente per avere una vita relativamente breve. Il loro scopo dovrebbe essere quello di ospitare versioni in release, beta e hotfix alla versione principale. Se stessimo sviluppando un App o un sito, il ramo master dovrebbe idealmente ospitare l’ultima versione di produzione, cioè quella che gli utenti usano.

Unire due rami completa il loro ciclo di vita, che parte dalla creazione fino ad appunto la loro fusione in un altro ramo. È quindi logico che Git offra una funzione avanzata di fusione tra rami, cioè quella di merge . Il comando base per effettuare una funzione è git merge <nome> . Nell’esempio del precedente capitolo, abbiamo creato il ramo test , abbiamo creato un nuovo commit, adesso siamo pronti per unirlo al ramo principale master :

git merge test

Eseguendo questo comando, nella storia del repository, questa fusione non ci sarà. È utile, spesso, avere una traccia di questa unione. Usando l’opzione –no-ff  diciamo a Git di creare un commit relativo a questo merge così da poterla identificare in futuro.

git merge --no-ff test

Attenzione: il ramo test verrà unito al ramo attuale, cioè quello nel quale stiamo lavorando. Come abbiamo visto, dobbiamo usare il comando git checkout <ramo> . L’operazione completa sarà quindi:

$ git checkout master
Switched to branch 'master'
$ git merge test
Updating 14f3ced..dc8c7f7
Fast-forward
 nuovofile.txt                         | 0
 file2.txt | 2 +-
 2 files changed, 1 insertion(+), 1 deletion(-)
 create mode 100644 nuovofile.txt

La fusione è andata a buon fine, possiamo in questo caso cancellare il ramo test  con il comando:

git branch -d test

Come fa Git a determinare la fusione? Innanzitutto determina in modo automatico il miglior commit genitore di entrambi i rami e, sempre automaticamente, utilizza l’algoritmo migliore per fondere i file.

Risolvere un conflitto

Potrebbe capitare che tutta quest’automazione non vada a buon fine, specialmente se abbiamo fatto modifiche allo stesso file in più rami che sono in conflitto tra di loro. Git non sarà in grado di gestire la fusione del file modo pulito. Nel caso succeda, ci avverte in questo modo:

$ git merge test
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.

Fin tanto che il conflitto ci sarà, la fusione tra rami non avverrà. Vediamo come risolvere il conflitto. Nel nostro caso, Git ci dice che il file file.txt  ha qualche problema. Se proviamo a modificare il file, troveremo che sono state aggiunte delle righe simili a queste:

<<<<<<< HEAD:test.txt
Alice cominciava a sentirsi assai stanca di sedere sul poggetto accanto a sua sorella, senza far
niente: aveva una o due volte data un'occhiata al libro che la sorella stava leggendo, ma non v'erano
né dialoghi né figure, - e a che serve un libro, pensò Alice, - senza dialoghi né figure?
=======
La buca della conigliera filava dritta come una galleria, e poi si sprofondava così improvvisamente
che Alice non ebbe un solo istante l'idea di fermarsi: si sentì cader giù rotoloni in una specie di
precipizio che rassomigliava a un pozzo profondissimo.
>>>>>>> test:test.txt

Cosa significa? In sostanza che il testo compreso tra <<<<<<<  e =======  è quello che avevamo nel ramo principale, ma che nel momento della fusione Git ha trovato il testo compreso tra =======  e >>>>>>>  nel ramo test  e non ha saputo cosa fare. Non ci resta che risolvere manualmente il conflitto modificando questa zona del file, salvare e usare git add test.txt  per dirgli: hey, il conflitto è stato risolto! Successivamente diamo un git commit  per completare la fusione precedentemente iniziata:

Merge branch 'test'
Conflicts: test.txt
#
# It looks like you may be committing a MERGE.
# If this is not correct, please remove the file
# .git/MERGE_HEAD # and try again.
#

Vedere una lista dei rami non uniti

 

In precedenza, abbiamo visto come avere una lista dei rami presenti nel repository. Se volessimo però visualizzare quelli non fusi nel ramo attuale, possiamo usare git branch –no-merged :

git branch --no-merged