Merge branch 'master' of https://github.com/matrig/gitmagic
[gitmagic.git] / it / history.txt
blob6414ba966d217f1448b158aa344855b25ba5d473
1 == Lezioni di storia ==
3 Una delle conseguenze della natura distribuita di Git è che il corso
4 storico può essere modificato facilmente. Ma se alterate il passato fate
5 attenzione: riscrivete solo le parti di storia che riguardano solo voi.
6 Nello stesso modo in cui nazioni dibattono le responsabilità di
7 atrocità, se qualcun altro ha un clone la cui storia differisce dalla
8 vostra, avrete problemi a riconciliare le vostre differenze.
10 Certi sviluppatori insistono che la storia debba essere considerata
11 immutabile, inclusi i difetti. Altri pensano invece che le strutture
12 storiche debbano essere rese presentabili prima di essere presentate
13 pubblicamente. Git è compatibile con entrambi i punti di vista. Come con
14 l'uso di clone, branch e merge, riscrivere la storia è semplicemente un
15 altra capacità che vi permette Git. Sta a voi farne buon uso.
17 === Mi correggo ===
19 Avete appena fatto un commit, ma ora vi accorgete che avreste voluto
20 scrivere un messaggio diverso? Allora eseguite:
22  $ git commit --amend
24 per modificare l'ultimo messaggio. Vi siete accorti di aver dimenticato
25 di aggiungere un file? Allora eseguite *git add* per aggiungerlo, e
26 eseguite il comando precedente.
28 Volete aggiungere qualche modifica supplementare nell'ultimo commit?
29 Allora fatele e eseguite:
31  $ git commit --amend -a
33 === ... e ancora di più ===
35 Supponiamo che il problema precedente è dieci volte peggio. Dopo una
36 lunga seduta avete fatto parecchi commit. Ma non siete soddisfatto da
37 come sono organizzati, e alcuni messaggi di commit potrebbero essere
38 riscritti meglio. Allora digitate:
40  $ git rebase -i HEAD~10
42 e gli ultimi 10 commit appariranno nel vostro $EDITOR di teso
43 preferito. Ecco un piccolo estratto come esempio:
45     pick 5c6eb73 Added repo.or.cz link
46     pick a311a64 Reordered analogies in "Work How You Want"
47     pick 100834f Added push target to Makefile
49 I commit più vecchi precedono quelli più recenti in questa lista, a
50 differenza del comando `log`. Qua 5c6eb73 è il commit più vecchio e
51 100834f è il più recente. In seguito:
53 - Rimuovete un commit cancellando la sua linea. È simile al comando
54   revert, ma è come se il commit non fosse mai esistito.
55 - Cambiate l'ordine dei commit cambiando l'ordine delle linee.
56 - Sostituite `pick` con:
57    * `edit` per marcare il commit per essere modificato.
58    * `reword` per modificare il messaggio nel log.
59    * `squash` per fare un merge del commit con quello precedente.
60    * `fixup` per fare un merge di questo commit con quello precedente e rimuovere il messaggio nel log.
62 Ad esempio, possiamo sostituire il secondo `pick` con `squash`:
64     pick 5c6eb73 Added repo.or.cz link
65     squash a311a64 Reordered analogies in "Work How 'ou Want"
66     pick 100834f Added push target to Makefile
68 Dopo aver salvato ed essere usciti dal file, Git fa un merge di a311a64
69 in 5c6eb73. Quindi *squash* fa un merge combinando le versioni nella
70 versione precedente.
72 Git quindi combina i loro messaggi e li presenta per eventuali
73 modifiche. Il comando *fixup* salta questo passo; il messaggio log a cui
74 viene applicato il comando viene semplicemente scartato.
76 Se avete marcato un commit con *edit*, Git vi riporta nel passato, al
77 commit più vecchio. Potete correggere il vecchio commit come descritto
78 nella sezione precedente, e anche creare nuovi commit nella posizione
79 corrente. Non appena siete soddisfatto con le rettifiche, ritornate in
80 avanti nel tempo eseguendo:
82  $ git rebase --continue
84 Git ripercorre i commit fino al prossimo *edit*, o fino al presente se
85 non ne rimane nessuno.
87 Potete anche abbandonare il vostro tentativo di cambiare la storia con
88 'rebase' nel modo seguente:
90  $ git rebase --abort
92 Quindi fate dei commit subito e spesso: potrete mettere tutto in ordine
93 più tardi con 'rebse'.
95 === E cambiamenti locali per finire ===
97 State lavorando ad un progetto attivo. Fate alcuni commit locali, e poi vi
98 sincronizzate con il deposito ufficiale con un merge. Questo ciclo si
99 ripete qualche volta fino a che siete pronti a integrare a vostra volta
100 i vostri cambiamenti nel deposito centrale con 'push'.
102 Ma a questo punto la storia del vostro clone Git locale è un confuso
103 garbuglio di modifiche vostre e ufficiali. Preferireste vedere tutti i
104 vostri cambiamenti in una sezione contigua, seguita dai cambiamenti
105 ufficiali.
107 Questo è un lavoro per *git rebase* come descritto precedentemente. In
108 molti casi potete usare la flag *--onto* per evitare interazioni.
110 Leggete *git help rebase* per degli esempi dettagliati di questo
111 fantastico comando. Potete scindere dei commit. Potete anche
112 riarrangiare delle branch di un deposito.
114 State attenti: rebase è un comando potente. In casi complessi fate prima
115 un backup con *git clone*.
117 === Riscrivere la storia ===
119 Occasionalmente c'è bisogno  di fare delle modifiche equivalenti a
120 cancellare con persone da una foto ufficiale, cancellandole dalla storia
121 in stile Stalinista. Per esempio, supponiamo che avete intenzione di
122 pubblicare un progetto, ma che questo include un file che per qualche
123 ragione volete tenere privato. Diciamo ad esempio che ho scritto il mio
124 numero di carta di credito in un file che ho aggiunto per sbaglio al
125 progetto. Cancellare il file non è abbastanza, visto che si può ancora
126 recuperare accedendo ai vecchi commit. Quello che bisogna fare è
127 rimuovere il file da tutti i commit:
129  $ git filter-branch --tree-filter 'rm file/segreto' HEAD
131 Nella documentazione in *git help filter-branch* viene discusso questo
132 esempio e dà anche un metodo più rapido. In generale, *filter-branch* vi
133 permette di modificare intere sezioni della storia con un singolo
134 comando.
136 In seguito la cartella +.git/refs/original+ conterrà lo stato del vostro
137 deposito prima dell'operazione. Verificate che il comando filter-branch
138 abbia fatto quello che desiderate, e cancellate questa cartella se
139 volete eseguire ulteriori comandi filter-branch.
141 Infine rimpiazzate i cloni del vostro progetto con la versione
142 revisionata se avete intenzione di interagire con loro più tardi.
144 === Fare la storia ===
146 [[makinghistory]]
147 Volete far migrare un progetto verso Git? Se è gestito con uno dei
148 sistemi più diffusi, è molto probabile che qualcuno abbia già scritto
149 uno script per esportare l'intera storia verso Git.
151 Altrimenti, documentatevi sul comando *git fast-import* che legge un
152 file di testo in un formato specifico per creare una storia Git a partire
153 dal nulla. Tipicamente uno script che utilizza questo comando è uno
154 script usa-e-getta scritto rapidamente e eseguito una volta sola per far
155 migrare il progetto.
157 Come esempio, incollate il testo seguente in un file temporaneo
158 chiamato `/tmp/history`:
159 ----------------------------------
160 commit refs/heads/master
161 committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000
162 data <<EOT
163 Commit iniziale
166 M 100644 inline hello.c
167 data <<EOT
168 #include <stdio.h>
170 int main() {
171   printf("Hello, world!\n");
172   return 0;
177 commit refs/heads/master
178 committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800
179 data <<EOT
180 Remplacement de printf() par write().
183 M 100644 inline hello.c
184 data <<EOT
185 #include <unistd.h>
187 int main() {
188   write(1, "Hello, world!\n", 14);
189   return 0;
192 ----------------------------------
194 Poi create un deposito Git a partire da questo file temporaneo
195 eseguendo:
197  $ mkdir project; cd project; git init
198  $ git fast-import --date-format=rfc2822 < /tmp/history
200 Potete fare il checkout dell'ultima versione di questo progetto con:
202  $ git checkout master .
204 Il comando *git fast-export* può convertire qualsiasi deposito Git nel
205 formato *git fast-import*, che vi permette di studiare come funzionano
206 gli script di esportazione, e vi permette anche di convertire un
207 deposito in un formato facilmente leggibile. Questi comandi permettono
208 anche di inviare un deposito attraverso canali che accettano solo
209 formato testo.
211 === Dov'è che ho sbagliato? ===
213 Avete appena scoperto un bug in una funzionalità del vostro programma
214 che siete sicuri funzionasse qualche mese fa. Argh! Da dove viene questo
215 bug? Se solo aveste testato questa funzionalità durante lo sviluppo!
217 Ma è troppo tardi. D'altra parte, a condizione di aver fatto dei commit
218 abbastanza spesso, Git può identificare il problema.
220  $ git bisect start
221  $ git bisect bad HEAD
222  $ git bisect good 1b6d
224 Git estrae uno stato a metà strada di queste due versioni (HEAD e 1b6d).
225 Testate la funzionalità e, se ancora non funziona:
227  $ git bisect bad
229 Altrimenti rimpiazzate "bad" con "good". Git vi trasporta a un nuovo
230 stato a metà strada tra le versioni "buone" e quelle "cattive",
231 riducendo così le possibilità. Dopo qualche iterazione, questa ricerca
232 binaria vi condurrà al commit che ha causato problemi. Una volta che la
233 vostra ricerca è finita, ritornate allo stato originario digitando:
235  $ git bisect reset
237 Invece di testare ogni cambiamento a mano, automatizzate la ricerca
238 scrivendo:
240  $ git bisect run my_script
242 Git usa il valore di ritorno dello script 'my_script' che avete passato
243 per decidere se un cambiamento è buono o cattivo: my_script deve
244 terminare con il valore 0 quando una versione è ok, 125 quando deve
245 essere ignorata, o un valore tra 1 e 127 se ha un bug. Un valore di
246 ritorno negativo abbandona il comando bisect.
248 Ma potete fare molto di più: la pagina di help spiega come visualizzare
249 le bisezioni, esaminare o rivedere il log di bisect, e eliminare noti
250 cambiamenti innocui per accelerare la ricerca.
252 === Chi è che ha sbagliato?  ===
254 Come in molti altri sistemi di controllo di versione, Git ha un comando
255 per assegnare una colpa:
257  $ git blame bug.c
259 Questo comando annota ogni linea del file mostrando chi l'ha cambiata
260 per ultimo e quando. A differenza di molti altri sistemi di controllo di
261 versione, questa operazione è eseguita off-line, leggendo solo da disco
262 locale.
264 === Esperienza personale ===
266 In un sistema di controllo di versione centralizzato le modifiche della
267 storia sono un'operazione difficile, che è solo disponibile agli
268 amministratori. Creare un clone, una branch e fare un merge sono delle
269 operazioni impossibili senza una connessione di rete. La stessa cosa
270 vale per operazioni di base come ispezionare la storia, o fare il commit
271 di un cambiamento. In alcuni sistemi, è necessaria una connessione di
272 rete anche solo per vedere le proprie modifiche o per aprire un file con
273 diritto di modifica.
275 Sistemi centralizzati precludono il lavoro off-line, e necessitano
276 infrastrutture di rete più ampie all'aumentare del numero di
277 sviluppatori. Ancora più importante è il fatto che le operazioni sono a
278 volte così lente da scoraggiare l'uso di alcune funzioni  avanzate, a
279 meno che non siano assolutamente necessarie. In casi estremi questo può
280 valere addirittura per comandi di base. Quando gli utenti devono
281 eseguire comandi lenti, la produttività viene compromessa per via delle
282 continue interruzioni del flusso di lavoro.
284 Ho sperimentato questi fenomeni personalmente. Git è stato il primo
285 sistema di controllo di versione che ho utilizzato. Mi sono velocemente
286 abituato al suo uso, dando per scontate molte funzionalità. Assumevo
287 semplicemente che altri sistemi fossero simili: scegliere un sistema di
288 controllo di versione non mi sembrava diverso da scegliere un editor di
289 testo o un navigatore web.
291 Sono rimasto molto sorpreso quando più tardi sono obbligato ad
292 utilizzare un sistema centralizzato. Una connessione internet instabile
293 ha poca importanza con Git, ma rende lo sviluppo quasi impossibile
294 quando il sistema esige che sia tanto affidabile quanto il disco locale.
295 Inoltre, mi sono trovato ad evitare l'uso di alcuni comandi per via
296 delle latenze che comportavano, fatto che finalmente mi impediva di
297 seguire il metodo di lavoro abituale.
299 Quando dovevo eseguire un comando lento, le interruzioni influivano
300 molto negativamente sulla mia concentrazione. Durante l'attesa della
301 fine delle comunicazioni col server, facevo qualcos'altro per passare il
302 tempo, come ad esempio controllare le email o scrivere della
303 documentazione. Quando ritornavo al lavoro iniziale, il comando aveva
304 terminato da tempo e mi ritrovare a dover cercare di ricordare che cosa
305 stessi facendo. Gli esseri umani non sono bravi a passare da un contesto
306 all'altro.
308 C'erano anche interessanti effetti di tragedia dei beni comuni:
309 prevedendo congestioni di rete, alcuni utenti consumavano più banda di
310 rete che necessario per effettuare operazioni il cui scopo era di
311 ridurre le loro attese future. Questi sforzi combinati risultavano ad
312 aumentare ulteriormente le congestioni, incoraggiando a consumare ancora
313 più larghezza di banda per cercare di evitare latenze sempre più lunghe.