Compare commits
9 commits
7b35f5b47c
...
193ca1a70e
Author | SHA1 | Date | |
---|---|---|---|
|
193ca1a70e | ||
|
b92be4bf08 | ||
9602ef69cc | |||
515b9f2699 | |||
6c40a5f15c | |||
ed6d6ea9f7 | |||
1d6a6d9594 | |||
0448b01b58 | |||
|
f3eb22cdaf |
58
.gitignore
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
33
css/zoom.css
Normal file
|
@ -0,0 +1,33 @@
|
|||
img[data-action="zoom"] {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
.zoom-img,
|
||||
.zoom-img-wrap {
|
||||
position: relative;
|
||||
z-index: 666;
|
||||
-webkit-transition: all 300ms;
|
||||
transition: all 300ms;
|
||||
}
|
||||
img.zoom-img {
|
||||
cursor: zoom-out;
|
||||
}
|
||||
.zoom-overlay {
|
||||
z-index: 420;
|
||||
background: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
filter: "alpha(opacity=0)";
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 300ms;
|
||||
transition: opacity 300ms;
|
||||
}
|
||||
.zoom-overlay-open .zoom-overlay {
|
||||
filter: "alpha(opacity=100)";
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2Nzcy96b29tLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQjtDQUNqQjtBQUNEOztFQUVFLG1CQUFtQjtFQUNuQixhQUFhO0VBQ2IsOEJBQXNCO0VBQXRCLHNCQUFzQjtDQUN2QjtBQUNEO0VBQ0UsaUJBQWlCO0NBQ2xCO0FBQ0Q7RUFDRSxhQUFhO0VBQ2IsaUJBQWlCO0VBQ2pCLGdCQUFnQjtFQUNoQixPQUFPO0VBQ1AsUUFBUTtFQUNSLFNBQVM7RUFDVCxVQUFVO0VBQ1YscUJBQXFCO0VBQ3JCLDJCQUEyQjtFQUMzQixXQUFXO0VBQ1gsa0NBQStCO0VBQS9CLCtCQUErQjtDQUNoQztBQUNEO0VBQ0UsNkJBQTZCO0VBQzdCLFdBQVc7Q0FDWiIsImZpbGUiOiJ6b29tLmNzcyIsInNvdXJjZXNDb250ZW50IjpbImltZ1tkYXRhLWFjdGlvbj1cInpvb21cIl0ge1xuICBjdXJzb3I6IHpvb20taW47XG59XG4uem9vbS1pbWcsXG4uem9vbS1pbWctd3JhcCB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgei1pbmRleDogNjY2O1xuICB0cmFuc2l0aW9uOiBhbGwgMzAwbXM7XG59XG5pbWcuem9vbS1pbWcge1xuICBjdXJzb3I6IHpvb20tb3V0O1xufVxuLnpvb20tb3ZlcmxheSB7XG4gIHotaW5kZXg6IDQyMDtcbiAgYmFja2dyb3VuZDogI2ZmZjtcbiAgcG9zaXRpb246IGZpeGVkO1xuICB0b3A6IDA7XG4gIGxlZnQ6IDA7XG4gIHJpZ2h0OiAwO1xuICBib3R0b206IDA7XG4gIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICBmaWx0ZXI6IFwiYWxwaGEob3BhY2l0eT0wKVwiO1xuICBvcGFjaXR5OiAwO1xuICB0cmFuc2l0aW9uOiAgICAgIG9wYWNpdHkgMzAwbXM7XG59XG4uem9vbS1vdmVybGF5LW9wZW4gLnpvb20tb3ZlcmxheSB7XG4gIGZpbHRlcjogXCJhbHBoYShvcGFjaXR5PTEwMClcIjtcbiAgb3BhY2l0eTogMTtcbn1cbiJdfQ== */
|
|
@ -13,7 +13,23 @@ This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 Inte
|
|||
|
||||
## A chi è rivolto
|
||||
|
||||
Questo non è ancora chiaro...
|
||||
A chi si trova a volere/dovere usare Git, ed è ancora alle prime armi.
|
||||
|
||||
---
|
||||
|
||||
## Struttura del corso
|
||||
|
||||
<br />
|
||||
|
||||
## Parte 1
|
||||
|
||||
Le basi per lavorare in locale e collaborare con altri usando il forking workflow, da applicare senza porsi troppe domande.
|
||||
|
||||
<br />
|
||||
|
||||
## Parte 2
|
||||
|
||||
Una serie di strumenti avanzati, per chi ci ha preso gusto e vuole approfondire lo strumento.
|
||||
|
||||
---
|
||||
|
||||
|
@ -29,9 +45,6 @@ Questo non è ancora chiaro...
|
|||
|
||||
* gli internals (plumbing) di Git
|
||||
* le GUI
|
||||
* usi avanzati
|
||||
* GitHub e simili (sorry)
|
||||
* no, davvero: neanche l'ombra di una pull request, qui
|
||||
* amministrazione di un repository remoto
|
||||
* flame wars sui workflow
|
||||
|
||||
|
@ -96,9 +109,17 @@ Tutto vero, ma la sua user interface è un mezzo disastro.
|
|||
|
||||
### Bonus track
|
||||
|
||||
* cercare un esempio di ~/.gitconfig avanzato
|
||||
* cercare un esempio di ~/.gitconfig avanzato, con qualche alias per i comandi principali
|
||||
|
||||
---
|
||||
-----
|
||||
|
||||
## Parte 1
|
||||
|
||||
In cui forniamo un workflow precotto per chi non vuole porsi troppe domande, adatto allo sviluppo in solitaria o con pochi altri contributori.
|
||||
|
||||
Iniziamo lavorando in locale, per poi vedere come interagire con altri sviluppatori.
|
||||
|
||||
-----
|
||||
|
||||
## Le basi: creare un repository
|
||||
|
||||
|
@ -112,11 +133,9 @@ Clonare un repository remoto esistente:
|
|||
|
||||
-----
|
||||
|
||||
## Le basi: creare un repository
|
||||
## creare un repository: cosa è successo?
|
||||
|
||||
### Cosa è successo?
|
||||
|
||||
È stata creata la directory **.git** (il **repository**); se abbiamo fatto un clone, sono stati aggiunti i riferimenti al remote alla configurazione.
|
||||
È stata creata la directory **.git** (il **repository**); se abbiamo fatto un clone, sono stati aggiunti i riferimenti al remote.
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -127,6 +146,8 @@ Clonare un repository remoto esistente:
|
|||
|
||||
---
|
||||
|
||||
<!-- .slide: class="two-cols" -->
|
||||
|
||||
## Le basi: status
|
||||
|
||||
Vedere lo stato del sistema:
|
||||
|
@ -145,6 +166,8 @@ Vedere lo stato del sistema:
|
|||
|
||||
* **Staged**: nella staging area, pronti per il prossimo commit
|
||||
|
||||
<img style="width:300px" src="images/file-states.png" data-action="zoom">
|
||||
|
||||
---
|
||||
|
||||
## Le basi: add e commit
|
||||
|
@ -157,6 +180,10 @@ Committiamolo:
|
|||
|
||||
$ git commit [-m "messaggio di commit"]
|
||||
|
||||
Verifichiamo quanto accaduto:
|
||||
|
||||
$ git log
|
||||
|
||||
-----
|
||||
|
||||
## Le basi: add e commit
|
||||
|
@ -174,13 +201,12 @@ Abbiamo aggiunto un file alla staging area, per poi salvare uno snapshot del nos
|
|||
* git rm, git mv
|
||||
* come scrivere un messaggio di commit che non susciti sgomento?
|
||||
* le directory vuote non vengono salvate: .gitkeep / .gitignore
|
||||
* git add --patch
|
||||
|
||||
---
|
||||
|
||||
## Cosa sono i commit
|
||||
|
||||
Sono uno snapshot dell'intero stato del sistema in un dato momento, identificati da un hash.
|
||||
Sono uno snapshot dell'intero stato del sistema in un dato momento, **identificati da un hash**.
|
||||
|
||||
I commit hash sono generati partendo da: messaggio, committer, author, dates, tree, parent hash.
|
||||
|
||||
|
@ -205,7 +231,7 @@ Un tag è un puntatore ad un commit:
|
|||
|
||||
### Bonus track
|
||||
|
||||
* esistono sia i tag lightweight che annotated. La differenza principale è che i primi sono solo dei puntatori, i secondi sono oggetti completi: hanno un author e possono essere firmati.
|
||||
* esistono sia i tag *lightweight* che *annotated*. La differenza principale è che i primi sono solo dei puntatori, i secondi sono oggetti completi: hanno un author e possono essere firmati.
|
||||
|
||||
---
|
||||
|
||||
|
@ -237,28 +263,11 @@ Per vedere quanto è stato posto in staging area:
|
|||
|
||||
$ git diff --staged
|
||||
|
||||
<br />
|
||||
|
||||
### Bonus track
|
||||
|
||||
è possibile creare e riapplicare una patch usando i comandi:
|
||||
|
||||
$ git format-patch [refs]
|
||||
$ git apply patch-file.diff
|
||||
|
||||
---
|
||||
|
||||
## Scopriamo chi incolpare!
|
||||
|
||||
Annotare un file con chi ha effettuato l'ultima modifica riga per riga:
|
||||
|
||||
$ git blame file.txt
|
||||
|
||||
---
|
||||
|
||||
## Aggiustare i danni
|
||||
|
||||
Modificare l'ultimo commit (ad esempio per aggiungere un file, modificare il commit message o l'autore):
|
||||
Modificare l'ultimo commit (aggiungere un file, modificare il commit message o l'autore, ...):
|
||||
|
||||
$ git commit --amend [--author="Name Surname <user@example.com>"]
|
||||
|
||||
|
@ -284,47 +293,6 @@ Voglio creare un nuovo commit che annulla le modifiche introdotte da un commit p
|
|||
|
||||
---
|
||||
|
||||
## Mettere il lavoro da parte: stash
|
||||
|
||||
Capita di dover mettere da parte il lavoro nella directory corrente senza voler committare:
|
||||
|
||||
$ git stash
|
||||
|
||||
Vedere la lista:
|
||||
|
||||
$ git stash list
|
||||
|
||||
Riapplicare una modifica messa in stash:
|
||||
|
||||
$ git stash pop [stash]
|
||||
|
||||
Eliminarne uno:
|
||||
|
||||
$ git stash drop stash@{0}
|
||||
|
||||
## Quando usarlo?
|
||||
|
||||
Ad esempio quando vogliamo passare ad un altro branch, accantonando le modifiche nella working directory.
|
||||
|
||||
---
|
||||
|
||||
## Storico dei cambiamenti: reflog
|
||||
|
||||
La history mostra solo i commit inclusi in un branch.
|
||||
|
||||
Per vedere tutto ciò che è successo:
|
||||
|
||||
$ git reflog [--relative-date]
|
||||
|
||||
<br />
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
* a volte è utile capire come ci siamo mossi tra i branch
|
||||
* fondamentale per recuperare i **broken commits** (non referenziati da alcun branch)
|
||||
|
||||
---
|
||||
|
||||
## Branches: cosa sono e perché usarli?
|
||||
|
||||
Sono puntatori mobili, spostati ad ogni nuovo commit.
|
||||
|
@ -361,9 +329,9 @@ Creare e spostarsi in un singolo comando:
|
|||
|
||||
<br />
|
||||
|
||||
# Bonus track
|
||||
### Bonus track
|
||||
|
||||
* nello spostarsi, Git cerca di mantenere i cambiamenti presenti nella working directory
|
||||
* nello spostarsi, Git cerca di mantenere i cambiamenti presenti nella working directory e nella staging area
|
||||
|
||||
-----
|
||||
|
||||
|
@ -373,34 +341,10 @@ Creare e spostarsi in un singolo comando:
|
|||
|
||||
* fate caso all'asterisco: è il branch corrente
|
||||
|
||||
* dare nomi significativi; prefissi: bugfix/, fix/, improvement/, feature/, task/
|
||||
|
||||
* aggiungere issue di riferimento
|
||||
* dare nomi significativi; usate prefissi (bugfix/, fix/, improvement/, feature/, task/) e issue di riferimento
|
||||
|
||||
* **refs**: nome collettivo per riferirsi ad HEAD, branches, tags
|
||||
|
||||
* **detached HEAD**: ci siamo spostati su un commit che non è l'head di un branch
|
||||
|
||||
---
|
||||
|
||||
## Spostarsi tra i commit
|
||||
|
||||
Salire di 3 livelli, seguendo sempre il primo parent commit (in caso di merge):
|
||||
|
||||
$ git checkout HEAD~3
|
||||
|
||||
Salire di un livello, seguendo il secondo parent commit (in caso di merge):
|
||||
|
||||
$ git checkout HEAD^2
|
||||
|
||||
<br />
|
||||
|
||||
### Bonus track
|
||||
|
||||
* cosa è HEAD: reference al branch (o commit) corrente
|
||||
* questi operatori sono concatenabili: HEAD~~^2
|
||||
* double/tripe dot ranges: git log master..branch; git log --left-right master...branch: https://stackoverflow.com/questions/7251477/what-are-the-differences-between-double-dot-and-triple-dot-in-git-dif
|
||||
|
||||
---
|
||||
|
||||
## Rimettere insieme i pezzi: merge
|
||||
|
@ -411,14 +355,19 @@ Partendo da master:
|
|||
$ # editiamo nuovofile.txt
|
||||
$ git add nuovofile.txt
|
||||
$ git commit
|
||||
|
||||
<img style="width:300px" src="images/branch-commit.png" data-action="zoom">
|
||||
|
||||
$ git checkout master
|
||||
$ git merge fix/bug-123
|
||||
|
||||
<br />
|
||||
<img style="width:300px" src="images/branch-ff.png" data-action="zoom">
|
||||
|
||||
### Cosa è successo?
|
||||
---
|
||||
|
||||
fast-forward! master era più indietro rispetto a fix/bug-123, e quindi abbiamo semplicemente spostato il puntatore master.
|
||||
## Merge: cosa è successo?
|
||||
|
||||
**fast-forward**! master era più indietro rispetto a fix/bug-123, e quindi abbiamo semplicemente spostato il puntatore master.
|
||||
|
||||
Non è stato neppure creato un nuovo commit.
|
||||
|
||||
|
@ -440,6 +389,12 @@ Partendo da master:
|
|||
$ git add file.txt
|
||||
$ git commit
|
||||
|
||||
<img style="width:300px" src="images/branch-conflict.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Risoluzione dei conflitti
|
||||
|
||||
Mergiamo:
|
||||
|
||||
$ git merge fix/bug-123
|
||||
|
@ -447,11 +402,13 @@ Mergiamo:
|
|||
$ git add file.txt
|
||||
$ git commit
|
||||
|
||||
<img style="width:300px" src="images/branch-conflict-solved.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Conflict files
|
||||
|
||||
Cercare sempre tutti i markers <<<<<<<, =======, >>>>>>>
|
||||
Cercare sempre tutti i markers **<<<<<<<**, **=======**, **>>>>>>>**
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -461,80 +418,6 @@ Cercare sempre tutti i markers <<<<<<<, =======, >>>>>>>
|
|||
|
||||
---
|
||||
|
||||
## Rimettere insieme i pezzi: cherry-pick
|
||||
|
||||
$ git cherry-pick <commit>
|
||||
$ # in caso di conflitti:
|
||||
$ git cherry-pick --continue
|
||||
|
||||
<br />
|
||||
|
||||
### Cosa è successo?
|
||||
|
||||
Si sono prese le modifiche introdotte dai commit elencati, e sono state riapplicate sul branch corrente.
|
||||
Sono stati creati dei nuovi commit.
|
||||
|
||||
<br />
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
Ad esempio per backportare un fix su diversi release branch, o se vi siete accorti che un certo commit era da fare su un altro branch.
|
||||
|
||||
---
|
||||
|
||||
## Rimettere insieme i pezzi: rebase
|
||||
|
||||
Poniamoci nella stessa situazione divergente dell'esempio in cui abbiamo usato merge, e poi:
|
||||
|
||||
$ git checkout fix/bug-123
|
||||
$ git rebase master
|
||||
$ # risolviamo eventuali conflitti
|
||||
$ git rebase --continue
|
||||
|
||||
<br />
|
||||
|
||||
### Cosa è successo?
|
||||
|
||||
Abbiamo preso tutti i commit di fix/bug-123 e li abbiamo ri-applicati su master, che nel mentre era andato avanti.
|
||||
|
||||
Tutti i commit specifici di fix/bug-123 sono cambiati.
|
||||
|
||||
-----
|
||||
|
||||
## Rebase
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
Quando dovete spostare più commit e/o per porvi nella condizione di fare un merge pulito, mantenendo una history lineare.
|
||||
|
||||
<br />
|
||||
|
||||
### Quando NON usarlo?
|
||||
|
||||
MAI MAI MAI rebasare dei commit che sono stati condivisi su altri repositori.
|
||||
|
||||
---
|
||||
|
||||
## Modificare la history
|
||||
|
||||
Creiamo un nuovo branch e committiamo 2 o 3 modifiche. Poi:
|
||||
|
||||
$ git rebase -i master
|
||||
|
||||
<br />
|
||||
|
||||
### Cosa è successo?
|
||||
|
||||
Abbiamo accorpato, scartato o invertito l'ordine dei commit.
|
||||
|
||||
<br />
|
||||
|
||||
### Bonus track
|
||||
|
||||
* l'opzione nucleare: **filter-branch** per creare script che riscrivono la history.
|
||||
|
||||
---
|
||||
|
||||
## Lavorare con repository remoti
|
||||
|
||||
$ git remote add origin https://github.com/user/repo.git
|
||||
|
@ -545,9 +428,9 @@ Abbiamo accorpato, scartato o invertito l'ordine dei commit.
|
|||
## Bonus track
|
||||
|
||||
* **origin** è solamente un default
|
||||
* associazione tra branch remoti e locali
|
||||
* l'associazione tra branch remoti e locali viene effettuata in automatico, in base al nome del branch
|
||||
|
||||
---
|
||||
-----
|
||||
|
||||
## Fetch & pull
|
||||
|
||||
|
@ -591,9 +474,334 @@ Aggiungiamo i cambiamenti locali ad un branch remoto:
|
|||
|
||||
## Parlando della history remota...
|
||||
|
||||
Cosa da non fare **MAI** (salvo non ne siate davvero convinti): pushare modifiche alla history.
|
||||
Cosa da non fare **MAI** (salvo non ne siate davvero convinti): modificare una history che sia già stata pushata.
|
||||
|
||||
Questo perché se qualcuno sta lavorando sullo stesso branch remoto, romperete tutto.
|
||||
Questo perché se qualcuno sta lavorando sullo stesso branch remoto, le altre persone si troveranno con dei repository non consistenti.
|
||||
|
||||
---
|
||||
|
||||
## Workflow di sviluppo
|
||||
|
||||
Nello scegliere un workflow dovrete rispondere ad alcune domande, quali:
|
||||
|
||||
* chi parteciperà allo sviluppo? Vengono accettati contributi da esterni o solo da un gruppo ristretto?
|
||||
* qual è il mio modello di rilascio del software? Ho versioni multiple da manutenere? A partire da quanti/quali branch verranno rilasciate le nuove versioni del mio software?
|
||||
* chi si occuperà dell'integrazione? Gli sviluppatori stessi o una figura dedicata?
|
||||
|
||||
-----
|
||||
|
||||
## Worflows: le alternative
|
||||
|
||||
I principali sono:
|
||||
|
||||
* centralized
|
||||
* feature branch
|
||||
* gitflow
|
||||
* forking
|
||||
* qualcosa tenuto insieme con gli elastici
|
||||
|
||||
Valide risorse:
|
||||
|
||||
* https://www.atlassian.com/git/tutorials/comparing-workflows
|
||||
* https://guides.github.com/introduction/flow/
|
||||
|
||||
---
|
||||
|
||||
## Forking workflow
|
||||
|
||||
Vediamo il **forking workflow**. Non perché sia intrinsecamente il migliore, ma perché quello più diffuso nello sviluppo su piattaforme come Github. Presupposti:
|
||||
|
||||
* esiste un repository ufficiale (chiamiamolo **upstream**) di riferimento su cui solo gli autori principali possono scrivere
|
||||
* i contributi di terzi sono accettati
|
||||
* ruolo di **project maintainer**: la persona che si occuperà di mergiare nel repository principale
|
||||
* ruolo di **developer**: chi sta sviluppando un fix o una nuova feature
|
||||
* ciascun developer avrà un fork remoto del repository upstream ed una copia locale su cui lavorare
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: maintainer setup
|
||||
|
||||
Il project maintainer ha creato il repository upstream remoto e il proprio clone locale.
|
||||
|
||||
Maintainer:
|
||||
|
||||
* git clone
|
||||
|
||||
<img style="width:300px" src="images/worflow-maintainer-clone.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: developer setup
|
||||
|
||||
Il developer ora:
|
||||
|
||||
* crea un **fork** remoto del repository upstream
|
||||
|
||||
<img style="width:300px" src="images/worflow-developer-fork.png" data-action="zoom">
|
||||
|
||||
## Bonus track
|
||||
|
||||
* un fork altro non è che un clone (--mirror) di un repository, sempre ospitato sul sito remoto
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: developer setup
|
||||
|
||||
* fa un **clone** locale del proprio repository remoto
|
||||
|
||||
<img style="width:300px" src="images/worflow-developer-clone.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: iniziamo lo sviluppo
|
||||
|
||||
Developer deve sviluppare un fix che andrà applicato sul branch master del repository upstream.
|
||||
|
||||
Nel clone locale del *proprio* fork, farà:
|
||||
|
||||
$ git checkout master
|
||||
$ git pull upstream
|
||||
|
||||
<img style="width:300px" src="images/worflow-developer-branch.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: nuovo branch
|
||||
|
||||
$ git checkout -b fix/bug-123
|
||||
|
||||
<img style="width:300px" src="images/worflow-developer-branch.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: lavoriamo
|
||||
|
||||
$ # introdurre il fix
|
||||
$ git commit
|
||||
$ git push --set-upstream origin fix/bug-123
|
||||
|
||||
<img style="width:300px" src="images/worflow-developer-push.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: pull request
|
||||
|
||||
Ora va sulla pagina web del proprio fork e crea una **pull request**.
|
||||
|
||||
<img style="width:300px" src="images/worflow-developer-pull-request.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: pull request
|
||||
|
||||
Pull request **NON** è un concetto base di Git (non esattamente, almeno). È qualcosa che vi è stato costruito sopra per facilitare la collaborazione tra sviluppatori.
|
||||
|
||||
La pull request creata in precedenza dice: "propongo di applicare i commit del branch *developer-fork:fix/bug-123* a *repository-upstream:master*"
|
||||
Ora developer, project maintainer e altri possono discuterne.
|
||||
|
||||
Se dovesse essere necessario, developer può aggiungere altri commit semplicemente con un nuovo push.
|
||||
|
||||
-----
|
||||
|
||||
## Forking workflow: merging
|
||||
|
||||
Una volta soddisfatti, project maintainer potrà effettuare il merge del codice su *repository-upstream:master*.
|
||||
|
||||
Se il merge non presenta conflitti, lo si può fare direttamente dalla GUI web sul repository upstream. Altrimenti il project maintainer dovrà fare il fetch di developer-fork:fix/bug-123 sul proprio clone locale, effettuare il merge su master per poi farne il push sul repository upstream.
|
||||
|
||||
<img style="width:300px" src="images/worflow-maintainer-local-fix.png" data-action="zoom">
|
||||
|
||||
---
|
||||
|
||||
## Parte 2
|
||||
|
||||
In cui forniremo una serie di strumenti avanzati.
|
||||
|
||||
---
|
||||
|
||||
## Referenziare i commit
|
||||
|
||||
Salire di 3 livelli, seguendo sempre il primo parent commit (in caso di merge):
|
||||
|
||||
$ git log -1 HEAD~3
|
||||
|
||||
Salire di un livello, seguendo il secondo parent commit (in caso di merge):
|
||||
|
||||
$ git log -1 HEAD^2
|
||||
|
||||
### Bonus track
|
||||
|
||||
* cosa è HEAD: reference al branch (o commit) corrente
|
||||
* **detached HEAD**: ci siamo spostati su un commit che non è l'head di un branch
|
||||
* questi operatori sono concatenabili: HEAD~~^2
|
||||
|
||||
-----
|
||||
|
||||
## Referenziare i commit: range
|
||||
|
||||
double dot range:
|
||||
|
||||
$ git log master..branch
|
||||
|
||||
triple dot range:
|
||||
|
||||
$ git log --left-right master...branch
|
||||
|
||||
-----
|
||||
|
||||
## Referenziare i commit: range
|
||||
|
||||
<img style="width:300px" src="images/range-log.png" data-action="zoom">
|
||||
<img style="width:300px" src="images/range-diff.png" data-action="zoom">
|
||||
|
||||
|
||||
Vedere anche: https://stackoverflow.com/questions/7251477/what-are-the-differences-between-double-dot-and-triple-dot-in-git-dif
|
||||
|
||||
---
|
||||
|
||||
## Rimettere insieme i pezzi: cherry-pick
|
||||
|
||||
$ git cherry-pick <commit>
|
||||
$ # in caso di conflitti:
|
||||
$ git cherry-pick --continue
|
||||
|
||||
<img style="width:300px" src="images/cherry-pick.png" data-action="zoom">
|
||||
|
||||
### Cosa è successo?
|
||||
|
||||
Si sono prese le modifiche introdotte dai commit elencati, e sono state riapplicate sul branch corrente.
|
||||
Sono stati creati dei nuovi commit.
|
||||
|
||||
<br />
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
Ad esempio per backportare un fix su diversi release branch, o se vi siete accorti che un certo commit era da fare su un altro branch.
|
||||
|
||||
---
|
||||
|
||||
## Rimettere insieme i pezzi: rebase
|
||||
|
||||
Poniamoci nella stessa situazione divergente dell'esempio in cui abbiamo usato merge, e poi:
|
||||
|
||||
$ git checkout fix/bug-123
|
||||
$ git rebase master
|
||||
$ # risolviamo eventuali conflitti
|
||||
$ git rebase --continue
|
||||
|
||||
<img style="width:300px" src="images/rebase.png" data-action="zoom">
|
||||
|
||||
<br />
|
||||
|
||||
### Cosa è successo?
|
||||
|
||||
Abbiamo preso tutti i commit di fix/bug-123 e li abbiamo ri-applicati su master, che nel mentre era andato avanti.
|
||||
|
||||
Tutti i commit specifici di fix/bug-123 sono cambiati.
|
||||
|
||||
-----
|
||||
|
||||
## Rebase
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
Quando dovete spostare più commit e/o per porvi nella condizione di fare un merge pulito. Questo può essere fatto dal developer prima di aprire una pull request per semplificare il lavoro al maintainer e/o dal maintainer stesso prima del merge, per ottenere una history lineare.
|
||||
|
||||
<br />
|
||||
|
||||
### Quando NON usarlo?
|
||||
|
||||
Un rebase modifica i commit originali: questo va evitato se quei commit sono già stati pushati ed altri sviluppatori li stanno usando come base per il proprio lavoro.
|
||||
|
||||
---
|
||||
|
||||
## Modificare la history: rebase interactive
|
||||
|
||||
Creiamo un nuovo branch e committiamo 2 o 3 modifiche. Poi:
|
||||
|
||||
$ git rebase -i master
|
||||
|
||||
<img style="width:300px" src="images/rebase-interactive.png" data-action="zoom">
|
||||
|
||||
-----
|
||||
|
||||
### Rebase: interactive cosa è successo?
|
||||
|
||||
Abbiamo accorpato, scartato o invertito l'ordine dei commit.
|
||||
|
||||
<br />
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
Quando abbiamo finito di lavorare su un branch, e vogliamo semplificare la history.
|
||||
|
||||
<br />
|
||||
|
||||
### Bonus track
|
||||
|
||||
* l'opzione nucleare: **filter-branch** per creare script che riscrivono la history.
|
||||
|
||||
---
|
||||
|
||||
## Lavoro incompleto: committare a pezzi
|
||||
|
||||
* git add --patch
|
||||
|
||||
<br />
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
Ad esempio quando non si vuole includere in un commit una riga di debug, che però si vuole mantenere nella working directory.
|
||||
|
||||
---
|
||||
|
||||
## Mettere il lavoro da parte: stash
|
||||
|
||||
Capita di dover mettere da parte il lavoro nella directory corrente senza voler committare:
|
||||
|
||||
$ git stash
|
||||
|
||||
Vedere la lista:
|
||||
|
||||
$ git stash list
|
||||
|
||||
Riapplicare una modifica messa in stash:
|
||||
|
||||
$ git stash pop [stash]
|
||||
|
||||
Eliminarne uno:
|
||||
|
||||
$ git stash drop stash@{0}
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
Ad esempio quando vogliamo passare ad un altro branch, accantonando le modifiche nella working directory.
|
||||
|
||||
---
|
||||
|
||||
## Creare e applicare patch
|
||||
|
||||
è possibile creare e riapplicare una patch usando i comandi:
|
||||
|
||||
$ git format-patch [refs]
|
||||
$ git apply patch-file.diff
|
||||
|
||||
---
|
||||
|
||||
## Storico dei cambiamenti: reflog
|
||||
|
||||
La history mostra solo i commit inclusi in un branch.
|
||||
|
||||
Per vedere tutto ciò che è successo:
|
||||
|
||||
$ git reflog [--relative-date]
|
||||
|
||||
<br />
|
||||
|
||||
### Quando usarlo?
|
||||
|
||||
* a volte è utile capire come ci siamo mossi tra i branch
|
||||
* fondamentale per recuperare i **broken commits** (non referenziati da alcun branch)
|
||||
|
||||
---
|
||||
|
||||
|
@ -611,7 +819,6 @@ Questo perché se qualcuno sta lavorando sullo stesso branch remoto, romperete t
|
|||
* git submodule
|
||||
* git bisect
|
||||
* git gui; gitk
|
||||
* workflows!
|
||||
|
||||
---
|
||||
|
||||
|
@ -619,9 +826,9 @@ Questo perché se qualcuno sta lavorando sullo stesso branch remoto, romperete t
|
|||
|
||||
### Per imparare
|
||||
|
||||
* Pro Git: https://git-scm.com/book/en/v2
|
||||
* Pro Git: https://git-scm.com/book/en/
|
||||
* Reference: https://git-scm.com/docs
|
||||
* Learn Git Brancing: http://learngitbranching.js.org/
|
||||
* Learn Git Branching: http://learngitbranching.js.org/
|
||||
* Git ready: http://gitready.com/
|
||||
* Git Cookbook: https://git.seveas.net/
|
||||
* tutorial di Atlassian: https://www.atlassian.com/git/tutorials
|
||||
|
@ -633,3 +840,14 @@ Questo perché se qualcuno sta lavorando sullo stesso branch remoto, romperete t
|
|||
* bash prompt: https://github.com/magicmonty/bash-git-prompt
|
||||
* Meld: http://meldmerge.org/
|
||||
|
||||
---
|
||||
|
||||
## The end
|
||||
|
||||
<br />
|
||||
|
||||
## ?
|
||||
|
||||
<br />
|
||||
<br />
|
||||
## Davide Alberani <da@erlug.linux.it>
|
||||
|
|
BIN
images/branch-commit.odg
Normal file
BIN
images/branch-commit.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
images/branch-conflict-solved.odg
Normal file
BIN
images/branch-conflict-solved.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
images/branch-conflict.odg
Normal file
BIN
images/branch-conflict.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
images/branch-create-move.odg
Normal file
BIN
images/branch-create-move.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/branch-ff.odg
Normal file
BIN
images/branch-ff.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
images/branch-prototype.odg
Normal file
BIN
images/cherry-pick.odg
Normal file
BIN
images/cherry-pick.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
images/file-states.odg
Normal file
BIN
images/file-states.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
images/range-diff.odg
Normal file
BIN
images/range-diff.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
images/range-log.odg
Normal file
BIN
images/range-log.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
images/rebase-interactive.odg
Normal file
BIN
images/rebase-interactive.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
images/rebase.odg
Normal file
BIN
images/rebase.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
images/worflow-developer-branch.odg
Normal file
BIN
images/worflow-developer-branch.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
images/worflow-developer-clone.odg
Normal file
BIN
images/worflow-developer-clone.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
images/worflow-developer-fork.odg
Normal file
BIN
images/worflow-developer-fork.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
images/worflow-developer-pull-request.odg
Normal file
BIN
images/worflow-developer-pull-request.png
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
images/worflow-developer-pull-upstream.odg
Normal file
BIN
images/worflow-developer-pull-upstream.png
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
images/worflow-developer-push.odg
Normal file
BIN
images/worflow-developer-push.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
images/worflow-developer-remote-add-upstream.odg
Normal file
BIN
images/worflow-developer-remote-add-upstream.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
images/worflow-maintainer-clone.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
images/worflow-maintainer-local-fix.odg
Normal file
BIN
images/worflow-maintainer-local-fix.png
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
images/worflow-prototype.odg
Normal file
19
index.html
|
@ -1,8 +1,21 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/reveal.css">
|
||||
<link rel="stylesheet" href="css/zoom.css">
|
||||
<link rel="stylesheet" href="css/theme/white.css">
|
||||
<title>Git crash course</title>
|
||||
|
||||
<style>
|
||||
|
||||
.slides {
|
||||
margin-top: 5px !important;
|
||||
}
|
||||
|
||||
.two-cols ul, .two-cols h3 {
|
||||
float: left;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="reveal">
|
||||
|
@ -11,7 +24,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<script src="js/head.min.js"></script>
|
||||
<script src="js/reveal.js"></script><script>
|
||||
<script src="js/reveal.js"></script>
|
||||
<script src="js/jquery-3.2.1.min.js"></script>
|
||||
<script src="js/transition.js"></script>
|
||||
<script src="js/zoom.min.js"></script>
|
||||
<script>
|
||||
Reveal.initialize({
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
|
0
libs/head.min.js → js/head.min.js
vendored
4
js/jquery-3.2.1.min.js
vendored
Normal file
59
js/transition.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* ========================================================================
|
||||
* Bootstrap: transition.js v3.3.7
|
||||
* http://getbootstrap.com/javascript/#transitions
|
||||
* ========================================================================
|
||||
* Copyright 2011-2016 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
|
||||
// ============================================================
|
||||
|
||||
function transitionEnd() {
|
||||
var el = document.createElement('bootstrap')
|
||||
|
||||
var transEndEventNames = {
|
||||
WebkitTransition : 'webkitTransitionEnd',
|
||||
MozTransition : 'transitionend',
|
||||
OTransition : 'oTransitionEnd otransitionend',
|
||||
transition : 'transitionend'
|
||||
}
|
||||
|
||||
for (var name in transEndEventNames) {
|
||||
if (el.style[name] !== undefined) {
|
||||
return { end: transEndEventNames[name] }
|
||||
}
|
||||
}
|
||||
|
||||
return false // explicit for ie8 ( ._.)
|
||||
}
|
||||
|
||||
// http://blog.alexmaccaw.com/css-transitions
|
||||
$.fn.emulateTransitionEnd = function (duration) {
|
||||
var called = false
|
||||
var $el = this
|
||||
$(this).one('bsTransitionEnd', function () { called = true })
|
||||
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
|
||||
setTimeout(callback, duration)
|
||||
return this
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$.support.transition = transitionEnd()
|
||||
|
||||
if (!$.support.transition) return
|
||||
|
||||
$.event.special.bsTransitionEnd = {
|
||||
bindType: $.support.transition.end,
|
||||
delegateType: $.support.transition.end,
|
||||
handle: function (e) {
|
||||
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}(jQuery);
|
8
js/zoom.min.js
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* zoom.js - It's the best way to zoom an image
|
||||
* @version v0.0.2
|
||||
* @link https://github.com/fat/zoom.js
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
+function(t){"use strict";function o(){this._activeZoom=this._initialScrollPosition=this._initialTouchPosition=this._touchMoveListener=null,this._$document=t(document),this._$window=t(window),this._$body=t(document.body),this._boundClick=t.proxy(this._clickHandler,this)}function i(o){this._fullHeight=this._fullWidth=this._overlay=this._targetImageWrap=null,this._targetImage=o,this._$body=t(document.body)}o.prototype.listen=function(){this._$body.on("click",'[data-action="zoom"]',t.proxy(this._zoom,this))},o.prototype._zoom=function(o){var e=o.target;if(e&&"IMG"==e.tagName&&!this._$body.hasClass("zoom-overlay-open"))return o.metaKey||o.ctrlKey?window.open(o.target.getAttribute("data-original")||o.target.src,"_blank"):void(e.width>=t(window).width()-i.OFFSET||(this._activeZoomClose(!0),this._activeZoom=new i(e),this._activeZoom.zoomImage(),this._$window.on("scroll.zoom",t.proxy(this._scrollHandler,this)),this._$document.on("keyup.zoom",t.proxy(this._keyHandler,this)),this._$document.on("touchstart.zoom",t.proxy(this._touchStart,this)),document.addEventListener?document.addEventListener("click",this._boundClick,!0):document.attachEvent("onclick",this._boundClick,!0),"bubbles"in o?o.bubbles&&o.stopPropagation():o.cancelBubble=!0))},o.prototype._activeZoomClose=function(t){this._activeZoom&&(t?this._activeZoom.dispose():this._activeZoom.close(),this._$window.off(".zoom"),this._$document.off(".zoom"),document.removeEventListener("click",this._boundClick,!0),this._activeZoom=null)},o.prototype._scrollHandler=function(o){null===this._initialScrollPosition&&(this._initialScrollPosition=t(window).scrollTop());var i=this._initialScrollPosition-t(window).scrollTop();Math.abs(i)>=40&&this._activeZoomClose()},o.prototype._keyHandler=function(t){27==t.keyCode&&this._activeZoomClose()},o.prototype._clickHandler=function(t){t.preventDefault?t.preventDefault():event.returnValue=!1,"bubbles"in t?t.bubbles&&t.stopPropagation():t.cancelBubble=!0,this._activeZoomClose()},o.prototype._touchStart=function(o){this._initialTouchPosition=o.touches[0].pageY,t(o.target).on("touchmove.zoom",t.proxy(this._touchMove,this))},o.prototype._touchMove=function(o){Math.abs(o.touches[0].pageY-this._initialTouchPosition)>10&&(this._activeZoomClose(),t(o.target).off("touchmove.zoom"))},i.OFFSET=80,i._MAX_WIDTH=2560,i._MAX_HEIGHT=4096,i.prototype.zoomImage=function(){var o=document.createElement("img");o.onload=t.proxy(function(){this._fullHeight=Number(o.height),this._fullWidth=Number(o.width),this._zoomOriginal()},this),o.src=this._targetImage.src},i.prototype._zoomOriginal=function(){this._targetImageWrap=document.createElement("div"),this._targetImageWrap.className="zoom-img-wrap",this._targetImage.parentNode.insertBefore(this._targetImageWrap,this._targetImage),this._targetImageWrap.appendChild(this._targetImage),t(this._targetImage).addClass("zoom-img").attr("data-action","zoom-out"),this._overlay=document.createElement("div"),this._overlay.className="zoom-overlay",this._targetImageWrap.parentNode.insertBefore(this._overlay, this._targetImageWrap),this._calculateZoom(),this._triggerAnimation()},i.prototype._calculateZoom=function(){this._targetImage.offsetWidth;var o=this._fullWidth,e=this._fullHeight,a=(t(window).scrollTop(),o/this._targetImage.width),s=t(window).height()-i.OFFSET,r=t(window).width()-i.OFFSET,n=o/e,h=r/s;this._imgScaleFactor=r>o&&s>e?a:h>n?s/e*a:r/o*a},i.prototype._triggerAnimation=function(){this._targetImage.offsetWidth;var o=t(this._targetImage).offset(),i=t(window).scrollTop(),e=i+t(window).height()/2,a=t(window).width()/2,s=o.top+this._targetImage.height/2,r=o.left+this._targetImage.width/2;this._translateY=e-s,this._translateX=a-r;var n="scale("+this._imgScaleFactor+")",h="translate("+this._translateX+"px, "+this._translateY+"px)";t.support.transition&&(h+=" translateZ(0)"),t(this._targetImage).css({"-webkit-transform":n,"-ms-transform":n,transform:n}),t(this._targetImageWrap).css({"-webkit-transform":h,"-ms-transform":h,transform:h}),this._$body.addClass("zoom-overlay-open")},i.prototype.close=function(){return this._$body.removeClass("zoom-overlay-open").addClass("zoom-overlay-transitioning"),t(this._targetImage).css({"-webkit-transform":"","-ms-transform":"",transform:""}),t(this._targetImageWrap).css({"-webkit-transform":"","-ms-transform":"",transform:""}),t.support.transition?void t(this._targetImage).one(t.support.transition.end,t.proxy(this.dispose,this)).emulateTransitionEnd(300):this.dispose()},i.prototype.dispose=function(){this._targetImageWrap&&this._targetImageWrap.parentNode&&(t(this._targetImage).removeClass("zoom-img").attr("data-action","zoom"),this._targetImageWrap.parentNode.replaceChild(this._targetImage,this._targetImageWrap),this._overlay.parentNode.removeChild(this._overlay),this._$body.removeClass("zoom-overlay-transitioning"))},t(function(){(new o).listen()})}(jQuery);
|
4
run.sh
|
@ -3,7 +3,9 @@
|
|||
git submodule init
|
||||
git submodule update 2> /dev/null
|
||||
mkdir -p reveal.js/js/
|
||||
cp libs/head.min.js reveal.js/js/
|
||||
cp js/* reveal.js/js/
|
||||
cp css/* reveal.js/css/
|
||||
cp images/* reveal.js/images/
|
||||
rm -f reveal.js/index.html
|
||||
ln index.html git-crash-course.md reveal.js/ 2> /dev/null
|
||||
cd reveal.js
|
||||
|
|