Scarica in formato pdf o txt
Scarica in formato pdf o txt
Sei sulla pagina 1di 22

ISTRUZIONI CONFIGURAZIONE GIT PER GOOGLE

—-

Controllo di versione centralizzato e distribuito

Concetti chiave

Repository remoto - remote repo


Aggiungere un remote vuoto ad un progetto nuovo
Clonare un repository remoto
Interagire con il remote: download e upload delle modifiche
Scaricare dal remote: fetch VS pull
Pubblicare il proprio lavoro: push

Branching
Integrare le modifiche

⟲ undo: annullare le azioni su GIT


Rimuovere dall’index un file aggiunto in precedenza
Aggiungere modifiche ad un commit già registrato sul repository locale
Riportare il codice allo stato di un precedente commit

Risoluzione dei conflitti


File eliminato in un branch e modificato nell’altro
Stessa linea modificata su entrambi i branch

Risoluzione conflitti con VSCODE


difftool e mergetool
Configurare VSCODE come difftool e mergetool

Plugin git per VSCODE


Git History ( donjayamanne.githistory )
GitLens — Git supercharged ( amodio.gitlens )

Operazioni da GUI ( VSCODE )


git add [file]
git add .
git checkout [file]
git reset --hard
git reset [--hard] [COMMIT_ID]

Best practices

Comandi utili da CLI


git log --pretty=format:"%s"
git log --oneline --graph --all

Controllo di versione centralizzato e distribuito

GIT è un sistema di controllo di versione distribuito, a differenza di subversion (SVN) che è


centralizzato.
Con SVN il repository del codice risiede su un server e gli sviluppatori devono avere
permessi specifici (commit rights) per poter aggiungere codice al repository. Tutto vive nello
stesso posto.

Controllo di versione centralizzato

In un sistema distribuito, ciascuno sviluppatore ottiene un proprio repository quando clona il


progetto.
Questo significa che lo sviluppatore può lavorare e aggiungere codice al repo anche offline,
dal momento che il repository risiede sul suo computer.
Comporta altrettanto una certa disciplina per mantenere sincronizzato il lavoro con il team,
dal momento che ciascun repository è separato dagli altri.
Controllo di versione distribuito
Concetti chiave
Le tre componenti fondamentali di ogni progetto GIT :
● Working tree
Chiamato in alternativa working directory, consiste dei file su cui si sta correntemente
lavorando. Agli effetti pratici, è la porzione di filesystem corrispondente alle directory
di progetto.
● Index
Anche definito “staging area”, è lo spazio virtuale all’interno del quale vengono
preparati i commit. L’index tiene traccia delle differenze tra i file nel working tree e
quelli presenti nel repository. Dopo un cambiamento nel working tree, l’index segna il
file come modificato prima che ne venga fatto il commit.
● Repository
E’ il “contenitore” che conserva i cambiamenti ai file del progetto. Contiene tutti i
commit - ciascuno dei quali è uno snapshot di tutti i file in un dato istante - che sono
stati registrati.

I tre passaggi di base del workflow GIT:


● Modificare i file nel working tree
● Aggiungere all’index (in inglese ‘add files’ oppure ‘stage files’) i file che devono
essere inclusi nel prossimo commit
● Eseguire il commit delle differenze. Questa operazione prende le modifiche presenti
nell’index e le registra come snapshot nel repository.

I tre stati in cui si può trovare un file incluso (tracked) in un progetto GIT:
● Modified --->ANCORA SUL WORKING TREE, IL FILE RISULTA MODIFICATO
RISPETTO AL COMMIT CORRENTE (CONTRASSEGNATO COME <HEAD>)
● Staged (Added) ---> IL FILE MODIFICATO E’ STATO INCLUSO DALL’UTENTE NEL
PROSSIMO COMMIT
● Committed ---> IL FILE E’ STATO AGGIUNTO AL REPOSITORY

Un file può essere altresì visto da GIT


come ‘untracked’ quando risiede nella
cartella ma è assente sia dall’index che
dal repo. In questo stato il file non viene
monitorato dal sistema di controllo di
versione.

git add nomefile cambia lo stato del


file
- da untracked a staged
- da modified a staged

per ‘nascondere’ un file a GIT si usa il file


.gitignore (nella root VCS), file di testo con una riga per pattern (glob ammessi) da ignorare.
Repository remoto - remote repo

GIT adotta il concetto di remote repository, per permettere la sincronizzazione tra repository
differenti.
Formalmente, per GIT è ‘remote repo’ ogni repository noto a quello su cui si stia lavorando.
In effetti non esiste alcuno schema gerarchico tra i vari repository, e nulla vieta di lavorare
appoggiandosi esclusivamente ai repository locali dei singoli sviluppatori.

Spesso, comunque, si usa predisporre un repository remoto come “single source of truth”.

In questo caso, tipicamente il repository remoto viene installato come ‘bare repo’, un tipo di
repository speciale che contiene solo la storia dei commit come log dei diff tra commit, ma
non contiene direttamente il codice sorgente.

Questo tipo di repository viene inizializzato eseguendo,


all’interno della directory che lo conterrà, il comando
git init -- bare

La sintassi per aggiungere un remote al repo corrente è la seguente:

git remote add [NOME_LOCALE_REPO] [URL_REPO]

GIT supporta, oltre al trasferimento locale (due repository sullo stesso computer), tre
protocolli di rete per la sincronizzazione, di conseguenza la URL di un repo non locale può
essere in formato http(s), ssh o git. I protocolli più utilizzati sono https ed ssh.

Tipicamente (vedi http://jr0cket.co.uk/2016/05/ssh-or-https-that-is-the-github-question.html) è


più comune utilizzare ssh quando si voglia l’accesso in scrittura al repo (la possibilità di fare
push).

ESEMPI:
SSH → git remote add origin git@github.com:nodejs/node.git
HTTPS → git remote add origin https://github.com/nodejs/node.git

Il nome di default che GIT assegna al remote di cui viene fatto un clone locale è origin
Per coerenza questo è il nome che si usa assegnare al repository autoritativo remoto.

E’ possibile aggiungere allo stesso progetto GIT un numero indeterminato di remote.


Associare un repository remoto al progetto corrente può significare:

Aggiungere un remote vuoto ad un progetto nuovo

L’ipotesi è quella in cui si voglia configurare un remote per una cartella di sorgenti già
esistente. In questo caso, dopo aver inizializzato sia il repository locale che quello remoto,
dalla root dei sorgenti in locale, bisognerà eseguire il comando

git remote add [NOME_LOCALE_REPO] [URL_REPO]

Salvo necessità specifiche è consigliabile utilizzare questo comando per aggiungere il


remote solo quando quest’ultimo sia vuoto.

Clonare un repository remoto


Quando si presenti la necessità di creare un repo locale a partire da un progetto esistente su
un repository GIT remoto, il comando da eseguire è:

git clone [URL_REPO] [NOME_DIR*] -- NOME_DIR E’ OPZIONALE; DI DEFAULT


ASSEGNA LO STESSO NOME DEL REPOSITORY (*senza .git se presente - .git
convenzionalmente indica un bare repo)

quindi se dalla directory /progetti_git eseguo


git clone https://github.com/nodejs/node.git
verrà creata una directory /progetti_git/node

Interagire con il remote: download e upload delle modifiche

Scaricare dal remote: fetch VS pull


git fetch scarica i cambiamenti dal repository remoto - non integra alcun dato nel lavoro
corrente, permettendo quindi di verificare i cambiamenti avvenuti nel repository remoto
prima di pensare all’eventuale integrazione col lavoro corrente.
Tendenzialmente si tratta di un’operazione a basso rischio.

Ad esempio, git fetch origin potrebbe portare a questa situazione:

A--B--C--D <-- master (HEAD) ← MASTER BRANCH LOCALE

E--F <-- origin/master ← COPIA LOCALE DEL MASTER BRANCH REMOTO - A


QUESTO PUNTO SEMPLICEMENTE UN BRANCH LOCALE DIFFERENTE - PER INTEGRARLO DEVO
ESEGUIRE git merge origin/master

A questo link un approfondimento sul funzionamento di git fetch


git pull si usa con un obbiettivo diverso: aggiornare il branch specificato nel comando - o,
se omesso, quello corrente - tentando l’integrazione locale delle modifiche presenti sul
branch remoto associato (tracked).
Questa operazione ha delle potenziali conseguenze: al tentativo da parte del programma di
integrare i cambiamenti remoti con quelli presenti in locale, ove questi insistano sugli stessi
file, possono insorgere dei conflitti (merge conflicts) che vanno risolti manualmente.
Come per molte altre operazioni GIT, è consigliato eseguire git pull solamente a partire
da una working directory pulita, quindi dopo aver effettuato il commit di tutte le modifiche.

Per salvare temporaneamente dei cambiamenti la cui sorte sia ancora incerta all’atto del pull
(Es: devo scaricare il master - ho delle modifiche in sospeso di cui non voglio fare il commit),
esiste il comando git stash che salva le modifiche in una sorta di ‘limbo’ da cui poi
possono essere recuperate per riapplicarle allo stato corrente.

Pubblicare il proprio lavoro: push


Per eseguire l’upload delle modifiche locali sul repository remoto, il comando è git push

La sintassi completa è

git push [NOME_LOCALE_REPO] [NOME_BRANCH]

esempio: git push origin master

se il branch esiste solo sul repo locale:

git push --set-upstream origin branch_da_sincronizzare


--set-upstream può essere sostituito con -u
Branching
Elemento di forza di git è il supporto allo sviluppo non lineare, gestito attraverso le funzioni di
branching.
Ciascuno sviluppatore può modificare il proprio codice con la certezza di non interferire con
il lavoro altrui, creando un branch locale specifico (topic branch) per le modifiche di sua
competenza. Solo a modifiche completate integrerà (merge) il topic branch con il master.

l’operazione consta di due comandi:


git branch [NOME_BRANCH] → CREA IL BRANCH
git checkout [NOME_BRANCH] → IMPOSTA IL BRANCH COME CORRENTE (HEAD)

può essere eseguita anche con un comando unico:


git checkout -b [NOME_BRANCH]

Integrare le modifiche
Il comando per integrare le modifiche presenti in due branch differenti è git merge
Il merging è il modo in cui git rimette insieme la storia del codice a seguito di un fork.
Il comando git merge permette di prendere le linee di sviluppo indipendenti create con git
branch e reintegrarle in un unico branch.

Il comando viene eseguito sul branch corrente (HEAD), la sintassi è questa:


git merge [NOME_BRANCH]

Quando il percorso che va dall’ultimo commit del branch corrente al branch target è lineare,
git può eseguire un tipo particolare di merge, cosiddetto fast-forward, in cui semplicemente
sposta il tag HEAD - che identifica il branch e il commit corrente - all’ultimo commit del
branch target.
⟲ undo: annullare le azioni su GIT
GIT offre strumenti estremamente versatili per i casi in cui si debba ritornare su una
decisione presa in precedenza:

Rimuovere dall’index un file aggiunto in precedenza

git rm [file(s)]

questo comando, senza ulteriori parametri, elimina il file sia dall’index che dal filesystem.
Può verificarsi il caso in cui si voglia escludere un file dal VCS senza eliminarlo dal
filesystem (tipicamente, viene eseguito git add . ma successivamente si realizza che un
dato file (o insieme di file) non va tenuto sotto VCS - es: librerie, file di metadati osx, file di
configurazione IDE … - ma non è stato aggiunto a .gitignore)
In questo caso, la soluzione prevede due passaggi:

- rimuovere il file dall’index MA NON dal filesystem con il comando:


git rm --cached [file(s)]
- aggiungere a .gitignore una riga relativa al/ai file da ignorare

Es: Ho creato un progetto git, apro la cartella dei sorgenti con VS Code e modifico
un’impostazione dell’editor salvandola a livello di progetto. VS Code genera quindi una
cartella .vscode che è specifica rispetto alla mia configurazione personale, e
tendenzialmente non vorrò condividere.

git rm --cached .vscode/* oppure git rm -r .vscode


aggiungo a .gitignore (su una nuova linea)
.vscode

Aggiungere modifiche ad un commit già registrato sul repository locale

Una situazione abbastanza comune si verifica quando uno sviluppatore esegue il commit
troppo presto, magari dimenticando di aggiungere alcuni file o con un messaggio
inadeguato. E’ possibile rieseguire lo stesso commit utilizzando l’opzione --amend

git commit --amend

Questo comando utilizza la staging area (index) per il commit. Se non sono state fatte
modifiche dall’ultimo commit, lo snapshot sarà identico, e sarà possibile cambiare il
messaggio. Se sono presenti modifiche, verranno integrate nell’ultimo commit registrato, che
verrà sovrascritto.
Riportare il codice allo stato di un precedente commit

E’ interessante notare che il comando utilizzato per conoscere lo stato del working tree e
della staging area (index) mostra un suggerimento su come annullare i cambiamenti
presenti. Il comando git status risponde così:

$ git add *
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

renamed: README.md -> README


modified: CONTRIBUTING.md

Se un file è incluso nell’index (staging area) il comando git reset lo riporta nel working
tree mantenendo le modifiche presenti nel codice.

$ git reset HEAD CONTRIBUTING.md


Unstaged changes after reset:
M CONTRIBUTING.md

Di nuovo l’output di git status suggerisce - (use "git checkout -- <file>..." to


discard changes in working directory) - il comando da usare per annullare le
modifiche e riportare il file allo stato dell’ultimo commit registrato:

$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README

Changes not staged for commit:


(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working
directory)
modified: CONTRIBUTING.md

Il comando è:
git checkout -- [file(s)]

Se l’intenzione è quella di annullare in toto l’ultimo commit o anche una porzione di storia, i
due passaggi possono essere ridotti ad uno richiamando git reset con il parametro --hard
e specificando il commit che si vuole ripristinare

git reset --hard [COMMIT]


Se l’intenzione è quella di annullare l’ultimo commit o anche una porzione di
storia,mantenendo le modifiche in working tree, è possibile eseguire git reset con il
parametro --keep specificando il commit che si vuole ripristinare

git reset --keep [COMMIT]

Risoluzione dei conflitti


Un merge conflict può verificarsi in due scenari:

● due branch hanno modificato la stessa linea di codice


● un branch ha eliminato un file che è stato modificato in un altro branch

Quando git non è in grado di determinare univocamente che operazione compiere su un file,
risponde con un errore:

Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

File eliminato in un branch e modificato nell’altro


si risolve aggiungendo o rimuovendo il file dall’index:

git add README.md


oppure
git rm README.md

Stessa linea modificata su entrambi i branch

Se apro il file su cui si è verificato il conflitto troverò che git lo ha modificato inserendo, per la
riga che non sa come risolvere, entrambe le possibilità, quella corrispondente a HEAD (il
branch corrente) e quella relativa al branch da integrare (il parametro del comando git
merge)

This is a README.md file.


This is in a repository called merge-conflicts.
<<<<<<< HEAD
This file is on the main branch.
=======
This file is on the dev branch.
>>>>>>> dev

In questo caso la risoluzione del conflitto richiede che venga corretto il file rimuovendo le
annotazioni del VCS e scegliendo una delle soluzioni (eventualmente anche riscrivendo la
parte per incorporare entrambe le modifiche).
A modifiche terminate e file salvato, bisognerà aggiungere il file all’INDEX, effettuare il
commit delle modifiche e rilanciare il merge

git add README.md


git commit -m "feat: Resolve merge conflict."
git merge dev
Risoluzione conflitti con VSCODE

difftool e mergetool
git prevede due comandi per aiutare nella risoluzione dei conflitti:

il comando git difftool [<options>] [<commit> [<commit>]] [--] [<path>…​ ]


link alla documentazione
può essere utilizzato per visualizzare le differenze tra commit; se non diversamente
configurato, chiama il comando git diff

il comando git mergetool [--tool=<tool>] [-y | --[no-]prompt] [<file>…​ ]


link alla documentazione
può essere utilizzato per richiamare un programma per la risoluzione visuale dei conflitti.
Git supporta diversi strumenti per eseguire questo tipo di operazione.

Configurare VSCODE come difftool e mergetool


Il file di configurazione di git, [USER_HOME]/.gitconfig (su Win di solito
c:\\windows\users\[NOME_UTENTE]\.gitconfig --- su linux e OSX
/home/[NOME_UTENTE]/.gitconfig) va modificato per aggiungere le righe seguenti:

# VSCode as git diff and git merge tool


[merge]
tool = vscode
[mergetool "vscode"]
cmd = code --wait $MERGED
[diff]
tool = vscode
[difftool "vscode"]
cmd = code --wait --diff $LOCAL $REMOTE
# VSCode Difftool

Scenario:
- due branch, master e will_conflict
- due file di partenza: asd.txt e file.txt
- su due commit paralleli
- master modifica asd.txt:L1 e file.txt
- will_conflict modifica asd.txt:L1 ed elimina file.txt

git merge will_conflict


CONFLICT (modify/delete): file.txt deleted in will_conflict and
modified in HEAD. Version HEAD of file.txt left in tree.
Auto-merging asd.txt
CONFLICT (content): Merge conflict in asd.txt
Automatic merge failed; fix conflicts and then commit the result.
Se eseguo il comando git mergetool si aprirà Visual Studio Code con questo layout:

in evidenza in giallo i comandi per applicare con un click le modifiche apportate da uno o
dall’altro branch; cliccando su una delle soluzioni il file viene aggiornato rimuovendo le
annotazioni VCS e la versione scartata, e può quindi essere salvato.

git mergetool
Merging:
asd.txt
file.txt

Normal merge conflict for 'asd.txt':


{local}: modified file
{remote}: modified file

[QUI SI APRE VSCODE - UNA VOLTA CHIUSO IL PROCESSO CONTINUA]

Deleted merge conflict for 'file.txt':


{local}: modified file
{remote}: deleted
Use (m)odified or (d)eleted file, or (a)bort? m

git add .
git commit -am 'merge conflict su asd(modifica x) e su file(keep y)'
git merge will_conflict
Already up to date.
Plugin git per VSCODE
Vs code contiene un pannello per la gestione del VCS git, che tiene traccia delle modifiche
al working tree e ne propone l’integrazione fornendo all’utente un input box per inserire il
messaggio:

i comandi di git sono accessibili dal menu a tendina che si apre cliccando sui tre pallini
Git History ( donjayamanne.githistory )
aggiunge a VSCODE una vista log su tutto il progetto e sul singolo file, accessibile
cliccando l’icona

nel pannello VCS, oppure dall’elenco dei comandi -> CTRL+MAIUSC+P (Win) ||
CMD+MAIUSC+P (OSX/linux)

GitLens — Git supercharged ( amodio.gitlens )


aggiunge moltissime funzionalità di gestione git a VSCODE. Tra le feature più rilevanti, la
gestione dei merge conflicts integrata (senza bisogno di modificare la configurazione
generale dell’editor - IMPOSTAZIONI PERSONALIZZATE PER IL DIFFTOOL E IL
MERGETOOL CONVIVONO SERENAMENTE CON QUESTO PLUGIN, EVENTUALMENTE
E’ POSSIBILE DEFINIRLE COMUNQUE E MANTENERE LE DUE OPZIONI)

dalla documentazione del plugin

Here are just some of the features that GitLens provides,

● an unobtrusive current line blame annotation at the end of the line with detailed blame
information accessible via hovers
● authorship code lens showing the most recent commit and # of authors to the top of files
and/or on code blocks
● a status bar blame annotation showing author and date for the current line
● many rich Side Bar views
○ a Repositories view to visualize, navigate, and explore Git repositories
○ a File History view to visualize, navigate, and explore the revision history of the
current file
○ a Line History view to visualize, navigate, and explore the revision history of the
selected lines of current file
○ a Search Commits view to search and explore commit histories by message, author,
files, id, etc
○ a Compare view to visualize comparisons between branches, tags, commits, and
more
● on-demand gutter blame annotations, including a heatmap, for the whole file
● on-demand gutter heatmap annotations to show how recently lines were changed, relative to
all the other changes in the file and to now (hot vs. cold)
● on-demand recent changes annotations to highlight lines changed by the most recent
commit
● many powerful commands for exploring commits and histories, comparing and navigating
revisions, stash access, repository status, etc
● user-defined modes for quickly toggling between sets of settings
● and so much more
Operazioni da GUI ( VSCODE )

git add [file]


dal pannello integrato git

git add .
dal pannello integrato git

git checkout [file]


dal pannello integrato git
git reset --hard
dal pannello integrato git

git reset [--hard] [COMMIT_ID]


dal pannello di log
git merge [BRANCH O COMMIT_ID]
dal pannello di log

Risoluzione conflitti:
se un merge eseguito da VSCODE genera conflitti, il programma apre direttamente la
finestra mergetool sui file in stato conflicted

risolti i conflitti e salvato i file ci si può portare sul pannello integrato git che sarà già
predisposto per concludere il merge
Best practices
da https://git-scm.com/book/it/v2/Per-Iniziare-Una-Breve-Storia-di-Git

Il kernel di Linux è un progetto software open source di grande portata. ... Nel 2002, il
progetto del kernel Linux iniziò ad utilizzare un sistema DVCS proprietario chiamato
BitKeeper. Nel 2005 … fu revocato l’uso gratuito di BitKeeper. Ciò indusse ... a sviluppare
uno strumento proprio …
Obbiettivi del nuovo sistema erano i seguenti:

● Velocità
● Design semplice
● Ottimo supporto allo sviluppo non-lineare (migliaia di rami paralleli)
● Completamente distribuito
● Capacità di gestire, in modo efficiente (velocità e dimensione dei dati), grandi progetti
come il kernel Linux

La grande flessibilità del meccanismo di branching di git ha dato spazio alla definizione di un
certo numero di varianti in relazione alle relative buone prassi.

Un modello affermato è quello opportunamente conosciuto come GitFlow: riproposto in


diverse varianti sul web, è imperniato sull’idea di mantenere sempre almeno due specifici
branch principali:

- MASTER
- DEVELOP

Il principio di base è che, quando uno sviluppatore deve lavorare su una nuova feature, crea
un topic branch a partire da develop, e a lavoro finito esegue il merge del topic branch (o
feature branch) su develop.
Solo quando la feature è testata e funzionante, develop viene integrato con master (che
traccia il codice di produzione).

---
note wip:
https://medium.com/@thomaspoignant/simple-git-flow-who-works-dac82430e484
https://guides.github.com/introduction/flow/
Comandi utili da CLI

stampa il log del branch corrente omettendo gli hash dei commit

git log --pretty=format:"%s"

stampa il log di tutti i branch mostrando solo il titolo del messaggio di commit ed esponendo
graficamente gli eventuali merge

git log --oneline --graph --all

push di un branch locale impostando il tracking delle modifiche (--set-upstream o -u)

git push --set-upstream origin cassa-previdenziale

LINK INTERESSANTI

Tutorial interattivo: https://learngitbranching.js.org/?locale=it_IT

Potrebbero piacerti anche