git

Schema git

In figura, possiamo osservare 4 livelli ordinati:

  • working directory (WD): rappresenta la configurazione della directory di lavoro sul filesystem - esiste indipendentemente da git. Può essere vista come l’unione dei tracked and untracked files;
  • index (o area di staging): insieme dei tracked files da git.
  • (\(n\)?) local repository: insieme delle modifiche committate e relativo storico.
  • (\(n\)) remote repository: branch remoto; è possibile avere sia più branch per progetto remoto che più progetti remoti configurati.

Il termine repository è abbastanza misleading, perché è comunemente associato ad un progetto mentre in questa astrazione a livelli corrisponde di fatto a un branch.

Il passaggio tra un livello e l’altro non è mai automatico, ma è sempre esplicitato da un’operazione.

Operazioni di base

È consigliata la lettura di git Cheatsheet.

Puntatori commit git

Per ogni branch c’è un puntatore all’ultimo commit di tale branch. L’HEAD punta all’ultimo commit in cui siamo: normalmente corrisponde al puntatore del branch corrente; quando non è così siamo in una situazione di HEAD scollegato. È utile potersi spostare tra i commit per controllare revisioni precedenti, ma in caso di nuovi commit è importante creare un nuovo branch per poterci riferire ad esse.

git commitrecord changes to the repository

Il comando git commit ci permette di salvare del contenuto dall’index al branch locale.

Dopo aver creato il commit, l’HEAD e il puntatore al branch corrente puntano al nuovo commit. Anche il contenuto dell’index equivale al contenuto del commit.

Puntatori commit git 2

--amend

Con l’opzione --amend è possibile rimpiazziare facilmente l’ultimo commit con uno nuovo.

git commit –amend

git switchswitch branches

Il comando git switch ha un sottoinsieme delle funzionalità del comando git checkout ed è più semplice da utilizzare.

Permette di passare a un nuovo branch semplicemente modificando l’HEAD (e di conseguenza il contenuto dell’index e dei file).

git checkout

git mergejoin two or more development histories together

Il comando git merge è utile per unire branch (o più in generale alberi) insieme.

Se i due branch non sono divergenti, il merge avviene in modo banale con un fast-forward: nessun ulteriore commit verrà cambiato, verrà solo modificato il puntatore del branch e l’HEAD. Per forzare la creazione di un merge di commit (in gitFlow è apprezzato) occorre utilizzare l’opzione --no-ff.

In tutti gli altri casi, il merge può concludersi con successo oppure possono avvenire conflitti. Per risolverli, git ci proporrà un’interfaccia simile alla seguente.

<<<<<<< yours:sample.txt
Conflict resolution is hard;
let's go shopping.
=======
git makes conflict resolution easy.
>>>>>>> theirs:sample.txt

Una volta risolti tutti i conflitti è sufficiente commitare le modifiche concludendo quindi il merge.

git merge

La tecnica utilizzata per implementare la fusione di due rami è chiamata 3-way merge, inizialmente vengono considerati i commit HEAD dei due branch da unire e il primo commit comune a questi due (ovvero il commit da dove è iniziata la diramazione). A questo punto git cercherà di identificare le parti dei file modificate nelle diverse diramazioni sfruttando i commit considerati, se viene riscontrato un cambiamento della stessa porzione di file in entrambe le diramazioni significa che si è verificato un conflitto, e quindi verrà richiesto l’intervento manuale dell’utente, altrimenti verranno uniti automaticamente i due rami in un commit di merge.

git resetreset current HEAD to the specified state

Il comando git reset reimposta il contenuto dei file nell’index (e, opzionalmente con l’opzione --hard nella WD) all’ultimo commit puntato da HEAD o ad un altro commit.

git reset