== Cloniamo == In vecchi sistemi di controllo di versione l'operazione standard per ottenere dei file era il checkout. Ottenete così un insieme di file corrispondenti a un particolare stato precedentemente salvato. In Git e altri sistemi distribuiti di controllo versione, l'operazione standard è il clonaggio. Per ottenere dei file si crea un 'clone' di tutto il deposito. In altre parole, diventate praticamente un http://it.wikipedia.org/wiki/Mirror_(informatica)[mirror] del server centrale. Tutto ciò che può fare il deposito centrale, potete farlo anche voi. === Sincronizzazione tra computers === Posso tollerare l'idea di creare degli archivi *tar* o di utilizzare *rsync* per backup di base. Ma a volte lavoro sul mio laptop, altre volte sul mio desktop, e può darsi che nel frattempo le due macchine non si siano parlate. Inizializzate un deposito Git e fate un *commit* dei vostri file su una macchina. Poi sull'altra eseguite: $ git clone altro.computer:/percorso/verso/il/file per creare una seconda copia dei file in un deposito Git. Da adesso in avanti, $ git commit -a $ git pull altro.computer:/percorso/verso/il/file HEAD trasferirà lo stato dei file sull'altro computer aggiornando quello su cui state lavorando. Se avete recentemente fatto delle modifiche conflittuali dello stesso file, Git ve lo segnalerà e dovrete ripetere nuovamente il commit, dopo che avrete risolto il conflitto. === Controllo classico di file sorgente === Inizializzate il deposito Git dei vostri file: $ git init $ git add . $ git commit -m "Commit iniziale" Sul server centrale inizializzate un 'deposito nudo' (*nudo* nella terminologia Git) in una cartella qualunque: $ mkdir proj.git $ cd proj.git $ git init --bare $ touch proj.git/git-daemon-export-ok Se necessario, lanciate il daemon: $ git daemon --detach # potrebbe già essere in esecuzione Per servizi di hosting Git, seguite le istruzioni per il setup del deposito Git che inizialmente sarà vuoto. Tipicamente bisognerà riempire un formulario in una pagina web. Trasferite il vostro progetto sul server centrale con: $ git push git://server.centrale/percorso/fino/a/proj.git HEAD Per ottenere i file sorgente, uno sviluppatore deve eseguire: $ git clone git://server.centrale/percorso/fino/a/proj.git Dopo aver fatto delle modifiche, lo sviluppatore le salva in locale: $ git commit -a Per aggiornare alla versione corrente: $ git pull Tutti i conflitti nel momento del merge devono essere risolti e validati: $ git commit -a Per inviare le modifiche locali al deposito centrale: $ git push Se il server principale ha nuove modifiche introdotte da altri sviluppatori, il push fallisce et lo sviluppatore deve aggiornarsi all'ultima versione, risolvere eventuali conflitti , e provare di nuovo. Perché i comandi pull e push precedenti funzionino bisogna avere accesso SSH. Comunque, chiunque può vedere il codice sorgente digitando: $ git clone git://server.centrale/percorso/fino/a/proj.git Il protocollo nativo git è come l'HTTP: non c'è nessuna autenticazione, così che tutti possono ottenere il progetto. Quindi, per default, push è proibito con protocollo git. === File sorgente segreti === Per un progetto chiuso, omettete il comando touch, e assicuratevi di mai creare un file chiamato `git-daemon-export-ok`. Il deposito in questo caso non potrà più essere ottenuto con il protocollo git; solo chi ha accesso SSH potrà vederlo. Se tutti i vostri deposito sono chiusi, lanciare il daemon git non è necessario perché la comunicazione avviene via SSH. === Depositi nudi === Un deposito nudo (*bare repository*) si chiama così perché non possiede una cartella di lavoro; contiene solo i file che sono solitamente nascosti nella sottocartella `.git`. In altre parole, mantiene unicamente la storia del progetto, e e non conserva nessuna versione. Un deposito nudo gioca un ruolo simile a quello di un server principale in un sistema di controllo di versione centralizzato: è dove è localizzato il vostro progetto. Altri sviluppatori clonano il nostro progetto da lì, e vi trasferiscono gli ultimi modifiche ufficiali. Tipicamente si trova su un server che non fa altro che distribuire dati. Lo sviluppo avviene nei cloni, così che il deposito principale non ha bisogno di una cartella di lavoro. Molti comandi git non funzionano per depositi nudi, a meno che la variabile globale `GIT_DIR` non viene definita con il percorso al deposito, o si utilizza l'opzione `--bare`. === Push vs pull === Perché abbiamo introdotto il comando `push`, invece di affidarci al più familiare comando `pull`? Prima di tutto il comando `pull` non funziona con depositi nudi: in questo caso bisogna invece usare `fetch`, un comando che discuteremo più tardi. Ma anche se avessimo un deposito normale sul server centrale, usare `pull` sarebbe sarebbe scomodo. Bisognerebbe per prima cosa connettersi al server e poi dare come argomento a `pull` l'indirizzo della macchina dalla quale vogliamo ottenere le modifiche. I firewalls potrebbero interferire nel processo, e cosa faremmo se non avessimo nemmeno accesso shell al server? In ogni caso, questo caso a parte, vi scoraggiamo l'uso di `push` per via della confusione che potrebbe generare quando la destinazione ha una cartella di lavoro. In conclusione, mentre state imparando ad usare Git, usate `push` solo se la destinazione è un deposito nudo; altrimenti usate `pull`. === Fare il forking di un progetto === Stufi del modo in cui un progetto è amministrato? Pensate che potreste fare un lavoro migliore? In questo caso, dal vostro server eseguite: $ git clone git://server.principale/percorso/verso/i/files Informate ora tutti del vostro fork del progetto sul vostro server. In seguito potete includere le modifiche provenenti dal progetto originale con: $ git pull === Il sistema definitivo di salvataggio === Volete degli archivi ridondanti e geograficamente distribuiti? Se il vostro progetto ha moti sviluppatori non c'è bisogno di fare niente! Ogni clone del vostro codice è effettivamente un backup. Non solo dello stato corrente, ma dell'intera storia del vostro progetto. Grazie al hashing crittografico, se qualcuno dovesse avere un clone corrotto, sarà individuato non appena si connetterà agli altri. Se il vostro progetto non è molto popolare, trovate il più alto numero possibile di server che possano ospitare dei cloni. Il vero paranoico dovrebbe anche sempre annotarsi l'ultimo codice SHA1 dell'HEAD di 20 bytes in un posto sicuro. Deve essere sicuro, non privato. Ad esempio, pubblicarlo in un giornale funzionerebbe bene, visto che sarebbe difficile realizzare un attacco modificando tutte le copie del giornale. === Multi-tasking alla velocità della luce === Immaginiamo di voler lavorare simultaneamente su diverse funzionalità. In questo caso fate un commit del progetto e eseguite: $ git clone . /una/nuova/cartella Grazie ai http://it.wikipedia.org/wiki/Collegamento_fisico[collegamenti fisici], i cloni locali richiedono meno tempo e spazio che i backup usuali. Potete ora lavorare simultaneamente su due funzionalità indipendentemente. Ad esempio, potete modificare un clone mentre l'altro sta compilando. Ad ogni modo, potete validare con 'commit' le vostre modifiche e importare con `pull` i cambiamenti dagli altri cloni: $ git pull /il/mio/altro/clone HEAD === Controllo di versione da battaglia === State lavorando ad un progetto che usa qualche altro sistema di controllo di versione, e vi manca disperatamente Git? In tal caso, inizializzate un deposito Git nella vostra cartella di lavoro: $ git init $ git add . $ git commit -m "Commit iniziale" poi clonatelo: $ git clone . /una/nuva/cartella Ora navigate alla nuova cartella e lavorate da qua, utilizzando Git come volete. Di tanto in tanto, quando volete sincronizzarvi con gli altri, recatevi nella cartella originale, sincronizzate utilizzando l'altro sistema di controllo di gestione, e poi digitate: $ git add . $ git commit -m "Sincronizzazione con gli altri" Andate quindi nella nuova cartella e lanciate: $ git commit -a -m "Descrizione delle mie modifiche" $ git pull La procedura per condividere le vostre modifiche con gli altri dipende d'altro canto dall'altro sistema di controllo di versione. La nuova cartella contiene i file con i vostri cambiamenti. Lanciate qualsiasi comando dell'altro sistema di controllo di gestione sia necessario per inviarli al deposito centrale. Subversion, che è forse il migliore sistema di gestione di versione centralizzato, è utilizzato da innumerevoli progetti. Il comando *git svn* automatizza la procedura precedente per i depositi Subversion, e può anche essere usato per esportare un progetto Git in un deposito Subversion. === Mercurial === Mercurial è un sistema di controllo di versione che può funzionare in tandem con Git in modo quasi trasparente. Con il plugin `hg-git` un utente di Mercurial può, senza svantaggi, inviare a (push) e ottenere (pull) da un deposito Git. Scaricate il plugin `hg-git` con Git: $ git clone git://github.com/schacon/hg-git.git o Mercurial: $ hg clone http://bitbucket.org/durin42/hg-git/ Sfortunatamente, non sembra ci sia un plugin analogo per Git. Per questa ragione, mi sembra preferibile utilizzare Git piuttosto che Mercurial per i depositi principali. Nel caso di un progetto Mercurial di solito un volontario mantiene in parallelo un deposito Git che accomoda utenti Git, mentre, grazie al plugin `hg-git`, un progetto Git accomoda automaticamente utenti Mercurial. Nonostante il plugin può convertire un deposito Mercurial in uno Git trasferendolo in un deposito vuoto, questo è più facile con lo script `hg-fast-export.sh`, ottenibile da: $ git clone git://repo.or.cz/fast-export.git Per fare una conversione, in una nuovo cartella eseguite: $ git init $ hg-fast-export.sh -r /depot/hg dopo aver aggiunto lo script al vostro `$PATH`. === Bazaar === Menzioniamo brevemente Bazaar perché è il sistema di controllo di versione distribuito gratuito più popolare dopo Git e Mercurial. Bazaar ha il vantaggio del senno di poi, visto che è relativamente giovane; i suoi disegnatori hanno potuto imparare dagli errori commessi nel passato e evitare gli scogli storici. Inoltre, i suoi sviluppatori sono attenti a questioni come la portabilità e l'interoperabilità con altri sistemi di controllo di versione. Un plugin chiamato `bzr-git` permette agli utilizzatori di Bazaar di lavorare con depositi Git in una certa misura. Il programma `tailor` converte depositi Bazaar in depositi Git, e può farlo in maniera incrementale, mentre `bzr-fast-export` è fatto per le conversioni uniche. === Perché utilizzo Git === Ho originariamente scelto Git perché avevo sentito che era in grado di gestire l'inimmaginabilmente ingestibile sorgente del kernel Linux. Non ho mai sentito la necessità di cambiare. Git mi ha servito un servizio impeccabile, e non sono mai stato colto alla sprovvista dai suoi limiti. Siccome utilizzo primariamente Linux, i problemi che appaiono sulle altre piattaforme non mi concernono. In più preferisco programmi in C e scripts in bash rispetto agli eseguibili tipo gli scripts Python: ci sono meno dipendenze, e sono dipendente all'alta velocità di esecuzione. Ho riflettuto a come migliorare Git, arrivando fino al punto di scrivere la mia propria versione, ma solo come un esercizio accademico. Anche se avessi completato il mio progetto, sarei rimasto a Git comunque, visto che i vantaggi sarebbero stati minimi per giustificare l'utilizzazione di un sistema solitario. Naturalmente, i vostri bisogni e richieste probabilmente differiscono dai miei, e quindi potreste trovarvi meglio con un altro sistema. Nonostante ciò, non potete sbagliarvi scegliendo Git.