Setup Menus in Admin Panel

School.Dataninja.it

Applicazioni web: tenere tutto sotto controllo (e collaborare) con Git

Sviluppare un'applicazione web è un processo relativamente complesso che prevede migliaia di modifiche a innumerevoli file, per cui è necessario usare gli strumenti giusti per gestire al meglio questa complessità.

Tutte le fasi di sviluppo di un’applicazione costituiscono una vera e propria storia, che inizia con una cartella vuota e (si spera!) finisce con un software funzionante e utile. Trattandosi sostanzialmente di scrivere un testo dentro a un file, ogni volta che aggiungiamo anche un solo carattere a un file del nostro progetto, lo modifichiamo interamente.

Mentre lavoriamo, il progetto attraversa una moltitudine di stati intermedi, uno per ogni tasto della tastiera che premiamo. Naturalmente la gran parte di questi stati sono temporanei e non ci interessa tenerne traccia, ma non è vero in assoluto. Per esempio può essere utile tenere traccia dello stato del progetto prima e dopo l’aggiunta di una funzionalità. Oppure mantenere uno stato che sappiamo stabile perché testato a dovere, mentre sperimentiamo l’aggiunta di nuovo codice non ancora provato.

Questi stati interessanti di un’applicazione si chiamano versioni. E quando diventano tante è utile e necessario un efficace strumento di controllo di versione. Ne esistono tanti, qui ti presento uno dei più diffusi al momento: Git.

La sua guida ufficiale (disponibile gratuitamente anche in formato ePub), tra l’altro, è un’eccellente manuale introduttivo al controllo di versione, per cui ti consiglio caldamente di leggere almeno i primi capitoli (ma tanto so che ti appassionerai e lo leggerai dall’inizio alla fine). In italiano è disponibile la traduzione quasi integrale della prima edizione del libro, perfetta per quel che serve per questo corso, mentre è ancora abbastanza indietro quella della seconda edizione.

Installare Git

Git è un programma multi-piattaforma, funziona quindi su qualsiasi sistema operativo. Di per sé è pensato per essere usato da linea di comando, ma esistono delle interfacce grafiche che aiutano a usarlo anche solo con un mouse, sia ufficiali che di terze parti.

Tutti i dettagli e i link utili per l’installazione sono presenti nella pagina dedicata della documentazione ufficiale, qui riporto per comodità i principali passaggi necessari per i sistemi operativi più diffusi.


La versione di Git per Windows è particolarmente ben fatta perché porta con sé anche una shell simil-Linux molto utile anche per scopi che non riguardano l’uso di Git stesso. Benché interagire con un computer mediante linea di comando (detta anche shell o prompt) possa apparire quasi esotico a chi è abituato al punta-e-clicca, la vera forza sta nel mettersi nelle condizioni di poter usare entrambi i mondi: finestre e pulsanti per la maggior parte dei compiti, shell quando serve.

Da questa pagina puoi scaricare l’installer di Git per Windows (un po’ tutte le versioni, da XP a 8.1): https://git-scm.com/download/win. Se vuoi approfondire il progetto puoi invece leggere la pagina ufficiale di MSysGit.

Si tratta di un’installazione standard, basta seguire tutti i passaggi. Al termine vedrai due nuovi programmi, probabilmente due nuove icone nello Start o sul Desktop: Git Bash e Git GUI. Aprendo il primo, vedrai apparire una finestra con sfondo scuro con due righe e un cursore lampeggiante:

Non si tratta di una vera e propria shell Bash di Linux, ma le assomiglia molto. I principali comandi sono riconosciuti e funzionano come ci si aspetta, c’è anche qualche utile programma aggiuntivo, come cURL. E naturalmente c’è git:

In grassetto il comando da scrivere (ed eseguire premendo Invio), il resto è la risposta del computer al comando.


Git è regolarmente pubblicato nei repository ufficiali, per cui è sufficiente cercarlo e installarlo mediante il proprio gestore di pacchetti. Se si è su Ubuntu o comunque su una distribuzione basata su Debian, da shell:

Se invece si è su Fedora, CentOS, RedHat o distribuzioni analoghe, da shell il comando fa uso di yum:

Tutto qua.


L’installazione di Git su Mac è analoga a quella per Windows. Devi scaricare ed eseguire l’installer che trovi a questo link: http://git-scm.com/download/mac. Una volta fatto avrai a disposizione il comando git all’interno del Terminale.


Prima configurazione di Git

Non è strettamente necessario configurare Git prima di usarlo, ma è buona prassi esplicitare alcune opzioni fin dall’inizio. In generale si può definire una configurazione a livello di progetto, di utente o di sistema. La priorità con cui vengono gestite eventuali configurazioni in conflitto ha lo stesso ordine: quelle di progetto hanno la priorità su quelle di utente che a loro volta vincono su quelle di sistema (e poi ci sono quelle di default).

Probabilmente ti trovi nella classica situazione in cui sei l’unica persona a usare la tua utenza sul tuo computer. La prima cosa da fare, quindi, è farti riconoscere, indicando nome ed e-mail.

Queste informazioni rimangono sul tuo computer, non vengono inviate a qualcuno! Ma sono necessarie per attribuirti l’autorialità delle varie azioni che compierai sui tuoi progetti: in caso di collaborazione con altri, per esempio, tutti potranno vedere chi ha fatto una modifica, perché Git la assocerà a nome ed email del suo autore, prendendo queste informazioni proprio dalla sua configurazione.

Un’altra opzione utile da indicare subito è il tuo editor preferito, che Git userà quando sarà necessario lasciare una descrizione o un commento alle tue modifiche. Ne esistono centinaia e moltissimi validi, la scelta dipende in parte dal sistema operativo in uso e dal tipo di programma che ti appresti a scrivere, ma moltissimo dal gusto personale. In generale a Git interessa solo il percorso completo dell’eseguibile ed eventuali opzioni accettate.

Ecco alcuni esempi / consigli (rispettivamente vim, notepad++, sublime text per Linux, Windows e MacOSX):

  • git config --global core.editor vim
  • git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
  • git config --global core.editor "subl -n -w"

Installare git-flow

Esistono numerose interfacce grafiche per Git, ma io sono della vecchia scuola e, se serve, ti consiglio di approfittarne per prendere confidenza con la linea di comando. I comandi di base sono pochi, molto semplici e facilmente memorizzabili e in più viene in aiuto uno strumento che semplifica alcuni processi e in generale l’applicazione di uno dei pattern più diffusi nell’uso di Git: git flow.


L’installazione di git-flow su Windows è semplice, ma richiede alcuni passaggi aggiuntivi del semplice scarica e installa. È tutto descritto passo passo dalla guida ufficiale. Prima di tutto abbiamo bisogno di tre file aggiuntivi che l’installazione di Git non ha: getopt.exe (un eseguibile), libintl3.dlllibiconv2.dll (due librerie).

  1. Scarica e copia il file getopt.exe nella cartella C:\Program Files\Git\bin (o dove hai installato Git sul tuo computer), lo trovi all’interno del file zip scaricabile da util-linux-ng for Windows (sezione Downloads / Binaries).
  2. Scarica e copia il file libintl3.dll nella stessa cartella C:\Program Files\Git\bin (o dove hai installato Git sul tuo computer), lo trovi all’interno del file zip scaricabile da LibIntl for Windows (sezione Downloads / Dependencies).
  3. Scarica e copia il file libiconv2.dll nella stessa cartella C:\Program Files\Git\bin (o dove hai installato Git sul tuo computer), lo trovi all’interno del file zip scaricabile da LibIconv for Windows (sezione Downloads / Dependencies, lo stesso file che hai scaricato perlibintl3.dll).
  4. Mediante la Git Shell posizionati in una cartella temporanea e clona il repository remoto di git-flow:  git clone --recursive git://github.com/nvie/gitflow.git .
  5. Mediante ora il prompt di comandi di Windows (non la Git Shell!) posizionati nella cartella appena creata gitflow/ e lancia l’installer:  contrib\msysgit-install.cmd , eventualmente garantendo l’accesso di amministratore.
  6. Di nuovo nella Git Shell, crea un link simbolico all’eseguibile git-flow in modo da poterlo usare per qualunque progetto:  ln -s /C/gitflow/git-flow git-flow .


Come sempre l’installazione di questo genere di software su Linux è incredibilmente semplice. Da un terminale è sufficiente un  sudo apt-get install git-flow  per sistemi Debian/Ubuntu o uno  yum install gitflow  per sistemi basati su RedHat.


Per utenti Apple la guida ufficiale riporta ben quattro metodi diversi, ma come sempre un package manager è lo strumento con la S maiuscola per questo genere di lavori. In altre parole, se non usi ancora Homebrew, forse è ora di installarlo.


Raccontare una storia per usare Git…

Una volta capito concettualmente (non uso questo termine a caso…), Git è uno strumento molto semplice da usare nonostante sia incredibilmente ricco e flessibile, ma bisogna prima arrivarci a capirlo concettualmente… 🙂 Ti consiglio di osservare bene questa immagine di Vincent Driessen che mostra visivamente la storia evolutiva di un progetto à la Git Flow, sarà il riferimento del racconto che leggerai tra poco.

gitflow_flow

 

Se la Storia non è in alcun modo un processo lineare, perché mai dovrebbe esserlo quella di un progetto software? In effetti le linee grigie orizzontali della figura indicano varie linee di sviluppo che il progetto si trova a percorrere in vari momenti della sua storia, linee che sono parallele e che in varie occasioni procedono in contemporanea. Queste linee si chiamano branch.

I pallini, invece, colorati in base alla branch in cui si trovano, sono stati dell’applicazione che abbiamo deciso di salvare, quegli stati interessanti che all’inizio di questa unità ho chiamato versioni. Nel gergo di Git si chiamano commit e sono generati da un atto volontario ed esplicito del programmatore, vale a dire il comando  git commit (vale lo stesso per le branch che, neanche a dirlo, si creano con il comando  git branch [nome branch]). Ricorda che Git non fa di testa sua, se aggiungi dei file e delle cartelle che Git non conosce, per far sì che siano inclusi nel prossimo commit, devi aggiungerli all’indice con il comando git add [file o cartelle] .

Le frecce sono invece i passaggi diretti tra un commit e l’altro che compongono le singole storie, che poi a loro volta concorrono a comporre la Storia completa. E allora provo a raccontartela, questa Storia, a partire dal primo pallino azzurro in alto a sinistra, quello segnato con la tag 0.1. Considera che sia l’inizio di tutto, la classica paginetta “Hello World!” che aspetta solo di essere riempita dal codice della tua nuova killer application. Per ora è tutto quello che potrà vedere il mondo al di fuori del tuo ufficio…

Il percorso prima di avere qualcosa di serio è infatti ancora lungo, ma Git sarà sempre al tuo fianco. Inizializza il repository nella cartella della tua applicazione con il comando git init , quindi prosegui lo sviluppo sulla branch denominata develop, adatta allo scopo. Commit gialli uno dietro l’altro man mano che aggiungi funzionalità (la struttura dello scheletro della pagina web, il menù di navigazione, il download dei dati da remoto, ecc.), finché non te ne viene in mente una nuova, tanto bella quanto oscura da implementare. Invece di pensare troppo se vale la pena provarci, apri una nuova branch (pallini lilla in basso) e cominci a sperimentare.

Ma ecco che arriva il capo che spariglia le carte: “lascia stare, devi svilupparmi quest’altra funzionalità, ha la priorità assoluta”. E ora che fai con i tuoi esperimenti? Finora il tuo lavoro è stato lineare (prova a seguire le frecce fin qui), ma adesso ti si chiede di tornare indietro! Nessun problema: salvi tutto in un commit, torni alla branch develop (tecnicamente effettui un checkout con il comando  git checkout [nome branch] ) e apri una nuova branch per accontentare il capo (gli altri pallini lilla in basso).

Cosa vuol dire tornare alla develop dopo che si è proseguito lungo una branch feature? Significa tornare esattamente all’ultimo commit (in ordine temporale) della branch develop, in questo caso a quello da cui eri partito per sviluppare la nuova funzionalità, ancora incompleta. Significa che tutti i file della tua cartella di lavoro sono tornati a quello stato, a quel momento della storia. Significa che non hai più tutte le modifiche fatte successivamente a quel momento, ma attenzione! Non hai perso nulla, Git sa perfettamente cosa hai fatto nella branch feature appena lasciata, semplicemente ora il tuo lavoro sperimentale è nascosto nel repository. Come eventualmente riaverlo indietro? Con un semplice checkout sulla branch feature, naturalmente, ma non è ancora il momento di farlo…

Stai combattendo con un errore di cui non trovi la causa, il capo ti sta con il fiato sul collo, ed ecco che ti chiamano al telefono facendoti notare che la pagina iniziale ha un refuso: hai scritto “Hello word!” dimenticando una “l”! Nessuna figuraccia è ammessa, ormai hai capito il meccanismo: nuovo checkout sulla branch master, nuova branch per gestire l’hotfix (pallino rosso, chiamiamola “hotfix-typo”), refuso risolto in un baleno. Ma ricorda che il mondo vede solo la master, quindi devi in qualche modo applicare l’hotfix alla master (e pure alla develop, altrimenti rischi di reintrodurlo nuovamente)… è quello che si chiama merge e si effettua con il comando git merge hotfix-typo  a partire dalla branch di destinazione (in questo caso la master e poi la develop). Ed è nel merge che emerge la natura un po’ magica di Git: di fronte allo stesso file che si trova in due stati diversi (quello con refuso della master e quello con la correzione nella branch hotfix), Git è in grado (quasi sempre) di comporre le differenze sfruttando varie strategie e ottenere un nuovo commit sulla branch di destinazione che incorpori correttamente tutte le modifiche fatte.

Tutto a posto, quindi. Torni al tuo lavoro sulla funzionalità prioritaria, tre commit e via. Ah, ma ti accorgi che il refuso su “Hello world!” è ancora lì! Ovvio, la correzione è avvenuta dopo che avevi staccato questa branch dalla develop, quindi non puoi vederla. Ma non ti preoccupi, hai una fede cieca in Git: merge sulla develop, che ora si trova sia la nuova funzionalità che la correzione del bug! Il capo è contento e vuole subito rilasciarla pubblicamente. Non ti fidi troppo, apri una branch release per prepararti al meglio ed evitare nuovi refusi. Ricontrolli tutto, effettui dei test, sistemi alcuni piccoli bug, aggiorni la documentazione, il numero di versione e via, merge sulla master.

Ora sì che puoi tornare alla tua funzionalità tanto bella quanto ostica. Non ha molto senso però tornare a lavorare su una versione così vecchia del codice, così sulla branch feature fai un merge della develop aggiornata e prosegui, fino all’implementazione completa. E via così, verso il successo.

Usare Git per raccontare una storia…

Ogni volta che effettui un commit o un merge (almeno quando si realizza con un nuovo commit sulla branch di destinazione), Git ti impone di lasciare un commento al commit. Dopo un po’ di lavoro, prova il comando  git log : sarà come rileggere a ritroso questa tua storia, raccontata da Git con dovizia di particolari, ma usando rigorosamente le tue parole… sono messaggi per il te del futuro, ma anche per i tuoi collaboratori o anche semplici curiosi che vorranno dare un’occhiata al tuo lavoro.

Il flusso di lavoro appena descritto, tra branch develop, master, feature, release e hotfix, è abbracciato appieno da Git Flow, un pacchetto di comandi semplici e comprensibili che automatizzano tutta una serie di processi ripetitivi. Eccone una panoramica.

  • git flow init : prepara il progetto per Git Flow, creando le branch master e develop, se non esistono già, e impostando una serie di prefissi per i nomi delle branch (consiglio di lasciare i valori di default tranne che per il prefisso delle tag di versione, che imposterei con una “v”).
  • git flow feature start [nome feature] : apre una nuova branch “feature/[nome feature]” dalla develop.
  • git flow feature finish [nome feature] : chiude la branch “feature/[nome feature]” con un merge sulla develop e la cancellazione della branch stessa (dopo un merge, non serve più, al massimo se ne apre un’altra).
  • git flow release start [numero di versione] : apre una nuova branch “release/[numero di versione]” dalla develop.
  • git flow release finish [numero di versione] : chiude la branch “release/[numero di versione]” con un merge sulla master e uno sulla develop (e la cancellazione della branch stessa), aggiunge una tag “v[numero di versione]” al nuovo commit sulla master
  • git flow hotfix start [numero di versione] : apre una nuova branch “hotfix/[numero di versione]” dalla master.
  • git flow hotfix finish [numero di versione] : chiude la branch “hotfix/[numero di versione]” con un merge sulla master e sulla develop (e la cancellazione della branch stessa), aggiunge una tag “v[numero di versione]” al nuovo commit sulla master.

Una sorta di dialogo continuo con il tuo Git. Anche perché non si tratta di servo obbediente e silenzioso, ma di un infaticabile chiacchierone: l’esecuzione di ogni comando, soprattutto di Git Flow, è accompagnata da un output molto ricco, con spiegazioni di ciò che è accaduto, di ciò che sarebbe meglio impostare, di ciò che manca e ciò che in realtà è superfluo. Soprattutto all’inizio è utilissimo leggerlo, per capire cosa fa e come ragiona… per capirlo meglio e a fondo, come merita un buon amico.

Aprirsi al mondo

Oltre a start e finish, Git Flow accetta anche l’azione publish per le branch feature, nel caso in cui il repository locale sia collegato a uno remoto e pubblicamente accessibile via Internet. Git infatti è uno strumento che facilita enormemente lo sviluppo collaborativo, o social coding, grazie alla sua implementazione dei concetti di branching e merging. Nella storia che ti ho raccontato hai letto di un solo protagonista (e di una spalla e di un antagonista, come tutte le storie che si rispettano), ma le stesse azioni potevano essere compiute da più persone contemporaneamente, il risultato sarebbe stato lo stesso. Ma come fare se lavorano in postazioni diverse (o anche luoghi del mondo diversi)?

Git permette un approccio decentralizzato grazie alla sua efficienza nel gestire anche progetti grandi e complessi: il repository locale originario contiene tutta la storia del progetto e può essere pubblicato interamente su un server pubblico da cui chiunque può clonarlo con il semplice comando  git clone [url] in un proprio repository locale. Si hanno così tanti repository inizialmente identici su tanti computer, ma le varie branch, che si chiamano sempre allo stesso modo, sono localmente autonome: da casa puoi fare quello che vuoi del tuo repository locale, incluso aprire e chiudere branch, effettuare commit, ecc. Anche senza essere connesso a Internet. Poi puoi però anche pubblicare i tuoi commit (comando git push ) e le ture branch, o scaricare i commit pubblicati da altri (comando  git pull ), sincronizzando il tuo repository con quello centrale (comando git fetch ). Di fatto si tratta di merge tra branch diverse che hanno sì lo stesso nome, ma si trovano in luoghi diversi (con pull effettui il merge della develop remota con quella omonima locale, con push aggiungi invece i tuoi nuovi commit sulla develop locale a quella omonima remota).

Quello che serve per abilitare tutto questo è naturalmente un server accessibile pubblicamente su Internet. O un servizio che ne offra le funzionalità, magari gratis (almeno per progetti open-source). Insomma, un hub per Git. Vale a dire Github. Devi solo aprire un account, creare un repository remoto (vuoto, se hai già il tuo progetto in locale) e aggiungere il suo url pubblico al tuo progetto con il comando  git remote add origin [url] . Poi è una questione di  git push e sei già on-line. Anzi, se stai sviluppando pagine web con risorse statiche (html, css, js, ecc.), prova ad aprire una branch con nome “gh-pages” e a pubblicarla, poi dai un’occhiata all’url http://[nome utente].github.io/[nome repository]/… 🙂

Letture: 661