• controllo-di-versione

    Il controllo di versione con Git

    Una panoramica sui concetti di base del controllo di versione.

    I concetti di base del controllo di versione

    Il controllo di versione (Version Control o Versioning) è un processo che ti consente di tenere traccia nel tempo di tutte le modifiche effettuate ad un insieme di file. In un VCS, o Version Control System (sistema per il controllo di versione), viene registrata la modifica, chi e quando ha effettuato la modifica, il motivo per cui un file è stato modificato, ed è possibile recuperare una qualsiasi versione precedente in qualsiasi momento, o recuperare file che sono stati erroneamente cancellati o  perduti.

    vcs-versioni

    L’utilizzo degli strumenti di controllo di versione come Subversion, Perforce, TFS, Git e Mercurial ti possono aiutare ad essere più organizzato, a salvaguardare il tuo codice sorgente e persino a dormire meglio.

    I sistemi di controllo di versione sono importanti almeno per quattro motivi:

    • conferiscono tranquillità: ogni volta che aggiorni dei file e li memorizzi nel sistema di controllo di versione, i file vengono conservati in modo permanente;
    • gestione della cronologia: oltre al backup dei file, vengono memorizzate le modifiche che hai fatto rispetto alla versione precedente, eventuali commenti sulla modifica, la data e l’autore della modifica; tra 3 mesi o tra due anni puoi facilmente vedere cosa hai modificato e puoi ricostruirne anche il perché.
    • possibilità di tornare indietro senza problemi: puoi facilmente tornare a una versione precedente (in alcuni sistemi di controllo di versione, lo si può fare file per file, in altri sull’intero albero delle directory);
    • la possibilità di sperimentare senza paura: puoi creare una sandbox (un ambiente di test, magari slegato dal flusso principale) in cui puoi provare nuove funzionalità o apportare modifiche strutturali senza preoccuparti di interferire con che già è in produzione e funziona.

    Il controllo di versione è ancora più importante quando si lavora in un team, perché è semplice gestire i seguenti aspetti:

    • sincronizzazione: quando si salvano le modifiche al codice sorgente in un VCS, ciascun membro del team può facilmente aggiornare la propria copia del codice sorgente con le modifiche apportate dagli altri;
    • responsabilità: un VCS registra le informazioni sull’utente che apporta delle modifiche, che diventa fondamentale quando si lavora in team (in ogni momento si può verificare chi ha modificato un file e perché);
    • gestione dei conflitti: quando un membro del team apporta modifiche non automaticamente compatibili con le tue, il VCS ti avvisa e ti aiuta a risolvere i problemi che nascono dall’attività concorrente di più membri sugli stessi file con strumenti che mettono a confronto le versioni. Senza questi strumenti, puoi facilmente sovrascrivere le modifiche degli altri membri del team.

    Con un VCS, tutto questo avviene in modo praticamente automatico. Il carico di lavoro aggiuntivo consiste nella stesura di commenti ogni volta che si deposita il codice modificato.

     

    Comprensione della terminologia del controllo di versione

    Prima di vedere da vicino come funziona un VCS, ci sono sei concetti-chiave da comprendere:

    1. Repository: Un sistema per il controllo di versione è un’applicazione che gestisce la creazione di un repository, cioè del posto in cui sono archiviati file e cronologia. In alcuni sistemi, si tratta di un vero e proprio database, mentre in altri si crea una serie di piccoli file con le modifiche che vengono identificati e gestiti dal software.
    2. Working set: I file e le cartelle possono essere organizzati in progetti all’interno del repository in un modo simile a come gestisci i file mantenendoli in cartelle sull’hard disk. Dal punto di vista del VCS, i file sul tuo hard disk sono il working set.
    3. Add: Durante il proprio lavoro, un programmatore modifica i file nel working set, poi aggiorna il repository in modo che rifletta quegli aggiornamenti. Il processo di aggiornamento del repository si chiama add quando si aggiungono nuovi file.
    4. Check-in (commit): Il processo di aggiornamento del repository si chiama check-in quando si modificano file esistenti oppure quando si esegue il commit.
    5. Check-out (update): Il processo di aggiornamento del proprio working set con una versione (l’ultima aggiornata, oppure una specifica) dei dati sul repository si chiama check-out.
    6. Tag (label): è possibile contrassegnare lo stato di un intero albero di un progetto o di un intero repository con un identificatore chiamato tag (o label, a seconda del fornitore del VCS), utilizzato di solito in occasione del rilascio di una versione, oppure della consegna al cliente.

     

    Git in azione

    Prima di vedere come utilizzare nella pratica un repository Git, proviamo a rappresentare graficamente cosa faremo.

    repository-git-attività

    In figura la freccia rivolta verso destra rappresenta il repository in cui sono conservati i file, che contiene le diverse versioni dei file nel tempo.

    • Alle 9:00, viene creato un repository, a cui è possibile aggiungere file da versionare. Il comando utilizzato è init.
    • Alle 10:15 viene creato il file myprog.c e si aggiunge solo la funzione Main(). Quindi viene aggiunto al repository con con il comando add e poi viene eseguito un check-in (con relativo commento).
    • Alle 16:56 viene modificato il file myprog.c, aggiungendo la funzione Func1(). Il salvataggio su disco del file modificato rende il working diverso da quello che è stato memorizzato nel repository. Viene quindi fatto un nuovo check-in. Il repository ha due versioni del tuo file e due messaggi di commit.
    • Alle 17:40 viene aggiunta la funzione Func2() e viene fatto un altro check-in.

    Vediamo tutti questi passaggi in pratica. Apri un terminale e crea una cartella che conterrà il repository (al percorso/repo/demo):

    Entra dentro la directory appena creata:

    Una volta all’interno di questa directory, digita il comando git init per creare un repository vuoto.

    Viene mostrato il messaggio seguente: Initialized empty Git repository in /repo/demo/.git/

    Git memorizza i dati relativi ai file e alle directory e tutta la loro cronologia in una directory nascosta chiamata .git.

    Per verificare lo stato del repository, digita il comando seguente:

    Viene mostrato il seguente output:

    Il fatto che venga mostrato il messaggio “nothing to commit” significa che il working set è nello stesso stato del repository.

    A questo punto puoi creare il file myprog.c (ad esempio con vi), aggiungere la funzione Main() {} e salvare il file. Il working set adesso è diverso dallo stato del repository (c’è un file che prima non c’era) e con il comando (git status) per verificare lo stato del repository, ti viene mostrata la presenza di un nuovo file:

    Ogni volta che aggiungi nuovi file, devi dire a Git di versionare quei file. Il comando utilizzato per dire a Git che ci sono nuovi file è add. Puoi specificare il nome del singolo file oppure dire a Git di aggiungere tutti i file (utilizzando l’asterisco).

    Se esegui nuovamente il comando per vedere lo stato di Git (git status), vedrai il seguente output:

    Per rendere permanenti le modifiche sul repository, devi eseguire un commit del file.

    L’opzione -a dice a Git di memorizzare automaticamente nel repository i file modificati e/o cancellati in un unico passaggio (senza quindi dover lanciare il comando git add). L’opzione -m consente di specificare il messaggio da usare come commento al commit. Nell’esempio, il commento è “Add myprog.c” e deve essere breve, ma significativo per far capire che tipo di modifica è stata apportata al file.

    Questo è l’output del comando:

    Se Git non è stato configurato con le informazioni di esegue il commit, verrà invece mostrato un messaggio del genere:

    Ogni sistema di controllo di versione deve sapere chi sei, per poter attribuirti tutte le modifiche apportate ai file. Per configurare il nome e l’email digita i seguenti comandi:

    Le informazioni sull’utente vengono memorizzate sul file ~/.gitconfig e saranno le seguenti:

    Se dopo il commit lanci il comando per visualizzare lo stato del repository, vedi che non c’è niente da committare.

    A questo punto, possiamo chiedere a Git di darci la cronologia completa con il comando seguente:

    Che produce il seguente output:

    Puoi vedere le informazioni sull’autore (nome e indirizzo email), sulla data e l’ora del commit, che commento c’è sul file e la differenza con la precedente versione. In questo caso, non c’era nessuna versione precedente (si tratta di un nuovo file). La parte aggiunta viene colorata in verde.

    A questo punto modifica il file, aggiungendo la funzione Func1() {} e salvando le modifiche. L’esecuzione del comando git status evidenzia il fatto che il file è stato modificato e non ancora committato.

    Lancia il comando di commit e aggiungi il commento.

    Lancia di nuovo il comando per mostrare la cronologia (git log -p). L’output è il seguente:

    Quando l’elenco delle modifiche è più lungo di una pagina, l’ouput viene automaticamente paginato (ed occorre premere la barra spaziatrice per andare avanti) e devi digitare la lettera q per tornare al prompt dei comandi.

    Infine modifica myprog.c ancora una volta, aggiungi Func2(), salva il file e committa.

    Questa volta non ho usato l’opzione -a (che dice di committare tutti i file modificati), ma ho indicato il file da committare.

    Lancia di nuovo il comando per mostrare la cronologia, ma questa volta senza l’opzione -p (che mostra un output più dettagliato) per vedere informazioni sulle modifiche.

    L’output è il seguente:

    Per vedere ogni revisione ciascuna su una riga, utilizza  l’opzione –oneline:

    E questo l’output:

    Puoi vedere in ordine cronologico (dal più recente in alto al meno recente in basso) i tre commit con i rispettivi commenti. Il numero che vedi sulla sinistra (mostrato in giallo nel terminale) è l’identificatore del check-in.

    Per mostrare le differenze tra la prima revisione (f5892a7) e l’ultima (55ccf16) lancia il seguente comando:

    L’output è il seguente:

     

    Il ciclo di vita dello stato dei file

    Ciascun file del working set può essere in uno dei due stati seguenti: tracked (tracciato, o versionato) o untracked (non tracciato). I file tracked sono già presenti nell’ultimo snapshot; possono quindi a loro volta essere unmodified (non modificati), modified (modificati), o staged.

    git-ciclo-vita-stato-file

    I file untracked sono tutti gli altri file nel working set che non sono presenti nell’ultimo snapshot o nell’area di stage. Quando crei per la prima volta un repository, non ci sono file tracciati e file non modificati. Appena crei dei file (o dopo quando li editi e salvi le modifiche), Git li vede come modificati, perché sono cambiati rispetto all’ultima commit. Metti nell’area di stage i file modificati (fai commit, cioè check-in) e Git li rivedrà con non modificati.

     

    Giulio Cantali – IT Consultant

    Creatore di Database Master, il primo percorso per diventare esperti di database

Lascia un commento

Se vuoi condividere la tua opinione, lascia un commento

Puoi usare questi tag e attributi: HTML:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">