Maurizio Monge's homepage - site dedicated to mathematics and computer science
Icon set:
   Gartoon Redux 1.8
 Best viewed with any browser
 Valid W3C HTML
Server Information:
  Apache/2.4.10 (Debian)
  Php: 5.6.40-0+deb8u12
User Agent:
  claudebot
Instructions to use Git (untranslated)
Cos'è Git/Cos'è un VCS?

Su questa pagina trovate un'introduzione basilare a Git. Presupporrò che siate capaci ad installare un programma, o che l'abbiate già installato (e comunque l'operazione non è più difficile di un "apt-get install git" o "yum install git"). Cercherò però di spiegarvi cosa sia un VCS, e di convincervi di quanto possa essere utile usare uno strumento che faciliti lo stoccaggio e la sincronizzazione (nonché di un monte di altre cose) quando si lavora a un progetto in Latex (come ad esempio una tesi, o un grosso articolo). Anche il sito che state visitando è stato sviluppato con l'aiuto di Git.

Un VCS (Version Control System) è un programma che permette di registrare le modifiche fatte a una collezione di file (di testo solitamente) e di condividerle con altri sviluppatori, solitamente usando come tramite un server (ovvero un computer appositamente configurato e accessibile a tutti gli sviluppatori). I VCS sono stati inizialmente creati per gestire i sorgenti di progetti software, e facilitare la coordinazione fra i programmatori. Git è un VCS innovativo sotto molti aspetti (ed è un cosiddetto VCS Distribuito), e mi sebbene esistano svariate alternative eccellenti (tipo Mercurial, Bazaar, etc), mi sento di dire che è notevolmente più semplice e conveniente rispetto al più tradizionale Subversion (per non parlare di CVS che è praticamente un rudere).

Introduzione

Vediamo subito un esempio di utilizzo. Supponiamo di avere dei file in Latex (o simili), in una directory di nome "Tesi": ~/Tesi $ ls
main.tex capitolo1.tex capitolo2.tex bibliografia.bib
Creiamo una repository locale e registriamo i file attualmente contenuti in essa: ~/Tesi $ git init (crea il database locale)
Initialized empty Git repository in /home/maurizio/Tesi/.git/

~/Tesi $ git add * (segna tutti i file come da aggiungere al prossimo salvataggio)
Initialized empty Git repository in /home/maurizio/Tesi/.git/

~/Tesi $ git commit (registra nel database l'aggiunta dei file)
Ho iniziato a scrivere la mia tesi! (e apre l'editor "Vim" per far scrivere il messagio)
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Committer: Io <maurizio@localhost>
#
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: bibliografia.bib
# new file: capitolo1.tex
# new file: capitolo2.tex
# new file: main.tex
#
(in Vim usate Ins per iniziare a scrivere, poi Esc e :wq per salvare e uscire)
Se durante l'operazione di scrittura preferite usare un editor diverso da Vim, basta che impostiate la variabile di ambiente GIT_EDITOR prima di lanciare Git, ad esempio potete aggiungere la seguente riga dentro ~/.bashrc e ~/.profile per far usare "nano" a Git come editor: export GIT_EDITOR="nano" Supponiamo che ora abbiate modificato main.tex, e aggiunto un file intro.tex. Potete salvare questa modifica con ~/Tesi $ git add intro.tex (segna intro.tex come da aggiungere al prossimo salvataggio)

~/Tesi $ git commit -a (salva nel database tutte le modifiche ai file registrati)
Aggiunto introduzione. (mettiamo un nuovo messaggio di modifica comprensibile)
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Committer: Io <maurizio@localhost>
#
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: intro.tex
# modified: main.tex
#
Notate l'opzione "-a" passata a "git commit", essa dice a git di cercare tutti i file registrati che sono stati modificati, e di salvare le modifiche. Se ad esempio invece avete modificato tanti file distinti e volete salvare le modifiche in passi separati (ad esempio perché non c'entrano nulla una con l'altra e volete scrivere messaggi di commit distinti), potete fare "git add file1.tex" e poi "git commit" (senza il "-a"), e poi magari "git add file2.tex file3.tex" e poi "git commit", etc.

Se volete cancellare un file, dovete cancellarlo anche dalla repository, e quindi dovete farlo usando il comando "git rm", mentre dovete usare "git mv" per spostare un file: ~/Tesi $ git rm capitolo2.tex (rimuove capitolo2.tex localmente e lo segna da rimuovere nel database)

~/Tesi $ git mv capitolo1.tex Chap1.tex (rinomina capitolo1.tex localmente e lo segna da rinominare nel database)

~/Tesi $ git commit (per salvare le modifiche, come al solito)
Di fatto questi comandi sono già sufficienti per mantenere una storia delle modifiche localmente, e per poter quindi tornare indietro, confrontare versioni differenti, etc. Inoltre se ad esempio avete cancellato o danneggiato i file, potete ripristinarli dall'ultima versione salvata nel database ~/Tesi $ rm *.tex (Ops!! ho cancellato la mia tesi per sbaglio...)

~/Tesi $ git reset --hard (fai sì che i file corrispondano precisamente al database)
Notate che Git (a differenza di altri VCS come Subversion) non richiede necessariamente un server per registrare le modifiche. E' ad esempio molto comodo lavorare offline salvando le modifiche fatte in locale, e poi eventualmente salvare su un server remoto tutte le nuove modifiche non appena una connessione internet non sia disponibile.

Sincronizzazione con un computer remoto

Ora Git non è così utile se utilizzato singolarmente e senza poter sincronizzarsi con un server remoto. Come dicevamo non necessario un server su cui sia installato uno speciale servizio relativo a Git, ma basta un computer su cui abbiate un account ssh, e su cui sia installato Git (soltanto il programma Git), e se non è installato potete eventualmente anche installare una copia locale sulla vostra home e configurare Git in modo da fare riferimento ad essa (anche se è piacevole evitare di dover fare questo).

Come prima cosa, colleghiamoci al server remoto e creiamo un database vuoto, ad esempio che ho l'account "monge" sul server "linuz.sns.it" ho fatto ~ $ ssh monge@linuz.sns.it
monge@linuz.sns.it's password:

linuz:~ $ mkdir Tesi_backup (creiamo una nuova directory)

linuz:~ $ cd Tesi_backup

linuz:~/Tesi_backup $ git init
Poi, in locale, dobbiamo aggiungere un "remote", ovvero le informazioni relative a una repository remota (che di fatto in realtà può anche essere in un percorso locale). Le assegnamo come nome "tesi_linuz": ~/Tesi $ git remote add tesi_linuz ssh://monge@linuz.sns.it/~/Tesi_backup (creiamo la remote)

~/Tesi $ git push tesi_linuz master (copiamo la branch "master" nella repository remota)
Counting objects: 6, done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 515 bytes, done.
Total 6 (delta 1), reused 0 (delta 0)
Unpacking 6 objects
refs/heads/master: 0000000000000000000000000000000000000000 -> 0bf40572edb2ca302278f38bf5fa5238854432ee
To ssh://monge@linuz.sns.it/~/Tesi_backup
* [new branch] master -> master
La branch "master" è il ramo dell'albero che abbiamo usato inconsciamente fino a questo momento, è possibile creare altri rami in cui salvare modifiche indipendenti (che possono poi essere integrate nel ramo principale, etc), rimandiamo a una guida più esaustiva per queste possibilità.

Dopo che la repository remota è stata creata, è stata aggiunta alla repostory locale, e la branch master è stata salvata in remoto, possiamo dopo ogni modifica locale (ogni "commit") possiamo risincronizzare la copia remota facendo semplicemente ~/Tesi $ git push tesi_linuz Se invece da un altro computer, o in un'altra directory del nostro computer, etc. vogliamo "prendere" la copia salvata in remoto, possiamo fare ~ $ git clone ssh://monge@linuz.sns.it/~/Tesi_backup che creerà una directory di nome Tesi_backup contenente una repository (sia database che i file) come sono stati salvati nella repository remota.

Impostazione di una chiave Ssh

Siccome le operazioni di push e pull venegono realizzate da git tramite alcune connessioni al server remoto tramite ssh, è utile impostare una chiave sul server remoto, per evitare di dover digitare tante volte la password. Per fare questo basta lanciare ~ $ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/maurizio/.ssh/id_rsa): (Invio)
Enter passphrase (empty for no passphrase): (Invio)
Enter same passphrase again: (Invio)
Your identification has been saved in /home/maurizio/.ssh/id_rsa.
Your public key has been saved in /home/maurizio/.ssh/id_rsa.pub.
The key fingerprint is:
48:f5:b8:e9:4a:b3:6e:b9:2d:ba:eb:68:a5:f1:9e:9c maurizio@aragorn
The key's randomart image is:
+--[ RSA 2048]----+
|        .        |
|       . o       |
|      . . .      |
|     . . o       |
|      . S        |
|  . .  .         |
|   =  o..        |
|  oo.++=         |
| ..oE*=o.        |
+-----------------+
Questo comando crea una chiave privata in ~/.ssh/id_rsa e una pubblica in ~/.ssh/id_rsa.pub, per inserire la chiave nella lista di quelle accettate dal server remoto basta ad esempio fare ssh monge@linuz.sns.it "mkdir -p ~/.ssh; cat >>~/.ssh/authorized_keys" < ~/.ssh/id_rsa.pub
monge@linuz.sns.it's password: (Tollerate che il server vi chieda la password un'ultima volta...)