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 commit — record 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 switch — switch 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 merge — join 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 reset — reset 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