martedì 28 giugno 2011

Git reflogs

Git e' il sistema per la gestione delle revisioni che preferisco e che uso per la maggior parte dei miei progetti, alternando al suo fratello Mercurial.
Come e' noto, la capacita' di Git di lavorare con intricate connessioni di commit e di avere una storia non lineare e' superba. Esiste tuttavia un punto ove anche Git memorizza la storia in modo lineare: i reflogs.
I reflogs sono liste di identificativi SHA1, gli stessi usati per identificare gli oggetti in Git (commit, tag, ...). Lo scopo dei reflogs e' di associare ad una azione effettuata su un branch, ad esempio un commit, un punto nella storia. Ogni volta che un branch viene aggiornato (commit, checkout, merge, tag, rebase) viene memorizzata un'entry nel reflog indicando il tipo di azione, l'hash SHA1 di partenza, ove ci si trovava rispetto ad HEAD (nel tempo) e il messaggio descrittivo dell'azione.

Il seguente listato mostra una parte di reflog del progetto JFK:

$ git reflog
f16c3e0 HEAD@{0}: commit: Code clean up.
509b537 HEAD@{1}: commit: Inserted single includes for resources in the test goal.
c2d782b HEAD@{2}: checkout: moving from e3c164d49d5e50c42f90b9d142ef64ddc77c175c to master
e3c164d HEAD@{3}: checkout: moving from master to e3c164d49d5e50c42f90b9d142ef64ddc77c175c
c2d782b HEAD@{4}: commit (amend): Refactoring of the repository in order to use Maven for t
4c26949 HEAD@{5}: merge maven: Fast-forward
e3c164d HEAD@{6}: checkout: moving from maven to master
4c26949 HEAD@{7}: checkout: moving from e3c164d49d5e50c42f90b9d142ef64ddc77c175c to maven
e3c164d HEAD@{8}: checkout: moving from master to e3c164d49d5e50c42f90b9d142ef64ddc77c175c
e3c164d HEAD@{9}: checkout: moving from maven to master
4c26949 HEAD@{10}: checkout: moving from master to maven
e3c164d HEAD@{11}: checkout: moving from maven to master
4c26949 HEAD@{12}: commit: Refactoring of the repository in order to use Maven for the comp
e3c164d HEAD@{13}: checkout: moving from master to maven


Partendo dal fondo si ha che 13 modifiche prima dell'HEAD corrente (attenzione, le modifiche non sono per forza dei commit) si e' effettuato un checkout che ha portato HEAD a puntare dal ramo "master" a quello "maven". Analogamente si nota come "11 modifiche fa" si sia passati dal ramo "maven" a quello "master" per poi tornare nuovamente al ramo "maven" (10 modifiche fa).
L'hash riportato nella prima colonna indica a cosa puntava HEAD quando si e' svolta l'azione. Ad esempio nel caso della modifica 12 si aveva che HEAD puntava a 4c26949 (ramo "maven"); a seguito del cambio di ramo e successivo ritorno al ramo originario "maven" la HEAD e' tornata ad essere 4c26949. Questo perche' l'operazione 11 e' stata annullata dalla 10 che di fatto ha riportato la situazione di HEAD alla modifica 12. Analogamente la modifica 0 (HEAD corrente) punta alla HEAD corrente, come e' facile verificare con:

$ git log
commit f16c3e04a6220e5c246dda75832d3cb47890eb37


Riassumendo quindi si puo' dire che i reflog rappresentano un giornale delle azioni che hanno modificato la HEAD corrente (non importa su quale ramo si stia lavorando), e visto che ogni azione Git va a modificare la HEAD (commit, rebase, tag, branch, ...) si ha come risultato che i reflogs rappresentano la storia lineare del processo di sviluppo. In altre parole i reflogs sono il diario delle azioni svolte dagli sviluppatori sul repository, e volendo usare un brutto paragone sono una sorta di ".bash_history" del repository.

Nessun commento: