20 aprile 2008

Git - il controllo versione che ti fa sentire stupido

Quanti lettori di questo blog conoscono Git ?

(Git cosa ?)

Ebbene, Git è un sistema di controllo versione distribuito scritto da Linus Torvalds che viene utilizzato, tra le altre cose, per gestire lo sviluppo del Kernel di Linux.

Il termine 'distribuito' lo identifica come un sistema di controllo versione che non si appoggia ad un server centralizzato, come SubVersion o CVS, ma in cui la 'storia' delle modifiche è memorizzata all'interno di ogni cartella di lavoro.

Se cercate Git su Wikipedia, troverete qualche spiegazione sull'origine del nome, che pare sia un termine britannico per indicare una persona stupida o sgradevole. In particolare (riporto testualmente): "a causa della difficoltà di utilizzo delle prime versioni, il programma è stato definito "il sistema di controllo versione progettato per farti sentire più stupido di quanto tu lo sia"."
Con queste premesse, come resistere alla tentazione di provarlo ?


Ok, scarichiamo una versione di Git. Nel caso specifico proviamo ad andare su msysgit, che offre un package piuttosto facile da installare su Windows. (scaricate git-XXX.exe da questo link).

A questo punto, per giocare un po' con questo strumento, create una normale cartella con un file di testo (MySource.txt) che simulerà il nostro codice sorgente.

Spostatevi sulla cartella del progetto, con il tasto destro sulla cartella selezionate 'Git BASH Here'. Si aprirà una finestra di Bash, una shell testuale che useremo per gestire Git.



Nel command prompt, digitate:

git init

A questo punto Git avrà creato il repository localmente alla cartella del progetto. In termini pratici ha aggiunto una cartella '.git' in radice che contiene tutte le informazioni utili a gestire il controllo sorgente.


Ricordatevi di mantenere questa cartella per non perdere informazioni !



Il lavoro non è finito: bisogna infatti aggiungere i files del progetto al controllo versione. Per farlo, digitate:

git add .

Questo è il sistema più semplice per aggiungere tutti i files della vostra cartella al controllo versione di Git, ma in realtà è possibile utilizzare filtri o aggiungere i files uno per uno.

A questo punto non avrete effettuato un commit dei vostri files, ma questi saranno memorizzati in una zona temporanea chiamata 'indice'. Tante chiamate a 'git add' continueranno ad aggiornare l'indice. Per memorizzare effettivamente la versione, digitate:

dig commit -m "il mio primo commit"

Questo comando registrerà le modifiche che avete 'fotografato' con la 'git add' in un'unica versione nel repository. Repository che, notate bene, è locale alla cartella del vostro progetto.

A questo punto proviamo a modificare uno dei files, e a salvare la modifica.

Digitate:

git add MySource.txt

Di nuovo non avete effettuato un commit, ma avete solo 'messo da parte' nell'indice la modifica al vostro file mySource.txt. Notate che i 'git add' sono cumulativi ma non hanno effetto sulla versione del repository fino ad un commit.

Se volete fare il punto e vedere cosa avete nell'index, potete digitare:

git status

Questo comando mostrerà la situazione delle vostre modifiche. A questo punto digitate di nuovo:

git commit -m "il mio secondo commit"

per memorizzare le modifiche.

Ora proviamo a vedere la storia del nostro repository digitando:

git log

.. apparirà una serie di informazioni relative alle modifiche apportate sui due commit. Una versione grafica si può ottenere digitando:

gitk

Ora, proviamo qualcosa di più cattivo.

Duplichiamo la cartella di lavoro in un'altra cartella che chiamiamo 'billproject', simulando il passaggio dei sorgenti ad un secondo programmatore. Questo secondo programmatore applicherà una modifica ad una riga. Nella stessa riga del nostro progetto iniziale, applichiamo un commento, o una modifica diversa.

Su entrambi i progetti, digitiamo 'git add .' per mettere nell'indice le modifiche apportate, e digitiamo 'git commit -m "commento"' per effettuare il commit.

A questo punto abbiamo due modifiche diverse apportate su due progetti distribuiti a due programmatori diversi. Ci siamo inoltre 'divertiti' a modificare la stessa riga di codice sorgente per vedere come se la cava il nostro amico git.

Simuliamo un merge: il programmatore principale vuole reinserire le modifiche di 'bill' nel proprio progetto. Lo farà digitando:

git pull --no-commit ../billproject/ master

Questa riga indica che intendiamo 'prendere' le modifiche del branch master della cartella '../billproject' ed inserirle nel branch locale della cartella locale. Indicando '--no-commit' richiediamo di non effettuare automaticamente il commit nella cartella locale.

Oops. Il risultato, evidenziato in rosso, è il seguente:


Nonostante i messaggi minacciosi, si tratta di un banale conflitto tra modifiche. Un 'git diff' evidenzierà che il problema sta proprio nella riga del codice che abbiamo modificato contemporaneamente nei due progetti.

Risolviamo il problema manualmente (per la cronaca, Git ha diversi algoritmi di merge automatico, quindi in una situazione reale li avremo provati prima di passare alla soluzione manuale), o con un editor di merge assistito, ed effettuiamo il commit nel nostro progetto.

Fatto !
Abbiamo simulato, in poche righe, quello che è il normale 'combattimento tra programmatori' in un progetto software.

Naturalmente non abbiamo visto tutte le funzionalità di git: i comandi sono molti e permettono anche operazioni interessanti che tuttavia vanno oltre i confini di un piccolo tutorial.


Quello che invece può essere interessante è considerare l'effettivo valore di questo strumento.

Con un atteggiamento decisamente polemico Linus Torvalds lo promuove come l'unico modo realistico di gestire il controllo sorgente, muovendo pesanti critiche sia al sistema CVS che a SVN.

Francamente, confrontare SVN con Git sembra confrontare un dolce alle pere con una grigliata di pesce.

Si tratta infatti di due modi completamente diversi di interpretare il controllo sorgente, ed ecco che diventa importare capire quale è la strategia che può essere utile nei nostri progetti:

- Con SVN (SubVersion) potete gestire in maniera centralizzata un repository seguito con organizzazione e metodo.
Avete il difetto di dover collegarvi ad un server (ma i repositories locali sono supportati tranquillamente) ma il vantaggio di avere una 'storia' delle modifiche centralizzata ed esterna alla cartella dei sorgenti.
Un difetto di SVN è che 'sparge' nella cartella di lavoro tanti piccoli files nascosti che sono un pò scomodi nel caso voleste rimuoverli per effettuare un backup.
SVN è il controllo sorgente perfetto per team di lavoro organizzati che lavorano all'interno di in una software house.

- Con Git avete il vantaggio di non dover nemmeno installare un server: può essere gestito completamente dal client perchè nella cartella di lavoro (il cosidetto tarball) è contenuto anche il repository con una storia delle modifiche, compresi i branch.
Avete il difetto di portarvi costantemente dietro questo repository che però è organizzato in una comoda cartella '.git' facile da rimuovere o filtrare.
Potete usare Git con successo se avete programmatori esperti che lavorano in locazioni diverse, senza un particolare scheduling e in maniera molto autonoma, e se le modifiche vengono spesso trasferite in modo eterogeneo. In poche parole se state gestendo un progetto di tipo Open Source.
In questo senso un difetto di Git è quello di perdere la 'storia' dei sorgenti: non c'è infatti una sola storia delle modifiche, ce ne sono tante quante sono le cartelle di lavoro e possono essere tutte diverse.


Insomma, a conti fatti i due strumenti sono entrambi potenti e affidabili.

L'importante è fare una scelta ponderata e consapevole in base ai pregi e ai difetti di ognuno. L'errore più grave sarebbe usare Git "solo perché lo usa Linus".

Forse la mancanza di una shell elegante e semplice come TortoiseSVN rende Git non inutilizzabile, ma sicuramente più scomodo per chi non è un vero e proprio smanettone. E al giorno d'oggi su un progetto software lavorano tanti tipi di professionisti: grafici, testers, analisti, ecc.

Ma, chissà, questa shell può sempre arrivare, no ?

Chi comincia a scriverla ?


[Aggiornamento dopo la stesura iniziale]

La shell è arrivata, e TortoiseGit non è niente male. Su Linux e Mac continuo a usare la command line, ma finalmente Git è utilizzabile anche su Windows ..

8 commenti:

  1. Avevo visto su Google Video un lungo discorsone di Torvalds su git (e contro cvs e svn), nel quale affermava che fare il merge di diversi branch in cvs e svn è una cosa che nessuno vorrebbe mai fare... mentre in git è tutto bello e colorato.

    Mi chiedevo in effetti perché, ma non ho mai avuto molta voglia di indagare su git - ho usato cvs un paio di volte nella mia vita, e giusto per giocherellare...

    Grazie dell'articolo :-)

    RispondiElimina
  2. Anch'io ho visto l'intervento di Torvalds. Notevole :)

    Ho l'impressione che abbia un pò forzato la mano, anche se ha avuto il merito di risvegliare la discussione su un argomento che era un pò .. assopito.

    RispondiElimina
  3. Aggiornamento (12/01/09) - E' ormai da un pò di tempo che lavoro con Git su più progetti. Ho fatto branches, merges, pull e rebase di tante modifiche fatte in posti diversi in contesti diversi.

    La mia impressione è che Git sia in grado di dare un bell'aiuto per certe operazioni.

    Ma non si tratta certo del 'tool definitivo' (fare un merge rimane noioso, pericoloso e lento anche in Git) oltre al fatto che l'interfaccia utente e il supporto a Windows lasciano ancora a desiderare.

    Si vedrà ..

    RispondiElimina
  4. Anonimo02:22

    Un difetto di SVN è che 'sparge' nella cartella di lavoro tanti piccoli files nascosti che sono un pò scomodi nel caso voleste rimuoverli per effettuare un backup.

    C'e' sempre la funzione export (seguita da pipe zip)... :-)

    RispondiElimina
  5. Sì, è un aspetto scomodo, anche se aggirabile.

    Git al contrario racchiude tutti i suoi files in una singola cartella '.git' posta immediatamente al di sotto della working folder. Torna molto utile sia per pulire una cartella che per lavorare con IDE, frameworks o ambienti di vario tipo, con i quali difficilmente Git fa 'a pugni'..

    RispondiElimina
  6. Anonimo01:18

    >In questo senso un difetto di Git è quello di perdere >la 'storia' dei sorgenti: non c'è infatti una sola
    >storia delle modifiche, ce ne sono tante quante sono
    >le cartelle di lavoro e possono essere tutte diverse.

    Come ho detto altrove, non è vero.
    Basta creare un repository centrale, un
    cosidetto "bare repository", senza file di lavoro, contenente solo la cartella .git e puoi usare git come svn (mantenendo tutti i vantaggi di git)

    Marco

    RispondiElimina
  7. Hai ragione, Marco. Un bare repository disponibile come repository pubblico permette ai vari sviluppatori di mantenere un unico 'filone ufficiale' ma di continuare a poter gestire vari repository locali con la massima flessibilità..

    RispondiElimina
  8. Anonimo11:08

    TortoiseSVN è una GUI non una shell.
    Forse intendevi una Windows Shell Extension. ;)

    RispondiElimina

Perchè non lasciare un commento intelligente ? Si accetta di tutto a parte lo spam e le volgarità ..