.. _mercurial: =================== 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 eseguito ``hg 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_ .. _evolve: https://www.mercurial-scm.org/doc/evolution/user-guide.html .. _topics: https://fluiddyn.readthedocs.io/en/latest/mercurial_heptapod.html .. _absorbe: https://gregoryszorc.com/blog/2018/11/05/absorbing-commit-changes-in-mercurial-4.8/ .. _`sui topics`: https://www.mercurial-scm.org/doc/evolution/tutorials/topic-tutorial.html .. _Heptapod: https://heptapod.net/pages/faq.html .. https://www.gerg.ca/evolve/concepts.html 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: a. Se il branch include delle migrazioni b. 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) .. note:: 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 | 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 | 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 | | 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 | | 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 | 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 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 | 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 | 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 | 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 | 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 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 | 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 | 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 | 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 | 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 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.