Added it/secrets.txt
authorMattia Rigotti <matrig@hotmail.com>
Sat, 6 Jul 2013 23:41:29 +0000 (6 19:41 -0400)
committerMattia Rigotti <matrig@hotmail.com>
Sat, 6 Jul 2013 23:41:29 +0000 (6 19:41 -0400)
it/secrets.txt [new file with mode: 0644]

diff --git a/it/secrets.txt b/it/secrets.txt
new file mode 100644 (file)
index 0000000..fc49718
--- /dev/null
@@ -0,0 +1,297 @@
+== Segreti rivelati ==
+
+Diamo ora un'occhiata sotto il cofano e cerchiamo di capire come Git
+realizza i suoi miracoli. Per una descrizione approfondita fate
+riferimento al
+http://www.kernel.org/pub/software/scm/git/docs/user-manual.html[manuale
+utente].
+
+=== Invisibilità ===
+
+Come fa Git ad essere così discreto? A parte qualche commit o merge
+occasionale, potreste lavorare come se il controllo di versione non
+esistesse. Vale a dire fino a che non è necessario, nel qual caso sarete
+felici che Git stava tenendo tutto sotto controllo per tutto il tempo.
+
+Altri sistemi di controllo di versione vi forzano costantemente a
+confrontarvi con scartoffie e burocrazia. File possono essere solo
+acceduti in lettura, a meno che non dite esplicitamente al server
+centrale quali file intendete modificare. I comandi di base soffrono
+progressivamente di problemi di performance all'aumentare del numero
+utenti. Il lavoro si arresta quando la rete o il server centrale hanno
+problemi.
+
+In contrasto, Git conserva tutta la storia del vostro progetto nella
+sottocartella `.git` della vostra cartella di lavoro. Questa è la vostra
+copia personale della storia e potete quindi rimanere offline fino a che
+non volete comunicare con altri. Avete controllo totale sul fato dei
+vostri file perché Git può ricrearli ad ogni momento a partire da uno
+stato salvato in `.git`.
+
+=== Integrità  ===
+
+La maggior parte della gente associa la crittografia con la
+conservazione di informazioni segrete ma un altro dei suoi importanti
+scopi è di conservare l'integrità di queste informazioni. Un uso
+appropriato di funzioni hash crittografiche può prevenire la corruzione
+accidentale e dolosa di dati.
+
+Un codice hash SHA1 può essere visto come un codice unico di
+identificazione di 160 bit per ogni stringa di byte concepibile.
+
+Visto che un codice SHA1 è lui stesso una stringa di byte, possiamo
+calcolare un codice hash di stringe di byte che contengono altri codici
+hash. Questa semplice osservazione è sorprendentemente utile: cercate ad
+esempio 'hash chains'. Più tardi vedremo come Git usa questa tecnica per
+garantire efficientemente l'integrità di dati.
+
+Brevemente, Git conserva i vostri dati nella sottocartella
+`.git/objects`, ma invece di normali nomi di file vi troverete solo dei
+codici. Utilizzando questi codici come nomi dei file, e grazie a qualche
+trucco basato sull'uso di 'lockfile' e 'timestamping', Git trasforma un
+semplice sistema di file in un database efficiente e robusto.
+
+=== Intelligenza ===
+
+Come fa Git a sapere che avete rinominato un file anche se non
+gliel'avete mai detto esplicitamente? È vero, magari avete usato *git
+mv*, ma questo è esattamente la stessa cosa che usare *git rm* seguito
+da *git add*.
+
+Git possiede dei metodi euristici stanare cambiamenti di nomi e copie
+tra versioni successive. Infatti, può addirittura identificare lo
+spostamento di parti di codice da un file ad un altro! Pur non potendo
+coprire tutti i casi, questo funziona molto bene e sta sempre
+costantemente migliorando. Se non dovesse funzionare per voi, provate
+le opzioni che attivano metodi di rilevamento di copie più impegnative,
+e considerate l'eventualità di fare un aggiornamento
+
+=== Indicizzazione  ===
+
+Per ogni file in gestione, Git memorizza delle informazioni, come la sua
+taglia su disco, e le date di creazione e ultima modifica, un file detto
+'indice'. Per determinare su un file è stato cambiato, Git paragona il
+suo stato corrente con quello che è memorizzato nell'indice. Se le due
+fonti di informazione corrispondono Git non ha bisogno di rileggere il
+file.
+
+Visto che l'accesso all'indice è considerabilmente più che leggere file,
+se modificate solo qualche file, Git può aggiornare il suo stato quasi
+immediatamente. 
+
+Prima abbiamo detto che l'indice si trova nell'area di staging. Com'è
+possibile che un semplice file contenente dati su altri file si trova
+nell'area di staging? Perché il comando 'add' aggiunge file nel database
+di Git e aggiorna queste informazioni, mentre il comando 'commit' senza
+opzioni crea un commit basato unicamente sull'indice e i file già
+inclusi nel database.
+
+=== Le origini di Git ===
+
+Questo http://lkml.org/lkml/2005/4/6/121[messaggio della mailing list
+del kernel di Linux] descrive la catena di eventi che hanno portato alla
+creazione di Git. L'intera discussione è un affascinante sito
+archeologico per gli storici di Git.
+
+=== Il database di oggetti ===
+
+Ognuna delle versioni dei vostri dati è conservata nel cosiddetto
+'database di oggetti' che si trova nella sottocartella `.git/objects`;
+il resto del contenuto di `.git/` rappresenta meno dati: l'indice, il
+nome delle branch, le tags, le opzioni di configurazione, i logs, la
+posizione attuale del commit HEAD, e così via. Il database di oggetti è
+semplice ma elegante, e è la fonte della potenza di Git.
+
+Ogni file in `.git/objects` è un 'oggetto'. Ci sono tre tipi di oggetti
+che ci riguardano: oggetti 'blob', oggetti 'albero' (o `tree`) e gli
+oggetti 'commit'.
+
+=== Oggetti 'blob' ===
+
+Prima di tutto un po' di magia. Scegliete un nome di file qualsiasi. In
+una cartella vuota eseguite:
+
+ $ echo sweet > VOSTRO_FILE
+ $ git init
+ $ git add .
+ $ find .git/objects -type f
+
+Vedrete +.git/objects/aa/823728ea7d592acc69b36875a482cdf3fd5c8d+.
+
+Come posso saperlo senza sapere il nome del file? Perché il codice hash
+SHA1 di:
+
+ "blob" SP "6" NUL "sweet" LF
+
+è aa823728ea7d592acc69b36875a482cdf3fd5c8d, dove SP è uno spazio, NUL è
+un carattere di zero byte e LF un passaggio a nuova linea. Potete
+verificare tutto ciò digitando:
+
+  $ printf "blob 6\000sweet\n" | sha1sum
+
+Git utilizza un sistema di classificazione per contenuti: i file non
+sono archiviati secondo il loro nome, ma secondo il codice hash del loro
+contenuto, in un file che chiamiamo un oggetto 'blob'. Possiamo vedere
+il codice hash come identificativo unico del contenuto del file. Quindi,
+in un certo senso, ci stiamo riferendo ai file rispetto al loro
+contenuto. L'iniziale `blob 6` è semplicemente un'intestazione che
+indica il tipo di oggetto e la sua lunghezza in bytes; serve a
+semplificare la gestione interna.
+
+Ecco come ho potuto predire il contenuto di .git. Il nome del file non
+conta: solo il suo contenuto è usato per costruire l'oggetto blob.
+
+Magari vi state chiedendo che cosa succede nel caso di file identici.
+Provate ad aggiungere copie del vostro file, con qualsiasi nome. Il
+contenuto di +.git/objects+ rimane lo stesso a prescindere del numero di
+copie aggiunte. Git salva i dati solo una volta.
+
+A proposito, i file in +.git/objects+ sono copressi con zlib e
+conseguentemente non potete visualizzarne direttamente il contenuto.
+Passatele attraverso il filtro http://www.zlib.net/zpipe.c[zpipe -d], o
+eseguite:
+
+ $ git cat-file -p aa823728ea7d592acc69b36875a482cdf3fd5c8d
+
+che visualizza appropriatamente l'oggetto scelto.
+
+=== Oggetti 'tree' ===
+
+Ma dove vanno a finire i nomi dei file? Devono essere salvati da qualche
+parte. Git si occupa dei nomi dei file in fase di commit:
+
+ $ git commit  # Scrivete un messaggio
+ $ find .git/objects -type f
+
+Adesso dovreste avere tre oggetti. Ora non sono più in grado di predire
+il nome dei due nuovi file, perché dipenderà in parte dal nome che avete
+scelto. Procederemo assumendo che avete scelto ``rose''. Se questo non
+fosse il caso potete sempre riscrivere la storia per far sembrare che lo
+sia:
+
+ $ git filter-branch --tree-filter 'mv NOME_DEL_VOSTRO_FILE rose'
+ $ find .git/objects -type f
+
+Adesso dovreste vedere il file
++.git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9+
+perché questo è il codice hash SHA1 del contenuto seguente:
+
+ "tree" SP "32" NUL "100644 rose" NUL 0xaa823728ea7d592acc69b36875a482cdf3fd5c8d
+
+Verificate che questo file contenga il contenuto precedente digitando:
+
+ $ echo 05b217bb859794d08bb9e4f7f04cbda4b207fbe9 | git cat-file --batch
+
+È più facile verificare il codice hash con zpipe:
+
+ $ zpipe -d < .git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9 | sha1sum
+
+Verificare l'hash è più complicato con il comando cat-file perché il suo
+output contiene elementi ulteriori oltre al file decompresso.
+
+Questo file è un oggetto 'tree': una lista di elementi consistenti in un
+tipo di file, un nome di file, e un hash. Nel nostro esempio il tipo di
+file è 100644, che indica che `rose` è un file normale e il codice hash
+e il codice hash è quello di un oggetto di tipo 'blob' che contiene il
+contenuto di `rose`.  Altri possibili tipi di file sono eseguibili, link
+simbolici e cartelle. Nell'ultimo caso il codice hash si riferisce ad un
+oggetto 'tree'.
+
+Se avete eseguito filter-branch avrete dei vecchi oggetti di cui non
+avete più bisogno. Anche se saranno cancellati automaticamente dopo il
+periodo di ritenzione automatica, ora li cancelleremo per rendere il
+nostro esempio più facile da seguire
+
+ $ rm -r .git/refs/original
+ $ git reflog expire --expire=now --all
+ $ git prune
+
+Nel caso di un vero progetto dovreste tipicamente evitare comandi del
+genere, visto che distruggono dei backup. Se volete un deposito più
+ordinato, è normalmente consigliabile creare un nuovo clone. Fate
+inoltre attenzione a manipolare direttamente il contenuto di +.git+: che
+cosa succederebbe se un comando Git è in esecuzione allo stesso tempo, o
+se se ci fosse un improvviso calo di corrente? In generale i refs
+dovrebbero essere cancellati con *git update-ref -d*, anche se spesso
+sembrerebbe sicuro cancella re +refs/original+ a mano.
+
+=== Oggetti 'commit' ===
+
+Abbiamo spiegato 2 dei 3 tipi di oggetto. Il terzo è l'oggetto
+'commit'. Il suo contenuto dipende dal messaggio di commit, come anche
+dalla data e l'ora in cui è stato creato. Perché far in maniera di
+ottenere la stessa cosa dobbiamo fare qualche ritocco:  
+
+ $ git commit --amend -m Shakespeare  # Cambiamento del messaggio di commit
+ $ git filter-branch --env-filter 'export
+     GIT_AUTHOR_DATE="Fri 13 Feb 2009 15:31:30 -0800"
+     GIT_AUTHOR_NAME="Alice"
+     GIT_AUTHOR_EMAIL="alice@example.com"
+     GIT_COMMITTER_DATE="Fri, 13 Feb 2009 15:31:30 -0800"
+     GIT_COMMITTER_NAME="Bob"
+     GIT_COMMITTER_EMAIL="bob@example.com"'  # Ritocco della data di creazione e degli autori
+ $ find .git/objects -type f
+
+Dovreste ora vedere il file +.git/objects/49/993fe130c4b3bf24857a15d7969c396b7bc187+
+che è il codice hash SHA1 del suo contenuto:
+
+ "commit 158" NUL
+ "tree 05b217bb859794d08bb9e4f7f04cbda4b207fbe9" LF
+ "author Alice <alice@example.com> 1234567890 -0800" LF
+ "committer Bob <bob@example.com> 1234567890 -0800" LF
+ LF
+ "Shakespeare" LF
+
+Come prima potete utilizzare zpipe o cat-file per verificare voi stessi.
+
+Questo è il primo commi, non ci sono quindi commit genitori. Ma i commit
+seguenti conterranno sempre almeno una linea che identifica un commit
+genitore.
+
+=== Indistinguibile dalla magia ===
+
+I segreti di Git sembrano troppo semplici. Sembra che basterebbe
+mescolare assieme qualche script shell e aggiungere un pizzico di codice
+C per preparare un sistema del genere in qualche ora: una combinazione
+di operazioni di filesystem di base e hashing SHA1, guarnito con
+lockfile e file di sincronizzazione per avere un po' di robustezza.
+Infatti questaè un descrizione accurata le prime versioni di Git.
+Malgrado ciò, a parte qualche astuta tecnica di compressione per
+risparmiare spazio e di indicizzazione per risparmiare tempo, ora
+sappiamo come Git cambia abilmente un sistema di file in un perfetto
+database per il controllo di versione.
+
+Ad esempio, se un file nel database degli oggetti è corrotto da un errore
+sul disco i codici hash non corrisponderanno più e verremo informati del
+problema. Calcolando il codice hash del codice hash di altri oggetti è
+possibile garantire integrità a tutti i livelli. I commit sono atomici,
+nel senso che un commit non può memorizzare modifiche parziali: possiamo
+calcolare il codice hash di un commit e salvarlo in un database dopo
+aver creato i relativi oggetti 'tree', 'blob' e 'commit'. Il database
+degli oggetti è immune da interruzioni inaspettate dovute ad esempio a
+cali di corrente.
+
+Possiamo anche far fronte ai tentativi di attacco più maliziosi.
+Supponiamo ad esempio che un avversario tenti di modificare di nascosto il
+contenuto di un file in una vecchia versione di un progetto. Per rendere
+il database degli oggetti coerente, il nostro avversario deve anche
+modificare il codice hash dei corrispondenti oggetti blob, visto che ora
+sarà una stringa di byte diversa. Questo significa che dovrà cambiare il
+codice hash di tutti gli oggetti tree che fanno riferimento al file, e
+di conseguenza cambiare l'hash di tutti gli oggetti commit in ognuno di
+questi tree, oltre ai codici hash di tutti i discendenti di questi
+commit. Questo implica che il codice hash dell'HEAD ufficiale differirà
+da quello del deposito corrotto. Seguendo la traccia di codici hash
+erronei possiamo localizzare con precisione il file corrotto, come anche
+il primo commit ad averlo introdotto.
+
+In conclusione, purché i 20 byte che rappresentano l'ultimo commit sono
+al sicuro, è impossibile manomettere il deposito Git.
+
+Che dire delle famose funzionalità di Git? Della creazione di branch?
+Dei merge? Delle tag? Semplici dettagli. L'HEAD corrente è conservata
+nel file +.git/HEAD+ che contiene un codice hash di un oggetto commit.
+Il codice hash viene aggiornato durante un commit e l'esecuzione di
+molti altri comandi. Le branch funzionano in maniera molto simile: sono
+file in +.git/refs/heads+. La stessa cosa vale per le tag, salvate in
++.git/refs/tags+ ma sono aggiornate da un insieme diverso di comandi.