Mercurial workflow¶
Imparare un flusso di lavoro che permetta la condivisione del codice fra colleghi in modalità idonea alla revisione del codice.
In particolare saranno di grande aiuto le seguenti estensioni/comandi:
topics
histedit
absorb
Gran parte delle cose che presento si basano sulla alcuni concetti:
- fasi
mercurial distingue i commit in base alla fase, la vedete anche in tortoisehg. Quando un commit viene creato (localmente) è in fase
draft
, quando in seguito viene eseguitohg push
il file viene considerato pubblico. Esiste la possibilità di create un repository «non pubblico» per cui il changeset non diventi pubblico- code-review
è la possibilità di commentare del codice altrui e suggerire miglioramenti. È auspicabile che poi i «balbettamenti» non finiscano nel codice finale.
I topics sono un nuovo modello di branching che viene implementata da heptapod che si basa sulla possibilità di condividere codice in fase draft.
Suggerimenti di letture¶
La introduzione ufficiale all’estensione evolve
La introduzione ufficiale all’estensione [evolve](https://www.mercurial-scm.org/doc/evolution/user-guide.html)
una semplice introduzione pragmatica ai topics
un’introduzione alla funzione absorbe
un lungo tutorial, ma molto asciutto, sui topics
La FAQ principale di Heptapod
Linee guida¶
Dal momento che in questo modo è possibile correggere quello che si pubblica, vi consigliamo di pubblicare spesso in modo da dare la possibilità ai colleghi di commentare il codice.
È importante che si tengano presente in modo ferreo alcune regole importanti:
I commit devono essere atomici ovvero devono ciascuno contenere un solo punto (topic, appunto), ma nello stesso tempo deve contenere tutto quello che questo topic richiede.
Ad esempio, se serve documentazione (sia generica sia nelle docstring delle funzioni) deve essere presente nello stesso commit del codice. Idem, quando vengono fatti per i test / remote test.
Richiesta di merge: una volta pronti deve essere fatta la richesta di merge, basta seguire il link generato in automatico dal push (che altrimenti ignorate). Aprite il link dal terminale al solito con click destro.
È importante che compiliate nella pagina che vi compare gli assegnatari (presumibilmente il vostro responsabile e Vitto che dopo la prima fase deciderà se continuare a ricevere…
È importante -per progetti Django- chiarire nel messaggio di merge almeno 2 cose:
Se il branch include delle migrazioni
Se il branch aggiunge delle dipendenze
Alcuni suggerimenti pratici¶
Q: come mai il repo locale non è imparentato con quello da cui avevo clonato?¶
È importante che il primo commit sia già public
e non draft
. Il motivo è
banalmente che potrete non essere in grado di committare le modifiche se viene
reso obsoleto il primo changeset che quindi di fatto cambia. È importante che
esista almeno un antenato comune nel momento in cui fate push
.
Per comprendere quanto sopra ricordo che ogni volta che facciamo un amend
(ma la stessa cosa vale per histedit, absorb e simili) di fatto si genera un
nuovo commit che sostituisce il primo. Se fate questo al primo commit di fatto
nascondete il commit comune con il repository remoto e quindi vi trovereste
nella situazione in cui il remoto non è imparentato con il locale.
Per ovviare a questa situazione suggerisco di fare sempre un primo commit, che banalmente potrebbe essere .hgignore che facilmente è il medesimo per tutti i progetti.
Q: Come convertire in topics una stack (non ancora pubblicata)?¶
Il comando topics
ha un’opzione -r che può avere come argomento il range (con
::) che si vuole tramutare in topic.:
hg topic -r sx::sy topic-name
Q: Come fare il merge di un topic se non ci son biforcazioni?¶
In questa situazione non si riesce a fare merge
, verrà fuori il messaggio
che non c’è nulla da «mergiare». È suff. rendere pubblic le parti
interessate:
hg phase -r sx::sy --publish
o alternativamente se si prevede di pubblicare:
hg push --publish [-t topic_name]
Q: Come eliminare un topic condiviso ma errato?¶
Se avete creato e poi condiviso un topic che però deve essere eliminato (ad
esempio perché bocciato), potete usare il comando hg prune
:
hg prune -r "topic(nome-de-topic)"
hg push
Faccio notare che "topic(nome-de-topic)"
è un modo molto efficace di produrre
la lista dei commit che appartengono a quel topic. Potremmo anche eliminare solo
alcuni changeset, ad esempio:
sandro@bluffx:/tmp/tut$ hg s
### topic: sd
### target: default (branch)
s4@ quattro (current)
s3: tre
s2: due
s1: uno
s0^ provay (base)
sandro@bluffx:/tmp/tut$ hg prune -r s2:s4
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
working directory is now at 95cc7b2dfb9e
3 changesets pruned
sandro@bluffx:/tmp/tut$ hg s
### topic: sd
### target: default (branch)
s1@ uno (current)
s0^ provay (base)
Nota
Quando non funziona…
Esistono delle circostanze in cui hg non si accorge del marker che
invalida il topic (obsolescce marker), i quel caso è necessario fare
nuovamente push del changeset padre di quello da cui nasceva il topic.
Per trovarlo può essere necessario usare hg log --hidden
Q: come inviare solo un topic sul repo condiviso?¶
Esistono 2 possibilità:
hg push -t my_topic
Q: Fallisce hg in
¶
Questo si risolve facendo prima hg pull
. A mio avviso succede quando la
struttura dati interna è stata fatta da mercurial pre 5 senza topics. Una volta
fatto hg pull
viene aggiornata e l’errore sparisce.
Q: come eliminare dei file capitati erroneamente in un commit?¶
Basta eliminarlo usando hg amend
:
hg amend --extract file-or-directory [file-or-directory ...]
Quel file rimarrà nella working directory e quindi andrà gestito (ad esempio creando un commit per lui, o eliminandolo). Supponiamo voi creiate un nuovo commit per questo:
$ mkdir /tmp/test && cd /tmp/test $ hg init $ touch .hgignore $ hg ci -A -m hgignore $ hg topics conta $ touch uno due tre otto $ hg ci -Am «init» $ touch quter cinq $ hg ci -Am «altro giro» $ touch ses sett $ hg ci -Am «ultimo arrivato paga da bere» $ hg up s1 $ hg stack ### topic: conta ### target: default (branch) s3: ultimo arrivato paga da bere s2: altro giro s1@ init (current) s0^ hgignore (base)
$ hg st –ch . A due A otto A tre A uno
$ hg amend –extract otto 2 new orphan changesets $ hg st A otto
La nostra correzione ha lasciato il file otto
aggiunto da committare ma ha
anche cambiato i due commit successivi che quindi sono ora orfani, indicato
dal $
nella stack:
$ hg stack
### topic: conta
### target: default (branch)
s3$ ultimo arrivato paga da bere (orphan)
s2$ altro giro (orphan)
s1@ init (current)
s0^ hgignore (base)
Ci occupiamo anzitutto del file da committare:
hg ci -m "otto"
che ci porta in una situazione biforcata:
$ hg log
@ changeset: [draft] 5 : d9ae185e86b6 default [#conta] tip
| node: d9ae185e86b68a5f716b55c868bf3845308806fa
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:55:46 +0100 (2 seconds ago)
| summary: otto
|
o changeset: [draft] 4 : 572ee3d89198 default [#conta]
| node: 572ee3d891986a5c3490b18d1d64530a3927e15f
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (12 minutes ago)
| summary: init
|
| * changeset: [draft] 3 : dacdfc8e209a default [#conta]
| | node: dacdfc8e209a75ae660273b2f9ad73aad23ec200
| | author: Sandro Dentella <adentella@thux.it>
| | date: Mon, 23 Mar 2020 19:43:38 +0100 (12 minutes ago)
| | summary: ultimo arrivato paga da bere
| |
| * changeset: [draft] 2 : 0b82bf9cdc53 default [#conta]
| | node: 0b82bf9cdc53b8f85b172bcf767159e7ff3af46d
| | author: Sandro Dentella <adentella@thux.it>
| | date: Mon, 23 Mar 2020 19:43:38 +0100 (12 minutes ago)
| | summary: altro giro
| |
| x changeset: [draft] 1 : 0190f266a5c7 default [#conta]
|/ node: 0190f266a5c7dc00bbc05a97e25b462bd402038c
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (12 minutes ago)
| summary: init
|
o changeset: [draft] 0 : 4d506ac20847 default
node: 4d506ac20847a463a15e049734f4b9441e25af7d
author: Sandro Dentella <adentella@thux.it>
date: Mon, 23 Mar 2020 19:43:37 +0100 (12 minutes ago)
summary: hgignore
che sistemeremo in 2 mosse::
$ hg evolve
$ hg log
o changeset: [draft] 7 : bb9b54592e7b default [#conta] tip
| node: bb9b54592e7b412617784e5deb68d72eada4f320
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (13 minutes ago)
| summary: ultimo arrivato paga da bere
|
o changeset: [draft] 6 : 3d788e78fe92 default [#conta]
| node: 3d788e78fe92933f177e7bf420f1f382e9ed8721
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (13 minutes ago)
| summary: altro giro
|
| @ changeset: [draft] 5 : d9ae185e86b6 default [#conta]
|/ node: d9ae185e86b68a5f716b55c868bf3845308806fa
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:55:46 +0100 (67 seconds ago)
| summary: otto
|
o changeset: [draft] 4 : 572ee3d89198 default [#conta]
| node: 572ee3d891986a5c3490b18d1d64530a3927e15f
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (13 minutes ago)
| summary: init
|
o changeset: [draft] 0 : 4d506ac20847 default
node: 4d506ac20847a463a15e049734f4b9441e25af7d
author: Sandro Dentella <adentella@thux.it>
date: Mon, 23 Mar 2020 19:43:37 +0100 (13 minutes ago)
summary: hgignore
Ora vedete che non esistono più orfani: in questa visualizzazione non ci son più
*
o x
. Esiste però una biforcazione che sistemiamo subito:
$ hg rebase [ -d tip ]
rebasing 5:d9ae185e86b6 "otto" (conta)
sandro@bluffx:/tmp/test$ hg log
@ changeset: [draft] 8 : 9697e04af32a default [#conta] tip
| node: 9697e04af32a3fe2333ae54e04d4c6a5e39b27e4
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:55:46 +0100 (7 minutes ago)
| summary: otto
|
o changeset: [draft] 7 : bb9b54592e7b default [#conta]
| node: bb9b54592e7b412617784e5deb68d72eada4f320
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (19 minutes ago)
| summary: ultimo arrivato paga da bere
|
o changeset: [draft] 6 : 3d788e78fe92 default [#conta]
| node: 3d788e78fe92933f177e7bf420f1f382e9ed8721
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (19 minutes ago)
| summary: altro giro
|
o changeset: [draft] 4 : 572ee3d89198 default [#conta]
| node: 572ee3d891986a5c3490b18d1d64530a3927e15f
| author: Sandro Dentella <adentella@thux.it>
| date: Mon, 23 Mar 2020 19:43:38 +0100 (19 minutes ago)
| summary: init
|
o changeset: [draft] 0 : 4d506ac20847 default
node: 4d506ac20847a463a15e049734f4b9441e25af7d
author: Sandro Dentella <adentella@thux.it>
date: Mon, 23 Mar 2020 19:43:37 +0100 (19 minutes ago)
summary: hgignore
Tutto è in ordine, otto che si era maldestramente infilato nel changeset
iniziale è tornato dopo gli altri (e paga da bere). Abbiamo ordinato i commit
con un rebase invece che un hg histedit
, ma avremmmo anche potuto fare
diversamente.