Usare Bazaar con un repository centrale su disco esterno

Ho sempre usato Bazaar tenendo il database delle revisioni nella stessa directory di lavoro del progetto, e la cosa non è sbagliata perché questo sistema di controllo di versione è stato pensato proprio così. Mi sono sempre trovato bene, ma ciò che mi sarebbe piaciuto era avere un unico archivio centrale dove tenere i database di tutti i progetti (idea che è nata dopo aver provato SVN); precisamente mi sarebbe piaciuto su un disco esterno, in modo da rendere più difficile la perdita dei dati in caso di crash o altro.

In questi ultimi tempi ho anche provato Subversion, che mi è piaciuto per il suo rigore nello struttura delle working directory (branches, tags, trunk) e per la filosofia di repository centrale, che mi è piaciuta davvero. Di contro non mi è proprio piaciuta la consuetudine di infilare una directory nascosta .svn in ogni dove nel progetto. Non ho però una seria esperienza di Subversion per poterlo giudicare, ma mi è apparso comunque un pelino schizzinoso rispetto a Bazaar,1 che invece apprezzo per la sua facilità e… direi “umanità”, proprio nello stile di Ubuntu, visto che anche lui è sponsorizzato da Canonical.

Con un po’ di pazienza e avendo in mente di creare un repository di progetti su un disco esterno, mi sono spulciato la documentazione ufficiale di Bazaar, in cui ho trovato le informazioni che mi servivano.

Ecco le mie note personali su quello che ho fatto. Non prendetele come una guida all’uso, ma come una condivisione di esperienza che sicuramente ha lati non chiari per me. Anzi, se avete da correggere quanto scrivo, discutiamone pure nei commenti.

Inizializzare il repository centrale sul disco esterno

Sul mio disco esterno USB ho creato una directory bzr-repo, una sorta di contenitore: in essa metterò tutti i progetti, uno in ogni sua sottodirectory:

bzr-repo       # contenitore centrale
+- progetto1   # directory progetto 1
+- progetto2   # directory progetto 2
+- progetto3   # directory progetto 3
...

Questa è l’idea. L’unica directory che ho creato finora è bzr-repo. Le dipendenti le creeremo con bazaar. Da terminale diamo:

bzr init-repo --no-trees file:///media/Golia/Aldo/bzr-repo/

L’opzione --no-trees dice a Bazaar che in quel repository non si terranno le copie di lavoro (working copy) dei file, ma solo il database con la loro storia.

Questo comando va dato ovviamente una sola volta per tutti i progetti.

Creare la directory del progetto 1

Quello che segue va fatto per ogni progetto che si vuole collegare al repository centrale.

Inizializziamo la directory del primo progetto:

bzr init file:///media/Golia/Aldo/bzr-repo/progetto1

Questo comando creerà la directory progetto1 con all’interno una nascosta .bzr.

Creare la directory di lavoro locale e collegarla al repository

Col repository abbiamo finito. Passiamo ora in locale e creiamo la struttura delle directory di lavoro (immaginiamo di voler tenere i progetti nella directory progetti nella propria /home), quelle in cui terremo le working copy. Per essere chiari, ecco cosa ho in mente di creare:

progetti           # contenitore generale
 +- progetto-uno   # directory principale progetto 1
 |  +- releases    # directory con i tarball dei rilasci
 |  +- trunk       # directory di sviluppo
 |
 +- progetto-due   # directory principale progetto 2
 |  +- releases    # directory con i tarball dei rilasci
 |  +- trunk       # directory di sviluppo
 …```

Questa struttura è quella che ho scelto io: ognuno può organizzarsi come meglio crede. Immagino sia semplice capire l’uso delle directory in base ai commenti.

Passiamo all’opera nel terminale:

cd ~/
mkdir progetti
mkdir progetti/progetto1
cd progetti/progetto1

Colleghiamo (facciamo in realtà il checkout su) questa directory con quella relativa all’interno del repository:

bzr co file:///media/Golia/Aldo/bzr-repo/progetto1/ trunk

Questo comando creerà la directory trunk (quella in cui terremo fisicamente i file di lavoro) dentro progetti/progetto1. Se ora la aprite, vedrete la solita directory .bzr per il controllo.
Passiamo ora in trunk:

cd trunk/

Possiamo già iniziare a creare i nostri file e a lavorare.

Se invece abbiamo già un progetto in corso non ancora sotto controllo di versione, copiamo tutti i file e tutte le directory qui dentro:

cp -ar ~/vecchia-directory/* .

Ora che abbiamo copiato i file, Bazaar ancora non sa cosa siano, quindi aggiungiamoli:

bzr add

e Bazaar li aggiungerà tutti, comprese le sottodirectory e il loro contenuto. Fatto ciò, eseguiamo il nostro primo commit (cioè inviamo il tutto al repository centrale):

bzr commit -m "Primo upload"

che possiamo anche scrivere con l’alias ci:

bzr ci -m "Primo upload"

L’acronimo ci sta per check-in.

Abbiamo finito con l’impostare database e directory di lavoro. Chiunque, adesso, se il disco è accessibile in rete, può scaricare la propria copia del progetto1 e lavorarci; ad esempio, in una rete dove è attiva una connessione SSH, si può lanciare un comando del tipo:

mkdir mia-directory-di-lavoro/progetto1
bzr co sftp://aldo@192.168.1.2/Aldo/bzr-repo/progetto1/

Questo comando si tirerà dietro tutta la storia del progetto. Se non lo si desidera, si può scaricare solo il progetto:

bzr co --lightweight sftp://aldo@192.168.1.2/Aldo/bzr-repo/progetto1/

Commit delle modifiche

I paragrafi che seguono sono soltanto un promemoria rapido per alcune operazioni comuni con Bazaar. Vediamo la principale: il commit.

Dopo ogni serie di modifiche correlate, eseguire il commit con:

bzr ci -m "Descrizione della modifica"

Commit locale se il repository è irraggiungibile

Qualora stiamo lavorando offline, lontano dal disco esterno, possiamo eseguire i commit localmente (cioè nel database locale presente nella directory trunk/) e poi inviare tutte le modifiche in una volta al repository. Ecco come cambia il comando:

bzr ci --local -m "Descrizione delle modifiche"

Quando il repository sarà di nuovo raggiungibile, possiamo inviarle così:

bzr update

e quindi il commit

bzr ci -m "Descrizione delle modifiche"

Il comando update esegue il merging delle revisioni, diciamo una “ri-unione” delle versioni tra quelle del repository e quelle del database locale. Questo perché Bazaar considera il lavoro offline come se fosse una nuovo linea di sviluppo (nello screenshot più sotto si vede graficamente questo concetto).

Taggare una versione

Periodicamente è bene taggare (etichettare) una revisione del lavoro, magari in concomitanza di un rilascio. Dalla directory trunk/ digitiamo:

bzr tag 0.3

Dopo aver taggato una versione non c’è bisogno di fare il commit, che precede quindi il comando di tag.

Esportare il codice in un pacchetto o in una directory

Bazaar consente di esportare facilmente la directory di lavoro in un pacchetto compresso, senza esportare la directory nascosta. Entrare in trunk/ e digitare:

bzr export ../releases/version-0.3.tar.gz

La directory releases deve ovviamente essere già stata creata manualmente prima del comando.

Si può scegliere anche un altro formato di compressione: Bazaar lo ricoscerà automaticamente dall’estensione. I formati sono: .tar, .tar.bz2, .tar.gz, .zip (comprese le forme contratte). Se non mettiamo alcuna estensione, Bazaar esporterà il contenuto in una directory (nel caso di sopra in ../releases/version-0.3/).

Una GUI per Bazaar

Esiste anche una comodissima interfaccia grafica per Bazaar, Olive, che potete installare con apt. Ecco qualche screenshot:

I progetti su Olive e la barra degli strumenti.

I progetti su Olive e la barra degli strumenti.

La storia delle revisioni di un progetto, con i commit locali (in blu) poi riuniti e i tag.

La storia delle revisioni di un progetto, con i commit locali (in blu) poi riuniti e i tag.

I cambiamenti effettuati in una particolare revisione.

I cambiamenti effettuati in una particolare revisione.

Photo credits: Williamcho, Bugis Street is not quite the same as what it used to be…, CC by-nc, 2010.


  1. Ad esempio, avevo cancellato un bel numero di file e la loro directory da quella di lavoro. Al momento del commit Subversion mi dice che non potevo eseguire il commit perché questi file non c’erano (o erano obsoleti, onestamente non ricordo). Esisterà un comando per farglieli cancellare dal database pur non essendo presenti fisicamente, ma non ci sono riuscito (diciamo pure che non mi sono impegnato). Bazaar, invece, capisce che quei file sono già stati eliminati dall’utente e permette il commit, eliminandoli automaticamente. ↩︎