Capitolo 8. Gestire le release e lo sviluppo con i rami

Indice

Dare un nome persistente a una revisione
Gestire i conflitti di etichette durante un’unione
Etichette e cloni
Quando le etichette permanenti sono eccessive
Il flusso dei cambiamenti—la visione d’insieme e la visione di dettaglio
Gestire i rami nella visione d’insieme
Non ripetetevi: le unioni tra rami
Denominare i rami in un repository
Gestire molti rami con nome in un repository
I nomi di ramo e le unioni
La denominazione dei rami è generalmente utile

Mercurial vi fornisce diversi meccanismi per gestire un progetto che sta facendo progressi su più fronti contemporaneamente. Per comprendere questi meccanismi, come prima cosa daremo una breve occhiata alla struttura di un progetto software abbastanza ordinario.

Molti progetti software distribuiscono periodicamente release principali (o «maggiori») che contengono nuove funzionalità sostanziali. In parallelo, possono distribuire release secondarie (o «minori») che di solito sono identiche alle release principali su cui sono basate e in più contengono alcune correzioni di bug.

In questo capitolo, cominceremo parlando di come mantenere una registrazione delle milestone di progetto come le release, poi continueremo parlando del flusso di lavoro tra fasi differenti di un progetto e di come Mercurial può aiutarvi a isolare e gestire questo lavoro.

Dare un nome persistente a una revisione

Una volta che avete deciso che vi piacerebbe chiamare «release» una particolare revisione, è una buona idea registrare l’identità di quella revisione. Questo vi permetterà di riprodurre quella release in un momento successivo, qualsiasi sia lo scopo che avete bisogno di raggiungere in quel momento (riprodurre un bug, convertirla verso una nuova piattaforma, etc).

$ hg init miaetichetta
$ cd miaetichetta
$ echo ciao > miofile
$ hg commit -A -m "Commit iniziale."
aggiungo miofile

Mercurial vi consente di dare un nome permanente a qualsiasi revisione usando il comando hg tag. Ovviamente, questi nomi sono chiamati «etichette» (in inglese, appunto, tag).

$ hg tag v1.0

Un’etichetta non è altro che un «nome simbolico» per una revisione. Le etichette esistono puramente per la vostra convenienza: vi offrono un modo comodo e permanente per fare riferimento a una revisione. Mercurial non interpreta in alcun modo i nomi delle etichette che usate, né impone alcuna restrizione sul nome di un’etichetta a parte le poche che sono necessarie affinché l’etichetta possa essere riconosciuta senza ambiguità. Un nome di etichetta non può contenere i seguenti caratteri:

  • due punti (codice ASCII 58, «:»)

  • ritorno a capo (codice ASCII 13, «\r»)

  • nuova riga (codice ASCII 10, «\n»)

Potete usare il comando hg tags per visualizzare le etichette presenti nel vostro repository. Nel risultato del comando, ogni revisione etichettata è identificata prima dal proprio nome, poi dal numero di revisione e infine dall’hash unico della revisione.

$ hg tags
tip                                1:87dee45bf6ec
v1.0                               0:35aa95ccc713

Notate che tip viene inclusa nell’elenco mostrato da hg tags. L’etichetta tip è una speciale etichetta «mobile» che identifica sempre la revisione più recente contenuta in un repository.

Il comando hg tags elenca le etichette in ordine inverso secondo il numero di revisione. Di solito questo significa che le etichette recenti vengono elencate prima delle etichette più vecchie. Significa anche che tip è sempre la prima etichetta elencata nel risultato di hg tags.

Il comando hg log stamperà le etichette associate a ogni revisione visualizzata.

$ hg log
changeset:   1:87dee45bf6ec
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:51:18 2009 +0000
sommario:    Aggiunta l'etichetta v1.0 per il changeset 35aa95ccc713.

changeset:   0:35aa95ccc713
etichetta:   v1.0
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:51:18 2009 +0000
sommario:    Commit iniziale.

I comandi Mercurial a cui dovete passare un identificatore di revisione accetteranno il nome di un’etichetta al suo posto. Internamente, Mercurial tradurrà il nome della vostra etichetta nel corrispondente identificatore di revisione e poi userà quest’ultimo per operare.

$ echo arrivederci > miofile2
$ hg commit -A -m "Secondo commit."
aggiungo miofile2
$ hg log -r v1.0
changeset:   0:35aa95ccc713
etichetta:   v1.0
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:51:18 2009 +0000
sommario:    Commit iniziale.

Non c’è alcun limite al numero di etichette che potete avere in un repository, o al numero di etichette che una singola revisione può avere. Nella pratica, non è una grande idea averne «troppe» (un numero che varierà da progetto a progetto), semplicemente perché le etichette sono pensate per aiutarvi a rintracciare le revisioni: se avete molte etichette, la comodità di usarle per identificare le revisioni diminuisce rapidamente.

Per esempio, se il vostro progetto definisce nuove milestone con una frequenza di alcuni giorni, è perfettamente ragionevole dotare ognuna di un’etichetta. Ma se avete un sistema di assemblaggio continuo che si assicura di poter assemblare ogni revisione senza problemi, introdurreste troppo rumore etichettando ogni assemblaggio pulito. Invece, potreste etichettare gli assemblaggi falliti (supponendo che siano rari!) o semplicemente evitare di usare le etichette per tenere traccia degli assemblaggi.

Se volete rimuovere un’etichetta che non volete più, usate hg tag --remove.

$ hg tag --remove v1.0
$ hg tags
tip                                3:f0420ed65292

Potete anche modificare un’etichetta in qualsiasi momento, in modo che identifichi una revisione differente, semplicemente invocando di nuovo il comando hg tag. Dovrete usare l’opzione -f per dire a Mercurial che volete davvero aggiornare l’etichetta.

$ hg tag -r 1 v1.1
$ hg tags
tip                                4:2f0219ae190a
v1.1                               1:87dee45bf6ec
$ hg tag -r 2 v1.1
fallimento: l'etichetta 'v1.1' esiste già (usate -f per forzare)
$ hg tag -f -r 2 v1.1
$ hg tags
tip                                5:9a0bd94354ec
v1.1                               2:35418c351c2b

La precedente identità dell’etichetta rimarrà permanentemente registrata, ma Mercurial non la userà più. Quindi non c’è alcuna penalità da pagare se etichettate la revisione sbagliata, ma tutto quello che dovete fare dopo aver scoperto il vostro errore è tornare sui vostri passi ed etichettare la revisione corretta.

Mercurial memorizza le etichette nel vostro repository in un normale file soggetto al controllo di revisione. Troverete le etichette che avete creato in un file chiamato .hgtags alla radice del vostro repository. Quando eseguite il comando hg tag, Mercurial modifica questo file, poi ne effettua automaticamente il commit registrandone i cambiamenti. Questo significa che ad ogni esecuzione di hg tag corrisponderà un changeset nell’elenco mostrato da hg log.

$ hg tip
changeset:   5:9a0bd94354ec
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:51:22 2009 +0000
sommario:    Aggiunta l'etichetta v1.1 per il changeset 35418c351c2b.

Gestire i conflitti di etichette durante un’unione

Avrete raramente bisogno di preoccuparvi del file .hgtags, ma talvolta la sua presenza si farà sentire durante un’unione. Il formato del file è semplice: consiste di una serie di righe, ognuna delle quali comincia con un hash di changeset, seguito da uno spazio, seguito dal nome di un’etichetta.

Se state risolvendo un conflitto nel file .hgtags durante un’unione, c’è una particolarità da ricordare quando modificate il file .hgtags: quando Mercurial sta analizzando le etichette in un repository, non legge mai la copia di lavoro del file .hgtags, ma legge la revisione del file registrata più recentemente.

Una sfortunata conseguenza di questo comportamento è che non potete verificare la correttezza del file .hgtags risultato dall’unione se non dopo aver effettuato il commit di un cambiamento. Quindi, se vi trovate a risolvere un conflitto su .hgtags durante un’unione, assicuratevi di eseguire hg tags dopo aver effettuato il commit. Se il comando trova un errore nel file .hgtags, vi indicherà la posizione dell’errore, che potrete dunque correggere registrando la correzione nel repository. Dovreste poi eseguire ancora hg tags, giusto per essere sicuri che la vostra correzione sia valida.

Etichette e cloni

Potreste aver notato che il comando hg clone offre un’opzione -r per lasciarvi clonare la copia esatta di una particolare revisione di un repository. Il nuovo clone non conterrà alcuna cronologia del progetto registrata dopo la revisione che avete specificato. Questa operazione interagisce con le etichette in un modo che potrebbe sorprendere i più distratti.

Se ricordate, un’etichetta viene memorizzata come una revisione del file .hgtags. Quando create un’etichetta, il changeset in cui viene registrata si riferisce a un changeset precedente. Quando eseguite hg clone -r foo per clonare un repository all’etichetta foo, il nuovo clone non conterrà alcuna revisione più recente di quella a cui si riferisce l’etichetta, compresa la revisione in cui l’etichetta è stata creata. Come risultato, otterrete esattamente il sottoinsieme corretto della cronologia del progetto nel nuovo repository, ma non l’etichetta che vi sareste potuti aspettare.

Quando le etichette permanenti sono eccessive

Dato che le etichette di Mercurial sono soggette a controllo di revisione e fanno parte della cronologia del progetto, chiunque lavori con voi vedrà le etichette che avete creato. Ma i nomi delle revisioni possono essere usati in modi che vanno oltre la semplice annotazione che la revisione 4237e45506ee è in realtà la v2.0.2. Se state provando a rintracciare un bug intricato, poteste volere un’etichetta per ricordarvi di qualcosa come «Anna ha visto gli effetti del bug in questa revisione».

In casi come questo, quello che potreste voler usare sono le etichette locali. Un’etichetta locale viene creata tramite l’opzione -l del comando hg tag e viene memorizzata in un file chiamato .hg/localtags. Diversamente da .hgtags, .hg/localtags non è soggetto a controllo di revisione, quindi qualsiasi etichetta creiate usando l’opzione -l rimarrà strettamente locale al repository in cui state attualmente lavorando.

Il flusso dei cambiamenti—la visione d’insieme e la visione di dettaglio

Per ritornare allo schema abbozzato all’inizio del capitolo, consideriamo un progetto che contiene molteplici attività di sviluppo parallele in lavorazione contemporaneamente.

Potrebbero esserci attività dedicate a una nuova release principale, a una nuova release «minore» che corregge alcuni bug trovati nell’ultima release principale e a un’inattesa «correzione a caldo» di una vecchia release che ora si trova in fase di manutenzione.

Di solito, ognuna di queste direzioni di sviluppo parallele viene chiamata «ramo» (in inglese, branch). Tuttavia, abbiamo già visto più volte che Mercurial tratta tutta la cronologia come una serie di rami e unioni. In realtà, quello che abbiamo qui sono due idee marginalmente correlate che condividono casualmente lo stesso nome.

  • Nella «visione d’insieme» i rami rappresentano il flusso dell’evoluzione di un progetto. Ognuno di questi rami ha il proprio nome ed è oggetto di conversazione tra gli sviluppatori.

  • Nella «visione di dettaglio» i rami sono artefatti costruiti durante l’attività quotidiana di sviluppo e unione dei cambiamenti. Questi rami narrano la storia di come il codice è stato sviluppato.

Gestire i rami nella visione d’insieme

Nella «visione d’insieme», il modo più facile per isolare un ramo in Mercurial è quello di utilizzare un repository dedicato. Se avete un repository condiviso esistente—chiamiamolo mioprogetto—che raggiunge una milestone «1.0», potete cominciare a preparare le future release di manutenzione basate sulla versione 1.0 etichettando la revisione dalla quale avete preparato la release 1.0.

$ cd mioprogetto
$ hg tag v1.0

Potete quindi clonare un nuovo repository condiviso mioprogetto-1.0.1 a partire da quella etichetta.

$ cd ..
$ hg clone mioprogetto mioprogetto-1.0.1
aggiorno la directory di lavoro
2 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti

Successivamente, chi ha bisogno di lavorare sulla correzione di un bug che dovrebbe essere contenuta in una prossima release «minore» 1.0.1 potrà clonare il repository mioprogetto-1.0.1, fare le proprie modifiche e poi trasmetterle a quel repository.

$ hg clone mioprogetto-1.0.1 mia-correzione-1.0.1
aggiorno la directory di lavoro
2 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti
$ cd mia-correzione-1.0.1
$ echo 'Ho corretto un bug usando solo echo!' >> miofile
$ hg commit -m "Importante correzione per la versione 1.0.1."
$ hg push
trasmetto a /tmp/mioprogetto-1.0.1
cerco i cambiamenti
aggiungo i changeset
aggiungo i manifest
aggiungo i cambiamenti ai file
aggiunti 1 changeset con 1 cambiamenti a 1 file

Nel frattempo, lo sviluppo della prossima release principale può continuare, isolato e ininterrotto, nel repository mioprogetto.

$ cd ..
$ hg clone mioprogetto mia-funzione
aggiorno la directory di lavoro
2 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti
$ cd mia-funzione
$ echo 'Questa è sicuramente una nuova ed eccitante funzione!' > mionuovofile
$ hg commit -A -m "Nuova funzione."
aggiungo mionuovofile
$ hg push
trasmetto a /tmp/mioprogetto
cerco i cambiamenti
aggiungo i changeset
aggiungo i manifest
aggiungo i cambiamenti ai file
aggiunti 1 changeset con 1 cambiamenti a 1 file

Non ripetetevi: le unioni tra rami

In molti casi, se avete un bug da correggere su un ramo di manutenzione, è probabile che il bug sia presente anche sul ramo principale del progetto (e magari anche su altri rami di manutenzione). È raro che uno sviluppatore voglia correggere lo stesso bug più volte, quindi diamo un’occhiata ad alcuni modi in cui Mercurial può aiutarvi a gestire queste correzioni senza duplicare il vostro lavoro.

Nel caso più semplice, tutto quello che dovete fare è propagare i cambiamenti dal vostro ramo di manutenzione al vostro clone locale del ramo di destinazione.

$ cd ..
$ hg clone mioprogetto mioprogetto-unione
aggiorno la directory di lavoro
3 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti
$ cd mioprogetto-unione
$ hg pull ../mioprogetto-1.0.1
estraggo da ../mioprogetto-1.0.1
cerco i cambiamenti
aggiungo i changeset
aggiungo i manifest
aggiungo i cambiamenti ai file
aggiunti 1 changeset con 1 cambiamenti a 1 file (+1 teste)
(eseguite 'hg heads' per vedere le teste, 'hg merge' per unire)

Poi dovrete unire le teste dei due rami e trasmettere i cambiamenti al ramo principale.

$ hg merge
1 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti
(unione tra rami, ricordatevi di eseguire il commit)
$ hg commit -m "Incorpora la correzione dal ramo 1.0.1."
$ hg push
trasmetto a /tmp/mioprogetto
cerco i cambiamenti
aggiungo i changeset
aggiungo i manifest
aggiungo i cambiamenti ai file
aggiunti 2 changeset con 1 cambiamenti a 1 file

Denominare i rami in un repository

Nella maggior parte dei casi, isolare ogni ramo in un proprio repository è l’approccio giusto, perché la sua semplicità lo rende facile da capire e quindi è difficile commettere errori. Esiste una relazione uno-a-uno tra i rami in cui state lavorando e le directory sul vostro sistema che vi consente di usare strumenti ordinari (ignari dell’esistenza di Mercurial) per lavorare sui file all’interno di un ramo/repository.

Se invece appartenete alla categoria degli «utenti avanzati» (e vi appartengono anche i vostri collaboratori), potete considerare un modo alternativo di gestire i rami. Ho già menzionato la distinzione con cui gli sviluppatori percepiscono i rami nella «visione di dettaglio» e nella «visione d’insieme». Se Mercurial lavora con molteplici rami «di dettaglio» alla volta in un repository (per esempio dopo che avete propagato i cambiamenti, ma prima di incorporarli), può anche lavorare con molteplici rami «d’insieme».

La chiave per lavorare in questo modo è che Mercurial vi permette di assegnare un nome persistente a un ramo. In ogni repository c’è sempre un ramo chiamato default. Anche prima che cominciate a creare voi stessi nuovi rami con il proprio nome, potete trovare tracce del ramo default se le cercate.

Per esempio, quando eseguite il comando hg commit e vi viene presentato un editor in modo che possiate inserire un messaggio di commit, cercate una riga che contiene il testo «HG: ramo default» verso il fondo. Questo comando vi informa che il vostro commit avverrà sul ramo chiamato default.

Per cominciare a lavorare con i rami con nome, usate il comando hg branches. Questo comando elenca i rami con nome già presenti nel vostro repository, dicendovi quale changeset è in cima a ognuno di loro.

$ hg tip
changeset:   0:fc8fb1089cc0
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:48:56 2009 +0000
sommario:    Commit iniziale.

$ hg branches
default                        0:fc8fb1089cc0

Dato che non avete ancora creato alcun ramo con nome, l’unico ramo esistente è default.

Per trovare qual è il ramo «attuale», eseguite il comando hg branch senza passargli alcun argomento. Otterrete il nome del ramo in cui trova il genitore del changeset corrente.

$ hg branch
default

Per creare un nuovo ramo, eseguite ancora il comando hg branch. Questa volta, passategli un argomento: il nome del ramo che volete creare.

$ hg branch foo
la directory di lavoro è stata contrassegnata come ramo foo
$ hg branch
foo

Dopo che avete creato un ramo, potreste chiedervi qual è stato l’effetto del comando hg branch. Che cosa ci dicono i comandi hg status e hg tip?

$ hg status
$ hg tip
changeset:   0:fc8fb1089cc0
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:48:56 2009 +0000
sommario:    Commit iniziale

Nulla è cambiato nella directory di lavoro e non è stata creata nuova cronologia. Come queste osservazioni suggeriscono, il comando hg branch non ha alcun effetto permanente, ma si limita a dire a Mercurial quale nome di ramo usare la prossima volta che effettuerete il commit di un changeset.

Quando inserite un cambiamento nel repository, Mercurial registra il nome del ramo su cui lo avete inserito. Una volta che siete passati dal ramo default a un altro e avete eseguito il commit, vedrete apparire il nome del nuovo ramo nel risultato di hg log, hg tip e altri comandi che mostrano lo stesso tipo di informazioni.

$ echo 'ancora ciao' >> miofile
$ hg commit -m "Secondo commit."
$ hg tip
changeset:   1:b15761055392
ramo:        foo
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:48:59 2009 +0000
sommario:    Secondo commit.

I comandi come hg log stamperanno il nome del ramo di ogni changeset che non appartiene al ramo default. Come risultato, se non avete mai usato i rami con nome, non vedrete mai questa informazione.

Una volta che avete denominato un ramo e inserito un cambiamento in quel ramo, ogni commit successivo che discende da quel cambiamento erediterà lo stesso nome di ramo. Potete cambiare il nome a un ramo in ogni momento, usando il comando hg branch.

$ hg branch
foo
$ hg branch bar
la directory di lavoro è stata contrassegnata come ramo bar
$ echo nuovo file > nuovofile
$ hg commit -A -m "Terzo commit."
aggiungo nuovofile
$ hg tip
changeset:   2:4dce38140953
ramo:        bar
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:49:00 2009 +0000
sommario:    Terzo commit.

In pratica, questa non è una cosa che farete molto spesso, dato che i nomi di ramo tendono ad avere un tempo di vita piuttosto lungo. (Questa non è una regola, ma solo un’osservazione.)

Gestire molti rami con nome in un repository

Se un repository contiene più di un ramo con nome, Mercurial ricorderà il ramo su cui si trova la vostra directory di lavoro quando eseguite un comando come hg update o hg pull -u e aggiornerà la directory di lavoro alla revisione di punta di quel ramo, a prescindere da quale sia la punta dell’intero repository. Per aggiornare la directory di lavoro a una revisione che si trova su un ramo con un nome diverso, potreste dover usare l’opzione -C del comando hg update.

Questo comportamento è leggermente complicato, quindi vediamolo in azione. Per prima cosa, controlliamo su quale ramo ci troviamo al momento e quali sono i rami contenuti nel nostro repository.

$ hg parents
changeset:   2:4dce38140953
ramo:        bar
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:49:00 2009 +0000
sommario:    Terzo commit.

$ hg branches
bar                            2:4dce38140953
foo                            1:b15761055392 (inattivo)
default                        0:fc8fb1089cc0 (inattivo)

Ci troviamo sul ramo bar, ma esiste anche un ramo più vecchio chiamato foo.

Possiamo utilizzare hg update per spostarci avanti e indietro tra le revisioni di punta dei rami foo e bar senza aver bisogno di impiegare l’opzione -C, perché questi spostamenti avvengono linearmente attraverso la nostra cronologia dei cambiamenti.

$ hg update foo
0 file aggiornati, 0 file uniti, 1 file rimossi, 0 file irrisolti
$ hg parents
changeset:   1:b15761055392
ramo:        foo
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:48:59 2009 +0000
sommario:    Secondo commit.

$ hg update bar
1 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti
$ hg parents
changeset:   2:4dce38140953
ramo:        bar
etichetta:   tip
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:49:00 2009 +0000
sommario:    Terzo commit.

Se torniamo indietro al ramo foo e invochiamo hg update, il comando ci manterrà su foo piuttosto che spostarci alla punta di bar.

$ hg update foo
0 file aggiornati, 0 file uniti, 1 file rimossi, 0 file irrisolti
$ hg update
0 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti

Il commit di una nuova modifica sul ramo foo introduce una nuova testa.

$ echo qualcosa > qualchefile
$ hg commit -A -m "Nuovo file."
aggiungo qualchefile
creata una nuova testa
$ hg heads
changeset:   3:859c842ea668
ramo:        foo
etichetta:   tip
genitore:    1:b15761055392
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:49:04 2009 +0000
sommario:    Nuovo file.

changeset:   2:4dce38140953
ramo:        bar
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:49:00 2009 +0000
sommario:    Terzo commit.

I nomi di ramo e le unioni

Come avete probabilmente notato, le unioni in Mercurial non sono simmetriche. Diciamo che il nostro repository possiede due teste, 17 e 23. Se uso hg update per aggiornare alla 17 e poi eseguo hg merge per incorporare la 23, Mercurial registra la 17 come primo genitore dell’unione e la 23 come secondo. Ma se uso hg update per aggiornare alla 23 e poi eseguo hg merge per incorporare la 17, Mercurial registra la 23 come primo genitore e la 17 come secondo.

Questo comportamento influenza la scelta del nome di ramo compiuta da Mercurial quando effettuate un’unione. Dopo un’unione, Mercurial manterrà il nome del ramo del primo genitore quando registrate i risultati dell’unione. Se il nome del ramo del primo genitore è foo e unite quel ramo con bar, dopo l’unione il nome del ramo in cui vi troverete sarà ancora foo.

Capita spesso che un repository contenga più teste, ognuna con lo stesso nome di ramo. Diciamo che io sto lavorando sul ramo foo e così fate anche voi. Eseguiamo il commit di cambiamenti differenti, dopodiché io estraggo i vostri cambiamenti e mi ritrovo con due teste, ognuna che dichiara di appartenere al ramo foo. Sperabilmente, il risultato di un’unione sarà una singola testa sul ramo foo.

Ma se io sto lavorando sul ramo bar e incorporo il lavoro dal ramo foo, il risultato rimarrà sul ramo bar.

$ hg branch
bar
$ hg merge foo
1 file aggiornati, 0 file uniti, 0 file rimossi, 0 file irrisolti
(unione tra rami, ricordatevi di effettuare il commit)
$ hg commit -m "Unione."
$ hg tip
changeset:   4:f50f493d0dc0
ramo:        bar
etichetta:   tip
genitore:    2:4dce38140953
genitore:    3:859c842ea668
utente:      Bryan O'Sullivan <[email protected]>
data:        Fri Jun 05 15:49:06 2009 +0000
sommario:    Unione.

Per farvi un esempio più concreto, se sto lavorando sul ramo sperimentale e voglio incorporare le ultime correzioni dal ramo stabile, Mercurial sceglierà il nome del ramo «corretto» (sperimentale) quando estrarrò e incorporerò i cambiamenti da stabile.

La denominazione dei rami è generalmente utile

Non dovreste pensare che i rami con nome si possano utilizzare solo in situazioni dove avete molteplici rami di lunga data che coabitano in un singolo repository. Sono molto utili anche nel caso in cui utilizziate un singolo ramo per repository.

Nel caso più semplice, dare un nome a ogni ramo vi offre una registrazione permanente dell’identità del ramo da cui un changeset ha avuto origine. Questo vi fornisce un contesto più ampio quando state cercando di seguire la cronologia di un progetto ramificato di lunga data.

Se state lavorando con repository condivisi, potete impostare un hook pretxnchangegroup su ogni repository in modo da bloccare i cambiamenti in entrata che appartengono al nome di ramo «sbagliato». Questo accorgimento vi offre una difesa semplice ma efficace nei confronti di chi trasmette accidentalmente i cambiamenti da un ramo «sperimentale» a un ramo «stabile». Un hook di questo tipo potrebbe somigliare al seguente, contenuto all’interno del file /.hgrc del repository condiviso.

[hooks]
pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mioramo

Volete rimanere aggiornati? Abbonatevi al feed delle modifiche per il libro italiano.

Copyright 2006, 2007, 2008, 2009 Bryan O’Sullivan. Icone realizzate da Paul Davey alias Mattahan.

Copyright 2009 Giulio Piancastelli per la traduzione italiana.