Se siete sviluppatori o designer, avrete probabilmente sentito parlare di Git e forse saprete che è diventato estremamente popolare, specialmente nella comunità open source. Sebbene sulle prime possa apparire criptico, questo sistema di version control potrebbe cambiare il modo in cui lavorate con il testo, sia che stiate scrivendo del codice sia un romanzo.
Questo articolo copre i motivi per cui il controllo di versione è importante, come installare il version control system Git e come iniziare il vostro primo repository. Una volta che avrete cominciato con Git, vorrete buttarci dentro tutto, dalle app fatte e finite alle bozze dei blog post dal momento che è così facile e versatile.
La progettazione di Git è stata ispirata da BitKeeper e da Monotone. Git era stato pensato inizialmente solamente come motore a basso livello che altri potevano usare per scrivere un front-end.
Tuttavia, il progetto Git è in seguito diventato un sistema completo di controllo versione, direttamente utilizzabile da riga di comando. Vari importanti progetti software adesso usano Git per il loro controllo versione, e principalmente il kernel Linux.
Il nome dato al progetto da Linus Torvalds è un termine gergale britannico per indicare una persona stupida o sgradevole. Linus lo spiegò così:
« Sono un egoista bastardo, e do a tutti i miei progetti un nome che mi riguardi. Prima Linux, adesso Git. »
Il wiki ufficiale di Git fornisce alcune spiegazioni alternative per il nome. Per esempio, 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 non sia".
Caratteristiche.
Il progetto di Git è la sintesi dell'esperienza di Torvalds nel mantenere un grande progetto di sviluppo distribuito, della sua intima conoscenza delle prestazioni del file system, e di un bisogno urgente di produrre un sistema soddisfacente in poco tempo. Queste influenze hanno condotto alle seguenti scelte implementative:
Forte supporto allo sviluppo non lineare. Git supporta diramazione e fusione (branching and merging) rapide e comode, e comprende strumenti specifici per visualizzare e navigare una cronologia di sviluppo non lineare. Un'assunzione centrale in Git è che una modifica verrà fusa più spesso di quanto sia scritta, dato che viene passata per le mani di vari revisori. Torvalds stesso fa la maggior parte delle fusioni e una piccola parte delle correzioni dirette al codice, perciò egli stesso ha dimostrato che questo aspetto funziona bene.
Sviluppo distribuito. Similmente a Darcs, BitKeeper, Mercurial, SVK, e Monotone, Git dà a ogni sviluppatore una copia locale dell'intera cronologia di sviluppo, e le modifiche vengono copiate da un tale repository a un altro. Queste modifiche vengono importate come diramazioni aggiuntive di sviluppo, e possono essere fuse allo stesso modo di una diramazione sviluppata localmente.
I repository possono essere pubblicati facilmente tramite HTTP, FTP, ssh, rsync, o uno speciale protocollo git. Git ha anche un'emulazione del server CVS, che consente di usare gli esistenti client CVS e plugin per IDE per accedere ai repositori Git.
Gestione efficiente di grandi progetti. Git è molto veloce e scalabile. È tipicamente un ordine di grandezza più veloce degli altri sistemi di controllo versione, e due ordini di grandezza più veloce per alcune operazioni.
Autenticazione crittografica della cronologia. La cronologia di Git viene memorizzata in modo tale che il nome di una revisione particolare (secondo la terminologia Git, una "commit") dipende dalla completa cronologia di sviluppo che conduce a tale commit. Una volta che è stata pubblicata, non è più possibile cambiare le vecchie versioni senza che ciò venga notato. (Anche Monotone ha questa proprietà.)
Progettazione del toolkit. Git è un insieme di programmi di base scritti in linguaggio C, e molti script di shell che forniscono comodi incapsulamenti. È facile concatenare i componenti per fare altre cose utili.
Strategie di fusione intercambiabili. Come parte della progettazione del suo toolkit, Git ha un modello ben definito di una fusione incompleta, e ha più algoritmi per tentare di completarla. Se tutti gli algoritmi falliscono, tale fallimento viene comunicato all'utente e viene sollecitata una fusione manuale. Pertanto è facile sperimentare con nuovi algoritmi di fusione.
La spazzatura si accumula fino a quando viene raccolta. Quando si abortisce un comando o si scartano delle modifiche si lasciano degli oggetti inutilizzabili nel database. Tipicamente, questi sono solo una piccola parte della cronologia continuamente crescente degli oggetti utili, ma il comando di recupero dello spazio, git-gc --prune, può richiedere parecchio tempo.
Una proprietà di Git che ha prodotto considerevoli controversie è il fatto che prende istantanee di interi alberi di directory di file invece che di singoli file. I primi sistemi di controllo versione del codice sorgente, SCCS and RCS, lavoravano su singoli file, e vantavano il risparmio di spazio ottenibile dalla codifica delta delle versioni simili. I successivi sistemi di controllo versione mantennero questo concetto di identità dei file al variare delle revisioni di un progetto.
Git rifiuta questo concetto e non registra esplicitamente le relazioni di revisione di file a nessun livello all'interno dell'albero del codice sorgente.
-->
Ciò comporta conseguenze rilevanti:
È effettivamente leggermente più costoso esaminare la cronologia di modifiche di un singolo file rispetto a quella dell'intero progetto. Per ottenere la cronologia delle modifiche che riguardano un dato file, Git deve ripercorrere la cronologia complessiva e poi determinare quali modifiche hanno riguardato quel file. Questo metodo di esaminare la cronologia, comunque, permette a Git di produrre con altrettanta efficienza una singola cronologia che mostra le modifiche a un arbitrario insieme di file. Per esempio, una sottodirectory dell'albero dei sorgenti più un file di intestazione (header) globale a loro associato.
I cambiamenti di nome di file e directory vengono gestiti in modo implicito invece che esplicito. Una grossa lamentela degli utenti di CVS è che usa il nome di un file per identificare la sua cronologia di revisioni, perciò non è possibile spostare un file o cambiargli nome senza interrompere la sua cronologia, così come cambiare nome alla cronologia rendendola inaccurata. La maggior parte dei sistemi di controllo versioni successivi a CVS risolvono questo problema dando a ogni file un nome interno univoco di lunga vita che sopravvive al cambiamento di nome.
Git non memorizza un identificatore di questo genere, e questo viene descritto come un vantaggio. I file di codice sorgente vengono talvolta spezzati o fusi oltre che semplicemente cambiati di nome, e memorizzare tali modifiche come un semplice cambiamento di nome congelerebbe per sempre nella cronologia una descrizione inaccurata di quello che è successo. Git affronta la questione rilevando i cambiamenti di nome mentre sfoglia la cronologia delle istantanee invece di memorizzarli quando si prende un'istantanea. (In breve, dato un file alla revisione N, un file con lo stesso nome alla revisione N-1 è il suo antenato di default.
Tuttavia, quando non ci sono file dal nome simile alla versione N-1, Git cerca un file che esisteva solamente alla versione N-1 e che abbia un contenuto molto simile a quello del nuovo file.) Questo richiede più lavoro di CPU ogni volta che si esamina la cronologia, e alcune opzioni per calibrare l'euristica.
Inoltre, la gente talvolta è turbata dal modello di immagazzinamento:
Impacchettamento esplicito periodico degli oggetti. Git immagazzina ogni nuovo oggetto in un file distinto.
Sebbene tale file sia in un formato compresso, può occupare parecchio spazio ed essere inefficiente. Questo problema è risolto dall'uso di "impacchettamenti" ("packs") che immagazzinano molti oggetti in un solo file (o in un flusso di dati via rete), che hanno essi stessi una compressione delta.
Gli impacchettamenti vengono compressi con l'euristica che i file con lo stesso nome sono probabilmente simili, funzionano correttamente anche se questo supposizione non è valida. Gli oggetti appena creati (cioè appena aggiunti alla cronologia) sono ancora immagazzinati singolarmente, e per mantenere l'efficienza si dovrebbe effettuare periodicamente un impacchettamento.
Git implementa varie strategie di fusione; in fase di fusione si può scegliere un comportamento diverso da quello di default:
risolvi (resolve): Questo è l'algoritmo tradizionale di fusione a 3 vie.
ricorsivo (recursive): Questo è l'algoritmo di default quando si estrae o si fonde un ramo, ed è una variante dell'algoritmo di fusione a 3 vie. "Quando ci sono più antenati comuni che possono esser usati per una fusione a 3 vie, crea un albero di fusione degli antenati comuni e lo utilizza come albero di riferimento per la fusione a 3 vie. Questo risulta produrre meno conflitti di fusione senza provocare mal-fusioni dalle prove effettuate su effettive fusioni di rilascio prese dalla cronologia di sviluppo del kernel Linux 2.6. Inoltre, questo può rivelare e gestire i cambiamenti di nome."
piovra (octopus): questo è l'algoritmo di default quando si fondono più di due teste.
Portabilità.
Git è pensato per funzionare in ambiente Linux, ma può essere portato su altri sistemi operativi Unix-like, tra cui BSD, Solaris e Darwin. Git è estremamente veloce su sistemi basati su POSIX come i suddetti.
Git può essere portato anche in ambiente Windows. Ci sono in effetti due possibilità per farlo: quella "ufficiale" richiede di installare e usare l'ambiente Cygwin (che è una emulazione POSIX); l'alternativa è un port nativo, cioè una modifica del codice sorgente per adattarlo a Windows. Git su Windows è sensibilmente più lento, a causa del massiccio uso da parte di Git di funzionalità POSIX del file system che devono essere emulate in ambiente Windows. Inoltre, molta gente trova che l'installazione di Cygwin sia troppo grande e invasiva per un tipico utente di Windows.
Esistono molti progetti open source che per ora hanno esplicitamente rinunciato a usare Git a causa della sua poca compatibilità con Windows, tra cui Mozilla e Ruby.
Un port nativo per Windows, con il nome di "WinGit" divenuto poi "Git on MSys", si avvicina al completamento utilizzando il compilatore MinGW, ma l'interfaccia-utente è ancora a riga di comando.
In alcuni casi (particolarmente per l'accesso remoto anonimo), si possono ammettere gli utenti Windows tramite il git-cvsserver (che emula un server CVS, consentendo l'uso di client CVS per Windows).
Altre alternative sono:
Un client GIT basato su EclipseIDE, che usa un'implementazione in puro Java delle funzioni interne di GIT
Un'estensione di Windows Explorer basata su libgit + cygwin.dll (è già iniziato un progetto per un software simile a TortoiseCVS)
Incapsulando in una libreria le operazioni di git a livello più basso in teoria consentirebbe la re-implementazione delle componenti di livello più basso per Windows senza dover riscrivere il resto.
Questi sforzi in generale dovrebbero aiutare a migliorare le prestazioni e la facilità di installazione su Windows; non è chiaro però se aiuteranno a risolvere la questione dei diversi modelli di autorizzazione.
Progetti che si basano su Git.
- git-gui è una GUI basata su Tk per le operazioni più comuni di Git. Questo progetto è incorporato in Git versione 1.5.0 e successive. (Si lancia con il comando "git gui").
- Cogito (homepage) - Petr Baudiš ha mantenuto un insieme di script chiamato Cogito (precedentemente git-pasky), che formano un sistema di controllo versione che usa Git come backend. Lo sviluppo di Cogito è stato interrotto nell'aprile 2007 quando la sua funzionalità è stata ritenuta ridondante con gli strumenti di frontend di Git, comunemente chiamati "porcellana" ("porcelain").
- StGIT (homepage) - Stacked GIT è un'applicazione Python che fornisce funzionalità simili a Quilt (homepage) (cioè aggiungere/togliere patch a/da uno stack) appoggiandosi a Git, per gestire le patch fino a quando vengo fuse.
- pg (Patchy GIT) è un'interfaccia a Git costituita da script di shell per aiutare l'utente a gestire un insieme di patch ai file. pg è in un certo senso simile a Quilt o a StGIT, ma ha un insieme di caratteristiche leggermente diverso. pg non viene più mantenuto dal 29 aprile, 2007
- DarcsGit è un'estensione di Darcs che gli consente di interagire con i repositori Git.
- bzr-git è un plugin per Bazaar per leggere gli alberi di Git. Sebbene sia ancora in fase alpha, fornisce abbastanza supporto per la visualizazione bzrk.
Ci sono molti modi per ottenere ed installare Git: il più rapido è quello di scaricarlo e compilarlo dal sorgente. Ecco una buona guida passo a passo su come installarlo su Mac OS X. In alternativa, gli utenti Mac possono anche scaricare l'installer grafico di Git ed utilizzarlo per installare Git come ogni altro programma Mac. Su Ubuntu Linux, eseguite
apt-get install git-core
; gli utenti Windows dovrebbero guardare msysgit.Il libro gratuito Pro Git ha anche una sezione ben fatta sull'installazione di Git su diverse piattaforme.
Creare un repository
Ora che Git è installato, inizieremo con un repository (o repo, per abbreviare). Per prima cosa, assicuriamoci di averlo installato correttamente:
prompt> git --version
git version 1.7.2.2
Funziona! (Se avete avuto un messaggio diverso, provate a re-installarlo). Ora siamo pronti per creare il nostro primo repo. Per prima cosa, creiamo una nuova cartella in un qualunque punto di Finder e poi andiamo su quella cartella dal terminale:
prompt> cd /Users/alshaw/testrepo
Per far sì che questa cartella diventi un repo di Git, digitate (Le linee che proseguono sulla riga successiva sono indicate da » —Ed.):
prompt> git init
Initialized empty Git repository in /Users/alshaw/»
testrepo/.git/
prompt> git status
# On branch master
#
# Initial commit
#
Dietro le quinte, questo crea una directory nascosta .git all'interno della cartella che terrà traccia dei cambiamenti che farete. Solo per essere sicuri, la testiamo:
prompt> ls -a
. .. .git
Git non toccherà mai i vostri files o farà mai nulla al di fuori della directory .git, a meno che voi non gli diciate di fare diversamente. Se un giorno doveste decidere che quella cartella non dovrà più essere un Git repo, basterà che cancelliate la cartella .git:
prompt> rm -rf .git
Un breve test per controllare di aver veramente tolto Git da “testrepo”:
prompt> git status
fatal: Not a git repository (or any of the parent »
directories): .git
Un altro modo per cominciare a lavorare con un repository consiste nel fare
git-clone
di un repository esistente. Supponiamo di voler scrivere una nuova app per il web e di voler usare il nuovo eccellente HTML5 Boilerplate di Paul Irish come punto di partenza. Dal momento che Paul ha il suo codice sorgente in un repository Git su GitHub, possiamo andare a prenderlo e cominciare a modificarlo senza lasciare la riga di comando:
prompt> git clone git://github.com/paulirish/»
html5-boilerplate.git
Cloning into html5-boilerplate...
remote: Counting objects: 932, done.
remote: Compressing objects: 100% (820/820), done.
remote: Total 932 (delta 477), reused 196 »
(delta 88)
Receiving objects: 100% (932/932), 1.54 MiB | 349 »
KiB/s, done.
Resolving deltas: 100% (477/477), done.
prompt> cd html5-boilerplate
git-log
:
prompt> git log
commit 75b34e5962b155238bcb711e87b34a6409787e78
Author: paulirish <paul.irish@gmail.com>
Date: Tue Aug 24 22:12:59 2010 -0700
minified dd_belated png... you probably dont »
need the full one.
[snip]
Con git-log
si può avere una lista di tutti i commit, dello hash SHA1 del commit (una stringa univoca assegnata ad ogni commit), l'autore ed un messaggio che è stato scritto dall'autore per descrivere la modifica.Se vogliamo esaminare nel dettaglio quello che è cambiato in questa versione, possiamo usare
git-diff
per confrontarla con le modifiche precedenti. Osserviamo la differenza tra la versione attuale ed un commit precedente. Per fare ciò, useremo git-diff
con l'hash id del commit precedente come argomento:
prompt> git diff b59c1cc00e1f6a25a12a224080a70287fa33e4da
[snip]
diff --git a/.htaccess b/.htaccess
index 9879e5e..5451611 100644
--- a/.htaccess
+++ b/.htaccess
@@ -68,7 +68,7 @@ AddType text/x-component htc
# Disabled by default.
# <FilesMatch "\.combined\.(js|css)$">
-# Options +IncludesNOEXEC
+# Options +Includes
# SetOutputFilter INCLUDES
# </FilesMatch>
[snip]
+
) e ne ha cancellata un'altra (marcata con -
).
Nessun commento:
Posta un commento
Non inserire link cliccabili altrimenti il commento verrà eliminato. Metti la spunta a Inviami notifiche per essere avvertito via email di nuovi commenti.