SlideShare a Scribd company logo
1 of 48
Download to read offline
Corso Introduttivo a Git
Federico Spinelli
fspinelli@gmail.com
github.com/Tabjones
Cos’è Git?
● Distributed Version Control System:
○ Tiene traccia delle modifiche a un gruppo di file nel corso del tempo.
○ Modifiche fatte da voi o da altri collaboratori.
○ Qualsiasi modifica registrata è ripristinabile in qualunque momento.
● Ogni Git repository è independente e completo.
● Non c’è un server centralizzato.
● È veloce.
● Git non memorizza i cambiamenti ai file, ma salva sempre tutti i file nella
loro interezza.
● All’occorrenza ricostruisce al volo le differenze.
Perchè usare Git?
● Permette di gestire “versioni” di un progetto in modo semplice e veloce.
● Permette di vedere le modifiche tra “versioni” e all’occorrenza tornare a
un punto precedente del tempo. Ovvero mantiene i “backup” di un
progetto.
● Gestisce in modo elegante modifiche apportate da persone diverse.
● È usato in tutto il mondo.
● Git è stato creato da Linus Torvald, il creatore di Linux.
Istallare Git
● Windows:
○ https://git-for-windows.github.io/
● Mac:
○ https://code.google.com/archive/p/git-osx-installer/downloads
● Linux:
○ sudo apt-get install git
● Configurare Git affinchè ti riconosca
git config --global user.name "Federico Spinelli"
git config --global user.email fspinelli@gmail.com
● Creare un repository Git
mkdir ImparareGit
cd ImparareGit
mkdir libs
touch libs/foo.txt
mkdir templates
touch templates/bar.txt
git init
Comandi Base
● Git mantiene un database chiave/valore di tutto il vostro progetto.
● Lo fa solo per i file che gli dite voi !
● Aggiungiamo il primo file a Git
git add libs/foo.txt
Con questo comando, git ispeziona il contenuto del file (è vuoto!) e lo memorizza nel suo database
chiave/valore, chiamato Object Database e conservato su file system nella directory nascosta .git.
Aggiungere un file a Git
● Il file appena aggiunto formerà una voce nel database
Per il valore git userà il contenuto stesso del file; per la chiave, calcolerà lo SHA1
(Secure Hash Algorithm 1) del contenuto.
Per curiosità nel caso di un file vuoto, questa vale
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391, che in assenza di ambiguità
può essere abbreviata!
● Aggiungiamo anche il secondo file
git add templates/bar.txt
Ora, dato che i due file hanno lo stesso identico contenuto (sono entrambi
vuoti!), nel Database entrambi verranno conservati in un unico oggetto.
Git non ha bisogno di creare una nuova voce per accedere al contenuto.
Il Database
● I File memorizzati nel Database sono chiamati blob
● Git ha memorizzato nel Database solo il contenuto dei file.
● Non il loro nome ne la loro posizione (apparentemente).
Naturalmente, però, a noi il nome dei file e la loro posizione interessano eccome. Per questo, Git
memorizza nel Database anche altri oggetti, chiamati tree che servono proprio a memorizzare il
contenuto delle varie directory e i nomi dei file.
Il Database 2
Nel nostro esempio avremo 3 tree.
Come ogni altro oggetto, anche i tree sono memorizzati
come oggetti chiave/valore e sono come delle freccie
che puntano ad altri tree oppure a blob.
● Tutte le strutture del database sono raccolte in un contenitore, chiamato
Commit
Git Commit
Naturalmente, come tutti gli altri oggetti del Database
anche i Commit sono memorizzati in una voce
chiave/valore.
● lI Commit può essere visto come una
fotografia dello stato attuale del progetto
● Eseguiamo il primo Commit
git commit -m "Commit A. Ecco il mio primo commit"
Con questo comando stiamo dicendo a Git di memorizzare nel repository, cioè nella storia del progetto,
il Commit, preparato in precedenza a colpi di add
Git Commit 2
Lo stato del repository adesso
contiene il primo commit. Ma cos’
è l’index ?
● L’ index è una struttura che fa da cuscinetto tra il file system e il Git
repository
● il file system è la cartella che contiene i files sul computer.
● il repository è il database dove Git conserva i vari Commit.
● L’ index è uno spazio che Git ti mette a disposizione per creare il tuo
prossimo commit prima di registrarlo definitivamente nel repository.
Il comando “git add” aggiunge un file all’index, mentre il comando “git commit” salva lo stato attuale
dell’index nel repository
Index o Staging Area
● Fisicamente l’ index non è molto diverso dal
repository: entrambi conservano nel
database le strutture tree e blob. Di fatto
l’index è un oggetto Commit come gli altri.
● Proviamo a fare delle modifiche a un file
echo “nel mezzo del cammin” >> libs/foo.txt
● E aggiorniamo l’ index
git add libs/foo.txt
Il contenuto di libs/foo.txt non è mai stato registrato, quindi Git
aggiunge all’Object Database un nuovo blob col nuovo
contenuto del file; contestualmente, aggiorna il tree libs perché il
puntatore chiamato foo.txt indirizzi il nuovo blob.
Index o Staging Area 2
● L’ index mantiene sempre una copia dell’ultimo commit, così che tu
possa continuare a lavorare senza interruzioni.
echo “happy happy joy joy” > doh.html
git add doh.html
Git aggiunge un nuovo blob object col contenuto del
file e, contestualmente, aggiunge nel tree “/” un
nuovo puntatore chiamato doh.html che punta al
nuovo blob.
● Le nuove modifiche rimangono
parcheggiate nell’ index in attesa
che voi le spediate nel repository
con il prossimo “git commit”
● L’ index non è altro che un oggetto
Commit temporaneo che è sempre
la fotografia dello stato attuale del
progetto.
Index o Staging Area 3
● Aggiungiamo anche un nuovo file nella root del progetto
git commit -m “Commit B. Il mio secondo commit”
L’operazione di commit può essere vista anche come:
“Ok, prendi l’attuale index e fallo diventare un nuovo commit nel repository.
Poi restituiscimi l’index così che io possa fare altre modifiche“
● Git salva anche un puntatore al commit di
provenienza, perchè ci interessa salvare anche la
storia del nostro file system
● Il commit index è sempre presente, ma alcune
interfaccie grafiche non lo mostrano a meno che
non ci siano delle modifiche non ancora registrate
nel repository, guarda:
gitk
Il mio secondo commit
● Salviamo l’attuale index nel repository con un nuovo commit
● Dato che tutto è indirizzabile da una chiave posso dire a Git, che voglio far
tornare il file system com’era al tempo del “Commit A”
git checkout <<<Chiave del Commit A>>>
● Già, ma qual’è la chiave del “Commit A” ?
git log --oneline
Mostra un elenco di tutti i commit memorizzati nel repository
Tornare indietro nel tempo
● Supponiamo che la chiave
SHA1 del “Commit A” sia
56674fb, allora
git checkout 56674fb
In definitiva il checkout riporta il file system
allo stato in cui era al momento del commit
● Che succede se dallo stato attuale del “Commit A” facessi altre modifiche
e creassi un nuovo Commit ?
echo “ei fu siccome immobile” > README.md
git add README.md
git commit -m “Ecco il commit C”
● Ho creato una situazione in cui C è figlio di A e non di B, ho creato una
diramazione. (Da non confondere con i branch!)
● Posso sempre muovermi tra Commit usando checkout e la chiave SHA1
del Commit corrispondente. Ma non è un po’ scomodo dover guardare
quelle chiavi tutte le volte ?
Divergere
● Git ti permette di assegnare un “etichetta” alle chiavi dei Commit
git branch bob 56674fb ← questa è la chiave del Commit A
● Ora bob è una variabile che contiene il “Commit A”, posso spostarmi lì
usando bob al posto della chiave SHA1
git checkout bob
● Queste variabili si chiamano branch
● Probabilmente hai notato che Git ha già creato un branch per te, il
“master” che in questo momento punta al “Commit B”, andiamo li e
creiamo un altro branch
git checkout master
git branch dev ← Se non specifichi una chiave, Git usa quella del commit attuale (Commit B)
I Branch
● Adesso cancelliamo bob, non ci serve più
git branch -d bob ← -d stà per delete, cancella
● Hai notato quel triangolino verde che ti segue ovunque ti sposti ? Quello è
un branch particolare chiamato HEAD, che punta sempre all’elemento del
repository nel quale ti trovi. Se ti sposti su dev, anche HEAD ti segue
git checkout dev
I Branch 2
● Quando esegui checkout a un branch ti “attacchi” a quel branch e
l’etichetta ti seguirà se aggiungi altri commit, prova:
touch style.css
git add style.css
git commit -m “adesso ho anche il css”
git checkout master
touch angular.js
git add angular.js
git commit -m “angular.js rocks”
← Come vedi, sia dev, sia master si sono
spostati seguendo i tuoi due nuovi
commit
● Ci sono anche altre scorciatoie per muoversi agilmente tra Commits, i
reference relativi.
I Branch 3
● La reference ^ significa “il commit precedente a”
git checkout master^ ← il Commit precedente a master
git checkout HEAD^^ ← 2 Commits prima di HEAD
● La reference ~n significa “n commit precedenti a”
git checkout dev~2 ← 2 Commit precedenti a dev
git checkout HEAD~3 ← 3 Commits prima di HEAD
Le Reference
● Supponiamo di voler farci dire da Git quali sono le differenze tra due
commit, per esempio che modifiche ho fatto da dev a master
git diff dev master
Con questo comando stiamo chiedendo a Git: “Qual’è l’elenco delle modifiche ai file da applicare a
dev affinchè il progetto diventi identico a quello fotografato in master ?”
● Puoi vedere anche le differenze di un file tra l’index e l’ultimo commit del
repository
Le Differenze
● Git cherry-pick è uno dei comandi più folli e versatili di Git.
● Applica i cambiamenti introdotti da un commit in un altro punto del
repository. Vediamo un esempio, creiamo un nuovo branch e
aggiungiamoci un commit
git checkout dev
git checkout -b experiment ←Puoi creare un nuovo branch e farci checkout con un solo
comando
touch experiment
git add experiment
git commit -m “un commit con un esperimento”
Il Cherry-Pick
● Adesso consideriamo l’ultima modifica appena fatta a partire da dev
git checkout master
git cherry-pick experiment
Cherry-pick “coglie” il commit che gli indichi e lo applica sul commit dove ti trovi.
Il Cherry-Pick 2
● Un uso comune di cherry-pick è correggere un bug a metà branch
● Creiamo un esempio
git checkout -b feature
touch feature && git add feature && git commit -m “feature”
touch orrore && git add orrore && git commit -m ”orrore e raccapriccio”
touch altra_feature && git add altra_feature && git commit -m “altra feature”
● Oh no! Il secondo Commit è stato un errore.
Se solo si potesse riscrivere la storia!
git checkout master
git branch --force feature ← Sposta il branch anche se era già assegnato a un altro commit
git checkout feature
● Adesso riapplichiamo solo i Commit che
ci interessano. Saltando il bug!
git cherry-pick b5041f3
git cherry-pick 841fb88
Il Cherry-Pick: Un esempio di uso
● Il rebase non è altro che una macro per eseguire una serie di cherry-pick
automaticamente, senza dover spostare a mano un commit alla volta
● Creiamo un esempio, modificando dev
git checkout dev
echo “a {color:red; }” >> style.css
git commit -am ”i link sono rossi”
● Vogliamo staccare tutto il ramo dev e riappiccicarlo sopra master!
Dal branch dev (abbiamo fatto checkout precedentemente)
git rebase master
Stai chiedendo a Git: “spostami il ramo corrente (dev) sulla nuova base (master)”.
Il che è del tutto equivalente a spostare uno per uno i commit con cherry-pick. Solo, più comodo.
Il Rebase
● Il rebase è estremamente utile in numerose situazioni, una molto
comune, che ti capiterà sicuramente, la simuliamo qui.
● Stacchiamo un nuovo branch da dev e lavoriamoci sopra
git checkout -b sviluppo
touch file1 && git add file1 && git commit -m”avanzamento 1”
touch file2 && git add file2 && git commit -m”avanzamento 2”
touch file3 && git add file3 && git commit -m”avanzamento 3”
● Supponiamo che nel frattempo un vostro
collega abbia lavorato a dev
git checkout dev
touch dev1 && git add dev1 && git commit -m”developer 1”
touch dev2 && git add dev2 && git commit -m”developer 2”
● Inevitabilmente vi ritrovate un questa
situazione
I mille usi del Rebase
● Supponiamo di voler rendere di nuovo lineare la storia, applicando i
Commit di sviluppo dopo quelli dei vostri colleghi in dev
● Con rebase la cosa è estremamente semplice
git checkout sviluppo
git rebase dev
Di nuovo stai chiedendo a Git: “riapplica tutto il
lavoro che ho fatto nel ramo corrente (sviluppo)
dopo quello che è stato fatto in dev”
● Tutto appare come se tu avessi iniziato a lavorare a sviluppo partendo
dall’ultima versione di dev !
I mille usi del Rebase 2
● Via via che prendi mano con Git ti rendi conto che puoi modificare i tuoi
commit letteralmente come vuoi, per esempio puoi
○ Invertire l’ordine di una serie di Commit
○ Spezzare in due un singolo ramo
○ Scambiare Commit tra un ramo e un altro
○ Aggiungere un Commit nel mezzo di un ramo
○ Spezzare un Commit in più di uno
○ Fondere più Commit in uno solo
● Attenzione però, se riscrivete la storia qualcun’altro potrebbe rimanerci
male !!
In generale non usate rebase o cherry-pick per riscrivere la storia se questa è stata in qualche modo
condivisa con un altro.
Nell’esempio precedente il branch sviluppo è solo locale, ovvero esiste SOLO sul vostro computer,
quindi potete modificarlo come volete senza danneggiare nessuno!
I mille usi del Rebase 3
● Il rebase non è l’unico comando che vi permette di integrare due (o più)
branch separati
● Git merge funziona esattamente come uno se lo aspetta, ovvero fonde
due o più commit insieme, vediamo un esempio
git checkout dev && git branch bugfix
git checkout bugfix
touch fix1 && git add fix1 && git commit -m ”bugfixing 1”
touch fix2 && git add fix2 && git commit -m ”bugfixing 2”
● Di nuovo abbiamo creato una situazione
divergente, da cui prima o poi vorremmo integrare i due rami
● Per esempio vogliamo aggiornare sviluppo in modo che contenga i
bugfixing introdotti da bugfix
Git Merge
● Fondiamo insieme i due rami
git checkout sviluppo
git merge bugfix
Con git merge bugfix hai chiesto a Git: “Procurami un
Commit che contenga tutto quello che c’è nel mio
branch corrente (sviluppo) e aggiungigci tutti i commit introdotti dal ramo bugfix”
● Git cerca nel suo database se per caso esiste un Commit che contenga
entrambi i rami
● Non lo trova perchè ripercorrendo a ritroso sviluppo non si incontra mai
bugfix
● Quindi Git crea un nuovo Commit al volo contenente tutti i Commit che gli
hai chiesto e lo aggiunge a sviluppo
● Il nuovo Commit ha quindi due genitori
Git Merge 2
● Da questa situazione, cosa succederebbe se mi spostassi su dev e
chiedessi a Git un merge col ramo
sviluppo ?
git checkout dev
git merge sviluppo
Per rispondere usiamo lo stesso ragionamento di
Prima, hai chiesto a Git: “Procurami un Commit che contenga tutto quello che c’è nel mio
branch corrente (dev) e aggiungigci tutti i commit introdotti dal ramo sviluppo”
● Di nuovo Git cerca nel suo database se per caso esiste un Commit che
contenga entrambi i rami
● E lo trova! L’ultimo commit di sviluppo, sicuramente contiene se stesso,
ma contiene anche dev, perchè ripercorrendo a ritroso si incontra dev.
Quindi non c’è dubbio che quel commit contenga già le modifiche
introdotte da dev
Fast forward merge
● Allora Git non ha motivo di creare un nuovo Commit e si limiterà
a spostarci sopra il branch dev
● Il branch dev è stato semplicemente spinto in avanti per contenere anche
sviluppo. Questo tipo di merge si chiama fast-forward
● Questo tipo di merge ti capiterà spessissimo, basta ricordarsi che se i due
rami sono sulla stessa linea di sviluppo, avverrà un fast-forward quando si
chiede un merge
Fast forward merge 2
● Si da il caso che un commit nato da un merge non sia limitato a solo due
genitori. In realtà può avere quanti genitori volete.
● Git merge infatti può fondere tutti i branch che volete in un colpo solo.
Creiamo 4 branch e fondiamoli insieme
git branch uno
git branch due
git branch tre
git branch quattro
git checkout uno
touch uno && git add uno && git commit -m”uno”
git checkout due
touch due && git add due && git commit -m”due”
git checkout tre
touch tre && git add tre && git commit -m”tre”
git checkout quattro
touch quattro && git add quattro && git commit -m ”e quattro”
Octopus merge
● Ora che abbiamo 4 rami chiediamo a dev di mergiarli tutti in un colpo solo
git checkout dev
git merge uno due tre quattro
Hai chiesto a Git di procurarti un Commit che contenesse sia dev sia tutti e quattro gli altri rami, non
avendolo trovato Git ne ha creato uno per te
● Questo tipo di merge si chiama octopus-merge
Octopus merge 2
● Fino ad ora abbiamo lavorato con un solo repository locale (sul nostro
computer), ma in realtà Git è anche un sistema peer-to-peer
● Il tuo repository può entrare a far parte di una rete di repository e
scambiare informazioni con altri repository
● Un qualsiasi repository connesso al tuo è un remote
Nota che un remote non deve necessariamente essere in rete, può anche essere in un’altra cartella del
tuo computer, per esempio in un disco che usi per i backup
I remote, andiamo in rete
● Ho creato un repository comune per il corso su GitHub, aggiungetelo
come remote
git remote add origin https://github.com/ImparareGit/ImparareGit.git
Hai aggiunto un remote che si chiama origin presente a quell’indirizzo, d’ora in poi per riferirti a quel
repository puoi semplicemente chiamarlo “origin”
● Puoi aggiungere quanti remote vuoi, basta che abbiano nomi diversi
● Origin adesso è connesso al tuo repository locale, con i comandi push e
fetch puoi spedire o ricevere un set di Commits
I remote
● Dopo tutti gli esercizi svolti, il nostro
repository locale è in questo stato
Il branch colorato di arancione è la posizione corrente
di HEAD
● Vediamo se origin contiene lo stato
attuale di tutto il nostro repository
locale
I remote 2
● Usiamo git fetch per ricevere i rami dal
repository remoto
git fetch origin
Oppure semplicemente “git fetch”, se si omette il nome del
remote, Git userà quello di default, dato che abbiamo solo
un remote, il nostro default è origin
● Dopo fetch il nostro repository non è
cambiato di una virgola, sono solo
comparse due strane etichette azzurre,
origin/feature e origin/master
● Vediamo cosa sono...
Git fetch
● origin/feature e origin/master sono due
branch remoti
● I branch remoti non possono essere
modificati da locale, se provate a
cancellarne uno, Git vi darà un errore
git branch -d origin/feature
Error: branch ‘origin/feature’ not found.
● Git dice che quel branch non esiste,
infatti quel branch è sul repository
remoto origin e non sul vostro
● I branch remoti sono una sorta di
reminder che vi mostrano lo stato dei
branch sul repository remoto
Branch remoti
● Quando abbiamo lanciato git fetch
abbiamo “scaricato” tutti i branch
presenti su origin.
● Dato che solo origin/feature e
origin/master sono comparsi significa
che il repository remoto non ha altri
branch
● Aggiorniamo origin con un altro ramo,
per esempio experiment
git push origin experiment
● Adesso origin ha anche experiment!
Git push
● Vediamo più in dettaglio il comando push, ha la seguente sintassi
git push <remote> <branch> ← <remote> è uno dei remote collegati, <branch> è il luogo sul
remote
dove aggiungere il branch, e contemporaneamente anche il branch
locale da inviare
git push origin experiment ← Significa, prendi il branch locale experiment e invialo a origin.
Questo dovrà salvarlo nel proprio branch experiment. Se non esiste
Git lo crea.
● Sia <remote>, sia <branch> possono essere omessi, in quel caso il remote
Sarà quello di default e il branch sarà l’attuale posizione di HEAD
● In realtà l’argomento <branch> può essere ulteriormente spezzettato in
<source>:<destination>, dandoci la possibilità di specificare il “source”
branch in locale e il “destination” branch sul remote. Vediamo un esempio
Git push 2
git push origin experiment:nuovo_esperimento
Questo comando dice a Git di prendere il branch locale experiment e di spedirlo al remote origin che
dovrà chiamarlo nuovo_esperimento.
← Solo il branch experiment è
visibile
per brevità
● In realtà questo, viene raramente fatto, poichè crea confusione. Però è
utile sapere che se il <source> è vuoto, Git cancellerà il branch remoto
git push origin :nuovo_esperimento
nuovo_esperimento sarà cancellato, perchè gli è stato detto che deve puntare al nulla, quindi Git lo
rimuove
Git push 3
● Vediamo adesso l’ultimo comando di questo corso, il pull.
In gran segreto ho aggiornato il branch origin/experiment con un nuovo
commit. Se guardate il vostro repository scoprirete che non è cambiato
nulla di una virgola.
● origin/experiment punta sempre al commit vecchio, origin è cambiato ma
il vostro repository locale ancora non lo sa!
Questo è perfettamente coerente con la natura non lineare di Git. I due repository locale e remoto sono
connessi ma si aggiornano SOLO al vostro comando.
● Chiediamo al nostro repository di scaricare lo stato di origin
git fetch origin
● Scoprendo che origin ha un nuovo commit che noi non abbiamo
← Se ci fate caso il nostro file system non è cambiato, il nostro
branch locale experiment punta sempre al commit vecchio.
Questo perchè Git vi da la possibilità di visionare i nuovi commit
remoti prima di integrarli con merge
Git pull
● Volendo possiamo integrare i cambiamenti remoti con
git checkout experiment
git merge origin/experiment ← Questo merge sarà un fast-forward
● Ma Git ci mette a disposizione un comando per fare entrambe le cose
contemporaneamente, git pull
git pull origin experiment
● git pull non è altro che una scorciatoia per fare git fetch seguito da git
merge
Il comando appena lanciato significa: “Scarica tutti i commit da origin/experiment e integrali con merge
nel mio branch locale experiment”
Git pull 2
● Adesso che abbiamo più chiari i comandi più importanti di Git possiamo
aggiornare il diagramma delle interazioni tra comandi
Interazione tra i comandi
● Visto che abbiamo il nostro repository pubblico a cui tutti abbiamo
accesso, usiamolo come repository centralizzato.
Un esempio pratico
● Ognuno di noi crei un
commit su experiment
git checkout experiment
Create un commit (o anche piu di uno se
volete), aggiungendo/modificando files e
mettendo il messaggio che preferite
● Adesso provate a pushare
su origin
git push origin experiment
Solo il primo di voi ce la farà (il più veloce),
gli altri riceveranno un simpatico
messaggio di errore in cui Git si lamenta
che non può integrare i cambiamenti sul
remote
● Cosa è successo ?
Il push del vostro collega ha fatto avanzare origin/experiment di un
commit, ma il vostro nuovo commit è figlio del vecchio experiment (locale)
che punta sempre a un commit oramai vecchio.
● Il vostro branch locale e quello remoto sono in divergenza e Git non sa
come integrare il nuovo commit, perchè per default il push accetta solo
fast-forward, Git vi suggerisce anche di eseguire un fetch prima di fare
qualunque cosa, facciamolo
git fetch
● Ora avete sostanzialmente due possibilità per integrare il vostro commit
con quello del collega
○ Merge: creare un nuovo commit che sia la fusione del vostro e di quello del collega
○ Rebase: riallineare il tuo commit dopo quello del collega
● Scegliete la soluzione che piu vi piace dopo di che fate push su origin
git push origin experiment
Un esempio pratico 2
● L’help di Git:
○ Lista di tutti i comandi disponibili: git help -a
○ Help su un comando specifico: git help merge
● Learn Git Branching:
http://learngitbranching.js.org/
Una guida interattiva, composta da una serie di esercizi a difficoltà
crescente, molto divertente e ne vale la pena!
● ProGit:
https://www.git-scm.com/book/en/v2
Un libro bellissimo, pratico e considerato uno dei migliori testi su Git mai
scritti, leggetelo non ve ne pentirete.
Risorse per approfondire

More Related Content

What's hot

Revisionare, tracciare, collaborare. Version control con git
Revisionare, tracciare, collaborare. Version control con gitRevisionare, tracciare, collaborare. Version control con git
Revisionare, tracciare, collaborare. Version control con gitFabio Alessandrelli
 
Git e GitHub - L'essenziale
Git e GitHub - L'essenziale Git e GitHub - L'essenziale
Git e GitHub - L'essenziale Gemma Catolino
 
Git/Continuous Integration/Docker: la terna dello sviluppo moderno.
Git/Continuous Integration/Docker: la terna dello sviluppo moderno.Git/Continuous Integration/Docker: la terna dello sviluppo moderno.
Git/Continuous Integration/Docker: la terna dello sviluppo moderno.Gerardo Di Iorio
 
Systemd - Firenze LUG
Systemd - Firenze LUGSystemd - Firenze LUG
Systemd - Firenze LUGTruelite
 
Git – lo stupido gestore di contenuti
Git – lo stupido gestore di contenutiGit – lo stupido gestore di contenuti
Git – lo stupido gestore di contenutiGiulio Caccin
 
Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5Marcello Teodori
 
Systemd - Como Lug
Systemd - Como LugSystemd - Como Lug
Systemd - Como LugTruelite
 
Corso Python Deltapromo - Lezione 3
Corso Python Deltapromo - Lezione 3Corso Python Deltapromo - Lezione 3
Corso Python Deltapromo - Lezione 3Paolo Ferretti
 
Git Flow - Un modello di branching che funziona
Git Flow - Un modello di branching che funzionaGit Flow - Un modello di branching che funziona
Git Flow - Un modello di branching che funzionaInnoteam Srl
 
Vagrant e Docker a confronto;scegliere ed iniziare
Vagrant e  Docker a confronto;scegliere ed iniziareVagrant e  Docker a confronto;scegliere ed iniziare
Vagrant e Docker a confronto;scegliere ed iniziareDaniele Mondello
 
Introduzione a Docker (parte 2 - Pratica)
Introduzione a Docker (parte 2 - Pratica)Introduzione a Docker (parte 2 - Pratica)
Introduzione a Docker (parte 2 - Pratica)Cristian Consonni
 
CI/CD - Presentazione Introduttiva
CI/CD - Presentazione IntroduttivaCI/CD - Presentazione Introduttiva
CI/CD - Presentazione IntroduttivaMatteo Di Carlo
 
Livin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzioneLivin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzionegiacomos
 
Introduzione a Docker (Maggio 2017) [ITA]
Introduzione a Docker (Maggio 2017) [ITA]Introduzione a Docker (Maggio 2017) [ITA]
Introduzione a Docker (Maggio 2017) [ITA]Valerio Radice
 
Chi ha paura di Github? Conosciamolo meglio!
Chi ha paura di Github? Conosciamolo meglio!Chi ha paura di Github? Conosciamolo meglio!
Chi ha paura di Github? Conosciamolo meglio!Giacoma Allegretta
 
Google cloud: Big Data + docker = kubernetes
Google cloud: Big Data + docker = kubernetesGoogle cloud: Big Data + docker = kubernetes
Google cloud: Big Data + docker = kubernetesGiuliano Latini
 

What's hot (20)

Revisionare, tracciare, collaborare. Version control con git
Revisionare, tracciare, collaborare. Version control con gitRevisionare, tracciare, collaborare. Version control con git
Revisionare, tracciare, collaborare. Version control con git
 
Git e GitHub - L'essenziale
Git e GitHub - L'essenziale Git e GitHub - L'essenziale
Git e GitHub - L'essenziale
 
Perchè Git?
Perchè Git?Perchè Git?
Perchè Git?
 
Git/Continuous Integration/Docker: la terna dello sviluppo moderno.
Git/Continuous Integration/Docker: la terna dello sviluppo moderno.Git/Continuous Integration/Docker: la terna dello sviluppo moderno.
Git/Continuous Integration/Docker: la terna dello sviluppo moderno.
 
Emerasoft Git quickstart
Emerasoft Git quickstartEmerasoft Git quickstart
Emerasoft Git quickstart
 
Systemd - Firenze LUG
Systemd - Firenze LUGSystemd - Firenze LUG
Systemd - Firenze LUG
 
Git – lo stupido gestore di contenuti
Git – lo stupido gestore di contenutiGit – lo stupido gestore di contenuti
Git – lo stupido gestore di contenuti
 
Docker & DevOps
Docker  & DevOpsDocker  & DevOps
Docker & DevOps
 
Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5
 
Systemd - Como Lug
Systemd - Como LugSystemd - Como Lug
Systemd - Como Lug
 
Corso Python Deltapromo - Lezione 3
Corso Python Deltapromo - Lezione 3Corso Python Deltapromo - Lezione 3
Corso Python Deltapromo - Lezione 3
 
Git Flow - Un modello di branching che funziona
Git Flow - Un modello di branching che funzionaGit Flow - Un modello di branching che funziona
Git Flow - Un modello di branching che funziona
 
Vagrant e Docker a confronto;scegliere ed iniziare
Vagrant e  Docker a confronto;scegliere ed iniziareVagrant e  Docker a confronto;scegliere ed iniziare
Vagrant e Docker a confronto;scegliere ed iniziare
 
Introduzione a Docker (parte 2 - Pratica)
Introduzione a Docker (parte 2 - Pratica)Introduzione a Docker (parte 2 - Pratica)
Introduzione a Docker (parte 2 - Pratica)
 
CI/CD - Presentazione Introduttiva
CI/CD - Presentazione IntroduttivaCI/CD - Presentazione Introduttiva
CI/CD - Presentazione Introduttiva
 
introduzione a symfony 2
introduzione a symfony 2 introduzione a symfony 2
introduzione a symfony 2
 
Livin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzioneLivin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzione
 
Introduzione a Docker (Maggio 2017) [ITA]
Introduzione a Docker (Maggio 2017) [ITA]Introduzione a Docker (Maggio 2017) [ITA]
Introduzione a Docker (Maggio 2017) [ITA]
 
Chi ha paura di Github? Conosciamolo meglio!
Chi ha paura di Github? Conosciamolo meglio!Chi ha paura di Github? Conosciamolo meglio!
Chi ha paura di Github? Conosciamolo meglio!
 
Google cloud: Big Data + docker = kubernetes
Google cloud: Big Data + docker = kubernetesGoogle cloud: Big Data + docker = kubernetes
Google cloud: Big Data + docker = kubernetes
 

Viewers also liked

Linux Day 2015 Genova
Linux Day 2015 GenovaLinux Day 2015 Genova
Linux Day 2015 Genovamperrando
 
Sys05 uso consapevole di git - beyond the basic
Sys05   uso consapevole di git - beyond the basicSys05   uso consapevole di git - beyond the basic
Sys05 uso consapevole di git - beyond the basicDotNetCampus
 
Git - An Introduction
Git - An IntroductionGit - An Introduction
Git - An IntroductionBehzad Altaf
 
Git基礎介紹
Git基礎介紹Git基礎介紹
Git基礎介紹Max Ma
 
Git in a nutshell
Git in a nutshellGit in a nutshell
Git in a nutshellNelson Tai
 
Git 101 Presentation
Git 101 PresentationGit 101 Presentation
Git 101 PresentationScott Chacon
 
Git and GitHub
Git and GitHubGit and GitHub
Git and GitHubJames Gray
 
[NDC16] Effective Git
[NDC16] Effective Git[NDC16] Effective Git
[NDC16] Effective GitChanwoong Kim
 
Advanced Git
Advanced GitAdvanced Git
Advanced Gitsegv
 
Getting Git Right
Getting Git RightGetting Git Right
Getting Git RightSven Peters
 
Intro to git and git hub
Intro to git and git hubIntro to git and git hub
Intro to git and git hubVenkat Malladi
 
Git 101 - Crash Course in Version Control using Git
Git 101 - Crash Course in Version Control using GitGit 101 - Crash Course in Version Control using Git
Git 101 - Crash Course in Version Control using GitGeoff Hoffman
 

Viewers also liked (20)

Linux Day 2015 Genova
Linux Day 2015 GenovaLinux Day 2015 Genova
Linux Day 2015 Genova
 
Sys05 uso consapevole di git - beyond the basic
Sys05   uso consapevole di git - beyond the basicSys05   uso consapevole di git - beyond the basic
Sys05 uso consapevole di git - beyond the basic
 
Git–SVN
Git–SVNGit–SVN
Git–SVN
 
GITT (part 1 of 2)
GITT (part 1 of 2)GITT (part 1 of 2)
GITT (part 1 of 2)
 
Introduzione a git
Introduzione a gitIntroduzione a git
Introduzione a git
 
Mini git tutorial
Mini git tutorialMini git tutorial
Mini git tutorial
 
Git - An Introduction
Git - An IntroductionGit - An Introduction
Git - An Introduction
 
Anatomia di un progetto open-source
Anatomia di un progetto open-sourceAnatomia di un progetto open-source
Anatomia di un progetto open-source
 
Git基礎介紹
Git基礎介紹Git基礎介紹
Git基礎介紹
 
Git in a nutshell
Git in a nutshellGit in a nutshell
Git in a nutshell
 
Git 101 Presentation
Git 101 PresentationGit 101 Presentation
Git 101 Presentation
 
Git and Github
Git and GithubGit and Github
Git and Github
 
Git and GitHub
Git and GitHubGit and GitHub
Git and GitHub
 
[NDC16] Effective Git
[NDC16] Effective Git[NDC16] Effective Git
[NDC16] Effective Git
 
Advanced Git
Advanced GitAdvanced Git
Advanced Git
 
Git Tutorial 教學
Git Tutorial 教學Git Tutorial 教學
Git Tutorial 教學
 
Introduction to git
Introduction to gitIntroduction to git
Introduction to git
 
Getting Git Right
Getting Git RightGetting Git Right
Getting Git Right
 
Intro to git and git hub
Intro to git and git hubIntro to git and git hub
Intro to git and git hub
 
Git 101 - Crash Course in Version Control using Git
Git 101 - Crash Course in Version Control using GitGit 101 - Crash Course in Version Control using Git
Git 101 - Crash Course in Version Control using Git
 

Similar to GitSlides

Git gestione comoda del repository
Git   gestione comoda del repositoryGit   gestione comoda del repository
Git gestione comoda del repositoryRoberto Polli
 
Git: un'introduzione pratica
Git: un'introduzione praticaGit: un'introduzione pratica
Git: un'introduzione praticaBabel
 
Introduzione a Git e GitLab
Introduzione a Git e GitLabIntroduzione a Git e GitLab
Introduzione a Git e GitLabYefry Figueroa
 
Migrare da un VCS centralizzato a Git
Migrare da un VCS centralizzato a GitMigrare da un VCS centralizzato a Git
Migrare da un VCS centralizzato a GitGian Maria Ricci
 
Introduzione a git
Introduzione a gitIntroduzione a git
Introduzione a gitrpanfili
 
Sublime Text Tips & Tricks
Sublime Text Tips & TricksSublime Text Tips & Tricks
Sublime Text Tips & TricksLuca Montanera
 
Da GitHub a Nuget con la nuova build di Visual Studio Online
Da GitHub a Nuget con la nuova build di Visual Studio OnlineDa GitHub a Nuget con la nuova build di Visual Studio Online
Da GitHub a Nuget con la nuova build di Visual Studio OnlineDavide Benvegnù
 
GUI in Gtk+ con Glade & Anjuta
GUI in Gtk+ con Glade & AnjutaGUI in Gtk+ con Glade & Anjuta
GUI in Gtk+ con Glade & Anjutadelfinostefano
 
Development process
Development processDevelopment process
Development processEmidio Croci
 
Lezione 4 - Pratica - Lavorare in azienda: il teamwork
Lezione 4 - Pratica - Lavorare in azienda: il teamworkLezione 4 - Pratica - Lavorare in azienda: il teamwork
Lezione 4 - Pratica - Lavorare in azienda: il teamworkGiuseppe Cramarossa
 
Dall'idea al deploy un lungo viaggio che passa per git flow e semver
Dall'idea al deploy   un lungo viaggio che passa per git flow e semverDall'idea al deploy   un lungo viaggio che passa per git flow e semver
Dall'idea al deploy un lungo viaggio che passa per git flow e semverMauro Servienti
 
Create R package with RStudio
Create R package with RStudioCreate R package with RStudio
Create R package with RStudioNicola Procopio
 

Similar to GitSlides (20)

Git
GitGit
Git
 
GIT SOTTO IL COFANO
GIT SOTTO IL COFANOGIT SOTTO IL COFANO
GIT SOTTO IL COFANO
 
Git
GitGit
Git
 
Git gestione comoda del repository
Git   gestione comoda del repositoryGit   gestione comoda del repository
Git gestione comoda del repository
 
Git: un'introduzione pratica
Git: un'introduzione praticaGit: un'introduzione pratica
Git: un'introduzione pratica
 
Xamarin DevOps
Xamarin DevOpsXamarin DevOps
Xamarin DevOps
 
Introduzione a Git
Introduzione a GitIntroduzione a Git
Introduzione a Git
 
Introduzione a Git e GitLab
Introduzione a Git e GitLabIntroduzione a Git e GitLab
Introduzione a Git e GitLab
 
Migrare da un VCS centralizzato a Git
Migrare da un VCS centralizzato a GitMigrare da un VCS centralizzato a Git
Migrare da un VCS centralizzato a Git
 
Introduzione a git
Introduzione a gitIntroduzione a git
Introduzione a git
 
Git in 5 minuti
Git in 5 minutiGit in 5 minuti
Git in 5 minuti
 
Sublime Text Tips & Tricks
Sublime Text Tips & TricksSublime Text Tips & Tricks
Sublime Text Tips & Tricks
 
Da GitHub a Nuget con la nuova build di Visual Studio Online
Da GitHub a Nuget con la nuova build di Visual Studio OnlineDa GitHub a Nuget con la nuova build di Visual Studio Online
Da GitHub a Nuget con la nuova build di Visual Studio Online
 
GUI in Gtk+ con Glade & Anjuta
GUI in Gtk+ con Glade & AnjutaGUI in Gtk+ con Glade & Anjuta
GUI in Gtk+ con Glade & Anjuta
 
Development process
Development processDevelopment process
Development process
 
Introduzione a Python e GitHub
Introduzione a Python e GitHub Introduzione a Python e GitHub
Introduzione a Python e GitHub
 
Desktop searching
Desktop searchingDesktop searching
Desktop searching
 
Lezione 4 - Pratica - Lavorare in azienda: il teamwork
Lezione 4 - Pratica - Lavorare in azienda: il teamworkLezione 4 - Pratica - Lavorare in azienda: il teamwork
Lezione 4 - Pratica - Lavorare in azienda: il teamwork
 
Dall'idea al deploy un lungo viaggio che passa per git flow e semver
Dall'idea al deploy   un lungo viaggio che passa per git flow e semverDall'idea al deploy   un lungo viaggio che passa per git flow e semver
Dall'idea al deploy un lungo viaggio che passa per git flow e semver
 
Create R package with RStudio
Create R package with RStudioCreate R package with RStudio
Create R package with RStudio
 

GitSlides

  • 1. Corso Introduttivo a Git Federico Spinelli fspinelli@gmail.com github.com/Tabjones
  • 2. Cos’è Git? ● Distributed Version Control System: ○ Tiene traccia delle modifiche a un gruppo di file nel corso del tempo. ○ Modifiche fatte da voi o da altri collaboratori. ○ Qualsiasi modifica registrata è ripristinabile in qualunque momento. ● Ogni Git repository è independente e completo. ● Non c’è un server centralizzato. ● È veloce. ● Git non memorizza i cambiamenti ai file, ma salva sempre tutti i file nella loro interezza. ● All’occorrenza ricostruisce al volo le differenze.
  • 3. Perchè usare Git? ● Permette di gestire “versioni” di un progetto in modo semplice e veloce. ● Permette di vedere le modifiche tra “versioni” e all’occorrenza tornare a un punto precedente del tempo. Ovvero mantiene i “backup” di un progetto. ● Gestisce in modo elegante modifiche apportate da persone diverse. ● È usato in tutto il mondo. ● Git è stato creato da Linus Torvald, il creatore di Linux.
  • 4. Istallare Git ● Windows: ○ https://git-for-windows.github.io/ ● Mac: ○ https://code.google.com/archive/p/git-osx-installer/downloads ● Linux: ○ sudo apt-get install git
  • 5. ● Configurare Git affinchè ti riconosca git config --global user.name "Federico Spinelli" git config --global user.email fspinelli@gmail.com ● Creare un repository Git mkdir ImparareGit cd ImparareGit mkdir libs touch libs/foo.txt mkdir templates touch templates/bar.txt git init Comandi Base
  • 6. ● Git mantiene un database chiave/valore di tutto il vostro progetto. ● Lo fa solo per i file che gli dite voi ! ● Aggiungiamo il primo file a Git git add libs/foo.txt Con questo comando, git ispeziona il contenuto del file (è vuoto!) e lo memorizza nel suo database chiave/valore, chiamato Object Database e conservato su file system nella directory nascosta .git. Aggiungere un file a Git
  • 7. ● Il file appena aggiunto formerà una voce nel database Per il valore git userà il contenuto stesso del file; per la chiave, calcolerà lo SHA1 (Secure Hash Algorithm 1) del contenuto. Per curiosità nel caso di un file vuoto, questa vale e69de29bb2d1d6434b8b29ae775ad8c2e48c5391, che in assenza di ambiguità può essere abbreviata! ● Aggiungiamo anche il secondo file git add templates/bar.txt Ora, dato che i due file hanno lo stesso identico contenuto (sono entrambi vuoti!), nel Database entrambi verranno conservati in un unico oggetto. Git non ha bisogno di creare una nuova voce per accedere al contenuto. Il Database ● I File memorizzati nel Database sono chiamati blob
  • 8. ● Git ha memorizzato nel Database solo il contenuto dei file. ● Non il loro nome ne la loro posizione (apparentemente). Naturalmente, però, a noi il nome dei file e la loro posizione interessano eccome. Per questo, Git memorizza nel Database anche altri oggetti, chiamati tree che servono proprio a memorizzare il contenuto delle varie directory e i nomi dei file. Il Database 2 Nel nostro esempio avremo 3 tree. Come ogni altro oggetto, anche i tree sono memorizzati come oggetti chiave/valore e sono come delle freccie che puntano ad altri tree oppure a blob.
  • 9. ● Tutte le strutture del database sono raccolte in un contenitore, chiamato Commit Git Commit Naturalmente, come tutti gli altri oggetti del Database anche i Commit sono memorizzati in una voce chiave/valore. ● lI Commit può essere visto come una fotografia dello stato attuale del progetto
  • 10. ● Eseguiamo il primo Commit git commit -m "Commit A. Ecco il mio primo commit" Con questo comando stiamo dicendo a Git di memorizzare nel repository, cioè nella storia del progetto, il Commit, preparato in precedenza a colpi di add Git Commit 2 Lo stato del repository adesso contiene il primo commit. Ma cos’ è l’index ?
  • 11. ● L’ index è una struttura che fa da cuscinetto tra il file system e il Git repository ● il file system è la cartella che contiene i files sul computer. ● il repository è il database dove Git conserva i vari Commit. ● L’ index è uno spazio che Git ti mette a disposizione per creare il tuo prossimo commit prima di registrarlo definitivamente nel repository. Il comando “git add” aggiunge un file all’index, mentre il comando “git commit” salva lo stato attuale dell’index nel repository Index o Staging Area
  • 12. ● Fisicamente l’ index non è molto diverso dal repository: entrambi conservano nel database le strutture tree e blob. Di fatto l’index è un oggetto Commit come gli altri. ● Proviamo a fare delle modifiche a un file echo “nel mezzo del cammin” >> libs/foo.txt ● E aggiorniamo l’ index git add libs/foo.txt Il contenuto di libs/foo.txt non è mai stato registrato, quindi Git aggiunge all’Object Database un nuovo blob col nuovo contenuto del file; contestualmente, aggiorna il tree libs perché il puntatore chiamato foo.txt indirizzi il nuovo blob. Index o Staging Area 2 ● L’ index mantiene sempre una copia dell’ultimo commit, così che tu possa continuare a lavorare senza interruzioni.
  • 13. echo “happy happy joy joy” > doh.html git add doh.html Git aggiunge un nuovo blob object col contenuto del file e, contestualmente, aggiunge nel tree “/” un nuovo puntatore chiamato doh.html che punta al nuovo blob. ● Le nuove modifiche rimangono parcheggiate nell’ index in attesa che voi le spediate nel repository con il prossimo “git commit” ● L’ index non è altro che un oggetto Commit temporaneo che è sempre la fotografia dello stato attuale del progetto. Index o Staging Area 3 ● Aggiungiamo anche un nuovo file nella root del progetto
  • 14. git commit -m “Commit B. Il mio secondo commit” L’operazione di commit può essere vista anche come: “Ok, prendi l’attuale index e fallo diventare un nuovo commit nel repository. Poi restituiscimi l’index così che io possa fare altre modifiche“ ● Git salva anche un puntatore al commit di provenienza, perchè ci interessa salvare anche la storia del nostro file system ● Il commit index è sempre presente, ma alcune interfaccie grafiche non lo mostrano a meno che non ci siano delle modifiche non ancora registrate nel repository, guarda: gitk Il mio secondo commit ● Salviamo l’attuale index nel repository con un nuovo commit
  • 15. ● Dato che tutto è indirizzabile da una chiave posso dire a Git, che voglio far tornare il file system com’era al tempo del “Commit A” git checkout <<<Chiave del Commit A>>> ● Già, ma qual’è la chiave del “Commit A” ? git log --oneline Mostra un elenco di tutti i commit memorizzati nel repository Tornare indietro nel tempo ● Supponiamo che la chiave SHA1 del “Commit A” sia 56674fb, allora git checkout 56674fb In definitiva il checkout riporta il file system allo stato in cui era al momento del commit
  • 16. ● Che succede se dallo stato attuale del “Commit A” facessi altre modifiche e creassi un nuovo Commit ? echo “ei fu siccome immobile” > README.md git add README.md git commit -m “Ecco il commit C” ● Ho creato una situazione in cui C è figlio di A e non di B, ho creato una diramazione. (Da non confondere con i branch!) ● Posso sempre muovermi tra Commit usando checkout e la chiave SHA1 del Commit corrispondente. Ma non è un po’ scomodo dover guardare quelle chiavi tutte le volte ? Divergere
  • 17. ● Git ti permette di assegnare un “etichetta” alle chiavi dei Commit git branch bob 56674fb ← questa è la chiave del Commit A ● Ora bob è una variabile che contiene il “Commit A”, posso spostarmi lì usando bob al posto della chiave SHA1 git checkout bob ● Queste variabili si chiamano branch ● Probabilmente hai notato che Git ha già creato un branch per te, il “master” che in questo momento punta al “Commit B”, andiamo li e creiamo un altro branch git checkout master git branch dev ← Se non specifichi una chiave, Git usa quella del commit attuale (Commit B) I Branch
  • 18. ● Adesso cancelliamo bob, non ci serve più git branch -d bob ← -d stà per delete, cancella ● Hai notato quel triangolino verde che ti segue ovunque ti sposti ? Quello è un branch particolare chiamato HEAD, che punta sempre all’elemento del repository nel quale ti trovi. Se ti sposti su dev, anche HEAD ti segue git checkout dev I Branch 2
  • 19. ● Quando esegui checkout a un branch ti “attacchi” a quel branch e l’etichetta ti seguirà se aggiungi altri commit, prova: touch style.css git add style.css git commit -m “adesso ho anche il css” git checkout master touch angular.js git add angular.js git commit -m “angular.js rocks” ← Come vedi, sia dev, sia master si sono spostati seguendo i tuoi due nuovi commit ● Ci sono anche altre scorciatoie per muoversi agilmente tra Commits, i reference relativi. I Branch 3
  • 20. ● La reference ^ significa “il commit precedente a” git checkout master^ ← il Commit precedente a master git checkout HEAD^^ ← 2 Commits prima di HEAD ● La reference ~n significa “n commit precedenti a” git checkout dev~2 ← 2 Commit precedenti a dev git checkout HEAD~3 ← 3 Commits prima di HEAD Le Reference
  • 21. ● Supponiamo di voler farci dire da Git quali sono le differenze tra due commit, per esempio che modifiche ho fatto da dev a master git diff dev master Con questo comando stiamo chiedendo a Git: “Qual’è l’elenco delle modifiche ai file da applicare a dev affinchè il progetto diventi identico a quello fotografato in master ?” ● Puoi vedere anche le differenze di un file tra l’index e l’ultimo commit del repository Le Differenze
  • 22. ● Git cherry-pick è uno dei comandi più folli e versatili di Git. ● Applica i cambiamenti introdotti da un commit in un altro punto del repository. Vediamo un esempio, creiamo un nuovo branch e aggiungiamoci un commit git checkout dev git checkout -b experiment ←Puoi creare un nuovo branch e farci checkout con un solo comando touch experiment git add experiment git commit -m “un commit con un esperimento” Il Cherry-Pick
  • 23. ● Adesso consideriamo l’ultima modifica appena fatta a partire da dev git checkout master git cherry-pick experiment Cherry-pick “coglie” il commit che gli indichi e lo applica sul commit dove ti trovi. Il Cherry-Pick 2
  • 24. ● Un uso comune di cherry-pick è correggere un bug a metà branch ● Creiamo un esempio git checkout -b feature touch feature && git add feature && git commit -m “feature” touch orrore && git add orrore && git commit -m ”orrore e raccapriccio” touch altra_feature && git add altra_feature && git commit -m “altra feature” ● Oh no! Il secondo Commit è stato un errore. Se solo si potesse riscrivere la storia! git checkout master git branch --force feature ← Sposta il branch anche se era già assegnato a un altro commit git checkout feature ● Adesso riapplichiamo solo i Commit che ci interessano. Saltando il bug! git cherry-pick b5041f3 git cherry-pick 841fb88 Il Cherry-Pick: Un esempio di uso
  • 25. ● Il rebase non è altro che una macro per eseguire una serie di cherry-pick automaticamente, senza dover spostare a mano un commit alla volta ● Creiamo un esempio, modificando dev git checkout dev echo “a {color:red; }” >> style.css git commit -am ”i link sono rossi” ● Vogliamo staccare tutto il ramo dev e riappiccicarlo sopra master! Dal branch dev (abbiamo fatto checkout precedentemente) git rebase master Stai chiedendo a Git: “spostami il ramo corrente (dev) sulla nuova base (master)”. Il che è del tutto equivalente a spostare uno per uno i commit con cherry-pick. Solo, più comodo. Il Rebase
  • 26. ● Il rebase è estremamente utile in numerose situazioni, una molto comune, che ti capiterà sicuramente, la simuliamo qui. ● Stacchiamo un nuovo branch da dev e lavoriamoci sopra git checkout -b sviluppo touch file1 && git add file1 && git commit -m”avanzamento 1” touch file2 && git add file2 && git commit -m”avanzamento 2” touch file3 && git add file3 && git commit -m”avanzamento 3” ● Supponiamo che nel frattempo un vostro collega abbia lavorato a dev git checkout dev touch dev1 && git add dev1 && git commit -m”developer 1” touch dev2 && git add dev2 && git commit -m”developer 2” ● Inevitabilmente vi ritrovate un questa situazione I mille usi del Rebase
  • 27. ● Supponiamo di voler rendere di nuovo lineare la storia, applicando i Commit di sviluppo dopo quelli dei vostri colleghi in dev ● Con rebase la cosa è estremamente semplice git checkout sviluppo git rebase dev Di nuovo stai chiedendo a Git: “riapplica tutto il lavoro che ho fatto nel ramo corrente (sviluppo) dopo quello che è stato fatto in dev” ● Tutto appare come se tu avessi iniziato a lavorare a sviluppo partendo dall’ultima versione di dev ! I mille usi del Rebase 2
  • 28. ● Via via che prendi mano con Git ti rendi conto che puoi modificare i tuoi commit letteralmente come vuoi, per esempio puoi ○ Invertire l’ordine di una serie di Commit ○ Spezzare in due un singolo ramo ○ Scambiare Commit tra un ramo e un altro ○ Aggiungere un Commit nel mezzo di un ramo ○ Spezzare un Commit in più di uno ○ Fondere più Commit in uno solo ● Attenzione però, se riscrivete la storia qualcun’altro potrebbe rimanerci male !! In generale non usate rebase o cherry-pick per riscrivere la storia se questa è stata in qualche modo condivisa con un altro. Nell’esempio precedente il branch sviluppo è solo locale, ovvero esiste SOLO sul vostro computer, quindi potete modificarlo come volete senza danneggiare nessuno! I mille usi del Rebase 3
  • 29. ● Il rebase non è l’unico comando che vi permette di integrare due (o più) branch separati ● Git merge funziona esattamente come uno se lo aspetta, ovvero fonde due o più commit insieme, vediamo un esempio git checkout dev && git branch bugfix git checkout bugfix touch fix1 && git add fix1 && git commit -m ”bugfixing 1” touch fix2 && git add fix2 && git commit -m ”bugfixing 2” ● Di nuovo abbiamo creato una situazione divergente, da cui prima o poi vorremmo integrare i due rami ● Per esempio vogliamo aggiornare sviluppo in modo che contenga i bugfixing introdotti da bugfix Git Merge
  • 30. ● Fondiamo insieme i due rami git checkout sviluppo git merge bugfix Con git merge bugfix hai chiesto a Git: “Procurami un Commit che contenga tutto quello che c’è nel mio branch corrente (sviluppo) e aggiungigci tutti i commit introdotti dal ramo bugfix” ● Git cerca nel suo database se per caso esiste un Commit che contenga entrambi i rami ● Non lo trova perchè ripercorrendo a ritroso sviluppo non si incontra mai bugfix ● Quindi Git crea un nuovo Commit al volo contenente tutti i Commit che gli hai chiesto e lo aggiunge a sviluppo ● Il nuovo Commit ha quindi due genitori Git Merge 2
  • 31. ● Da questa situazione, cosa succederebbe se mi spostassi su dev e chiedessi a Git un merge col ramo sviluppo ? git checkout dev git merge sviluppo Per rispondere usiamo lo stesso ragionamento di Prima, hai chiesto a Git: “Procurami un Commit che contenga tutto quello che c’è nel mio branch corrente (dev) e aggiungigci tutti i commit introdotti dal ramo sviluppo” ● Di nuovo Git cerca nel suo database se per caso esiste un Commit che contenga entrambi i rami ● E lo trova! L’ultimo commit di sviluppo, sicuramente contiene se stesso, ma contiene anche dev, perchè ripercorrendo a ritroso si incontra dev. Quindi non c’è dubbio che quel commit contenga già le modifiche introdotte da dev Fast forward merge
  • 32. ● Allora Git non ha motivo di creare un nuovo Commit e si limiterà a spostarci sopra il branch dev ● Il branch dev è stato semplicemente spinto in avanti per contenere anche sviluppo. Questo tipo di merge si chiama fast-forward ● Questo tipo di merge ti capiterà spessissimo, basta ricordarsi che se i due rami sono sulla stessa linea di sviluppo, avverrà un fast-forward quando si chiede un merge Fast forward merge 2
  • 33. ● Si da il caso che un commit nato da un merge non sia limitato a solo due genitori. In realtà può avere quanti genitori volete. ● Git merge infatti può fondere tutti i branch che volete in un colpo solo. Creiamo 4 branch e fondiamoli insieme git branch uno git branch due git branch tre git branch quattro git checkout uno touch uno && git add uno && git commit -m”uno” git checkout due touch due && git add due && git commit -m”due” git checkout tre touch tre && git add tre && git commit -m”tre” git checkout quattro touch quattro && git add quattro && git commit -m ”e quattro” Octopus merge
  • 34. ● Ora che abbiamo 4 rami chiediamo a dev di mergiarli tutti in un colpo solo git checkout dev git merge uno due tre quattro Hai chiesto a Git di procurarti un Commit che contenesse sia dev sia tutti e quattro gli altri rami, non avendolo trovato Git ne ha creato uno per te ● Questo tipo di merge si chiama octopus-merge Octopus merge 2
  • 35. ● Fino ad ora abbiamo lavorato con un solo repository locale (sul nostro computer), ma in realtà Git è anche un sistema peer-to-peer ● Il tuo repository può entrare a far parte di una rete di repository e scambiare informazioni con altri repository ● Un qualsiasi repository connesso al tuo è un remote Nota che un remote non deve necessariamente essere in rete, può anche essere in un’altra cartella del tuo computer, per esempio in un disco che usi per i backup I remote, andiamo in rete
  • 36. ● Ho creato un repository comune per il corso su GitHub, aggiungetelo come remote git remote add origin https://github.com/ImparareGit/ImparareGit.git Hai aggiunto un remote che si chiama origin presente a quell’indirizzo, d’ora in poi per riferirti a quel repository puoi semplicemente chiamarlo “origin” ● Puoi aggiungere quanti remote vuoi, basta che abbiano nomi diversi ● Origin adesso è connesso al tuo repository locale, con i comandi push e fetch puoi spedire o ricevere un set di Commits I remote
  • 37. ● Dopo tutti gli esercizi svolti, il nostro repository locale è in questo stato Il branch colorato di arancione è la posizione corrente di HEAD ● Vediamo se origin contiene lo stato attuale di tutto il nostro repository locale I remote 2
  • 38. ● Usiamo git fetch per ricevere i rami dal repository remoto git fetch origin Oppure semplicemente “git fetch”, se si omette il nome del remote, Git userà quello di default, dato che abbiamo solo un remote, il nostro default è origin ● Dopo fetch il nostro repository non è cambiato di una virgola, sono solo comparse due strane etichette azzurre, origin/feature e origin/master ● Vediamo cosa sono... Git fetch
  • 39. ● origin/feature e origin/master sono due branch remoti ● I branch remoti non possono essere modificati da locale, se provate a cancellarne uno, Git vi darà un errore git branch -d origin/feature Error: branch ‘origin/feature’ not found. ● Git dice che quel branch non esiste, infatti quel branch è sul repository remoto origin e non sul vostro ● I branch remoti sono una sorta di reminder che vi mostrano lo stato dei branch sul repository remoto Branch remoti
  • 40. ● Quando abbiamo lanciato git fetch abbiamo “scaricato” tutti i branch presenti su origin. ● Dato che solo origin/feature e origin/master sono comparsi significa che il repository remoto non ha altri branch ● Aggiorniamo origin con un altro ramo, per esempio experiment git push origin experiment ● Adesso origin ha anche experiment! Git push
  • 41. ● Vediamo più in dettaglio il comando push, ha la seguente sintassi git push <remote> <branch> ← <remote> è uno dei remote collegati, <branch> è il luogo sul remote dove aggiungere il branch, e contemporaneamente anche il branch locale da inviare git push origin experiment ← Significa, prendi il branch locale experiment e invialo a origin. Questo dovrà salvarlo nel proprio branch experiment. Se non esiste Git lo crea. ● Sia <remote>, sia <branch> possono essere omessi, in quel caso il remote Sarà quello di default e il branch sarà l’attuale posizione di HEAD ● In realtà l’argomento <branch> può essere ulteriormente spezzettato in <source>:<destination>, dandoci la possibilità di specificare il “source” branch in locale e il “destination” branch sul remote. Vediamo un esempio Git push 2
  • 42. git push origin experiment:nuovo_esperimento Questo comando dice a Git di prendere il branch locale experiment e di spedirlo al remote origin che dovrà chiamarlo nuovo_esperimento. ← Solo il branch experiment è visibile per brevità ● In realtà questo, viene raramente fatto, poichè crea confusione. Però è utile sapere che se il <source> è vuoto, Git cancellerà il branch remoto git push origin :nuovo_esperimento nuovo_esperimento sarà cancellato, perchè gli è stato detto che deve puntare al nulla, quindi Git lo rimuove Git push 3
  • 43. ● Vediamo adesso l’ultimo comando di questo corso, il pull. In gran segreto ho aggiornato il branch origin/experiment con un nuovo commit. Se guardate il vostro repository scoprirete che non è cambiato nulla di una virgola. ● origin/experiment punta sempre al commit vecchio, origin è cambiato ma il vostro repository locale ancora non lo sa! Questo è perfettamente coerente con la natura non lineare di Git. I due repository locale e remoto sono connessi ma si aggiornano SOLO al vostro comando. ● Chiediamo al nostro repository di scaricare lo stato di origin git fetch origin ● Scoprendo che origin ha un nuovo commit che noi non abbiamo ← Se ci fate caso il nostro file system non è cambiato, il nostro branch locale experiment punta sempre al commit vecchio. Questo perchè Git vi da la possibilità di visionare i nuovi commit remoti prima di integrarli con merge Git pull
  • 44. ● Volendo possiamo integrare i cambiamenti remoti con git checkout experiment git merge origin/experiment ← Questo merge sarà un fast-forward ● Ma Git ci mette a disposizione un comando per fare entrambe le cose contemporaneamente, git pull git pull origin experiment ● git pull non è altro che una scorciatoia per fare git fetch seguito da git merge Il comando appena lanciato significa: “Scarica tutti i commit da origin/experiment e integrali con merge nel mio branch locale experiment” Git pull 2
  • 45. ● Adesso che abbiamo più chiari i comandi più importanti di Git possiamo aggiornare il diagramma delle interazioni tra comandi Interazione tra i comandi
  • 46. ● Visto che abbiamo il nostro repository pubblico a cui tutti abbiamo accesso, usiamolo come repository centralizzato. Un esempio pratico ● Ognuno di noi crei un commit su experiment git checkout experiment Create un commit (o anche piu di uno se volete), aggiungendo/modificando files e mettendo il messaggio che preferite ● Adesso provate a pushare su origin git push origin experiment Solo il primo di voi ce la farà (il più veloce), gli altri riceveranno un simpatico messaggio di errore in cui Git si lamenta che non può integrare i cambiamenti sul remote
  • 47. ● Cosa è successo ? Il push del vostro collega ha fatto avanzare origin/experiment di un commit, ma il vostro nuovo commit è figlio del vecchio experiment (locale) che punta sempre a un commit oramai vecchio. ● Il vostro branch locale e quello remoto sono in divergenza e Git non sa come integrare il nuovo commit, perchè per default il push accetta solo fast-forward, Git vi suggerisce anche di eseguire un fetch prima di fare qualunque cosa, facciamolo git fetch ● Ora avete sostanzialmente due possibilità per integrare il vostro commit con quello del collega ○ Merge: creare un nuovo commit che sia la fusione del vostro e di quello del collega ○ Rebase: riallineare il tuo commit dopo quello del collega ● Scegliete la soluzione che piu vi piace dopo di che fate push su origin git push origin experiment Un esempio pratico 2
  • 48. ● L’help di Git: ○ Lista di tutti i comandi disponibili: git help -a ○ Help su un comando specifico: git help merge ● Learn Git Branching: http://learngitbranching.js.org/ Una guida interattiva, composta da una serie di esercizi a difficoltà crescente, molto divertente e ne vale la pena! ● ProGit: https://www.git-scm.com/book/en/v2 Un libro bellissimo, pratico e considerato uno dei migliori testi su Git mai scritti, leggetelo non ve ne pentirete. Risorse per approfondire