Finora abbiamo visto come usare Git in repository locali sul nostro computer. Abbiamo avuto modo di apprezzare i vari strumenti messi a disposizione da Git come la possibilità di visualizzare una versione precedente di un file oppure di organizzare il lavoro in diversi branch. I veri vantaggi si vedono però nel momento in cui si utilizza Git per lavorare in team e sfruttare a pieno le sue potenzialità grazie ai repository remoti. Esistono vari servizi online per l’hosting di repository, in alternativa è comunque sempre possibile configurare un proprio server. Iniziamo allora a vedere come sia semplice lavorare con repository remoti. Concettualmente non è nulla di nuovo rispetto a quanto abbiamo già visto.
Creare un repository remoto
Partiamo da un semplice esempio, creiamo un nuova cartella e inizializziamo un repository con il comando git init. All’interno della directory creata, inseriremo il file configurazione_pc.txt già usato in altre lezioni.
[remote_repo_1] (master) $ git init
[remote_repo_1] (master) $ touch configurazione_pc.txt
[remote_repo_1] (master) $ git add .
[remote_repo_1] (master) $ git commit -m 'first commmit'
[remote_repo_1] (master) $ echo 'AMD Ryzen 3 1200' > configurazione_pc.txt'
[remote_repo_1] (master) $ git commit -am 'aggiunge il processore AMD Ryzen 3 1200 al file configurazione_pc.txt'
# Abbiamo definito un nuovo alias per non dover digitare tutte le opzioni
# git help graph
# 'git graph' is aliased to `log --oneline --all --graph --decorate`
[remote_repo_1] (master) $ git graph
* d0dcf38 (HEAD -> master) aggiunge il processore AMD Ryzen 3 1200 al file configurazione_pc.txt
* 9221bff first commit
Fin qui non c’è nulla di nuovo rispetto a quanto abbiamo già visto nelle precedenti lezioni. L’unica novità è l’uso di quello che potrebbe sembrare un nuovo comando, ovvero git graph. In realtà si tratta di un alias che abbiamo precedentemente definito con il seguente comando:
$ git config --global alias.graph 'log --oneline --all --graph --decorate'
In questo modo evitiamo di dover digitare tutte le opzioni. È possibile definire degli alias a livello locale o globale. Per maggiori dettagli è possibile consultare la documentazione. (git help config)
A questo punto abbiamo il solito repository sul nostro computer. Se vogliamo creare un repository remoto a partire dal repository locale in maniera semplice e veloce, possiamo usare uno dei servizi di hosting di repository. Github è sicuramente la piattaforma più conosciuta. Vista l’enorme quantità di materiale e informazioni che si trovano online su Github e dato che le funzionalità sono simili, in questa guida vedremo come usare Bitbucket. Registriamo quindi un nuovo account, ed accediamo alla Dashboard in cui possiamo creare un nuovo repository sul server.
All’interno della Dashboard, selezioniamo il pulsante ‘+’ nell’angolo in alto a sinistra.
Procediamo selezionando ‘Repository’ dalla lista e procediamo alla pagina successiva in cui dovremo compilare un form con le infomazioni sul nuovo repository da creare.
In questo caso, inseriamo un nome per il repository (possiamo selezionare un qualsiasi nome anche diverso da quello della cartella che abbiamo sul nostro computer). Scegliamo di creare un repository privato e selezioniamo Git come sistema di controllo di versione. Trattandosi di un esempio, possiamo tralasciare gli altri campi.
Una volta creato il nuovo repository, Bitbucket ci suggerisce le istruzioni per iniziare a usare il nuovo repository. In particolare vengono fornite le istruzioni nel caso si cominci a lavorare a un nuovo progetto o si ha già un repository locale.
Bitbucket suggerisce di creare un file README contenente delle informazioni sul repository. Sia su Bitbucket che Github, il contenuto del file README viene solitamente mostrato nella pagina principale del repository. A seconda del progetto, può essere utile inserire nel file README degli esempi o una documentazione più o meno esaustiva.
$ touch README.md
$ cat README.md
<!-- contenuto file README.md -->
# Esempio repository remoto
Esempio che mostra come creare e usare un repository remoto su Bitbucket.
Nel nostro caso abbiamo creato il file README.md con una brevissima descrizione. Abbiamo usato il linguaggio Markdown (estensione.md) di cui non esiste ancora uno standard univocamente definito. In ogni caso potete trovare una rapida ma esauriente panoramica nella guida su Markdown di Github.
[remote_repo_1] (master) $ git add README.md
[remote_repo_1] (master) $ git commit -m 'aggiunge il file README.md'
[remote_repo_1] (master) $ git graph
* efca4c1 (HEAD -> master) aggiunge il file README.md
* d0dcf38 aggiunge il processore AMD Ryzen 3 1200 al file configurazione_pc.txt
* 9221bff first commit
Proseguiamo con le istruzioni fornite da Bitbucket ed eseguiamo il comando git remote add.
[remote_repo_1] (master) $ git remote add origin https://clauudio@bitbucket.org/clauudio/remote_repo_test.git
Abbiamo usato il comando git remote per aggiungere al file di configurazione .git/config i dettagli riguardo al repository remoto ‘collegato’ al nostro repository locale. In questo caso abbiamo indicato che faremo riferimento al repository remoto usando il nome origin e abbiamo specificato qual è l’indirizzo del repository sul server remoto. È pratica comune usare il nome origin per riferirsi al repository remoto, ma potremmo usare un qualsiasi altro nome. Dopo l’esecuzione del comando mostrato sopra, verrà aggiornato il file .git/config con le informazioni riguardanti il nuovo repository remoto.
[remote_repo_1] (master) $ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://clauudio@bitbucket.org/clauudio/remote_repo_test.git
fetch = +refs/heads/*:refs/remotes/origin/*
# visualizza le informazioni sui repository remoti configurati
[remote_repo_1] (master) $ git remote -v
origin https://clauudio@bitbucket.org/clauudio/remote_repo_test.git (fetch)
origin https://clauudio@bitbucket.org/clauudio/remote_repo_test.git (push)
Abbiamo anche usato il comando git remote con l’opzione -v per visualizzare l’indirizzo completo del repository usato da Git per le operazioni di push (invio dei file al repository remoto) e fetch (recupero dei file dal server remoto) di cui parleremo in maggior dettaglio nel corso della lezione.
Eseguiamo quindi il comando git push per inviare i commit del branch master al repository remoto in cui verrà creato un branch con lo stesso nome.
[remote_repo_1] (master) $ git push -u origin master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (9/9), 864 bytes | 0 bytes/s, done.
Total 9 (delta 0), reused 0 (delta 0)
To https://bitbucket.org/clauudio/remote_repo_test.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
[remote_repo_1] (master) $ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
Grazie all’opzione -u (o –set-upstream) Git inserisce nel file .git/config la configurazione necessaria per far in modo che il branch locale master tenga traccia di nuovi commit presenti in origin/master (ovvero dei cambiamenti apportati alla versione remota del branch master). Inoltre da questo momento in poi, quando siamo sul branch master, possiamo eseguire semplicemente il comando git push o git fetch senza altre opzioni e Git saprà a quale branch remoto facciamo riferimento. In caso contrario dovremmo ogni volta indicare il nome del repository e del branch remoto. Sempre grazie all’opzione -u, lanciando il comando git status dal branch master, verrà aggiunta all’output una nuova informazione, ovvero "Your branch is up to date with ‘origin/master’", con cui ci viene segnalato che il branch locale è sincronizzato con il branch ‘origin/master’.
[remote_repo_1] (master) $ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://clauudio@bitbucket.org/clauudio/remote_repo_test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
A proposito di origin/master, probabilmente vi starete chiedendo cos’è. Si tratta di quello che possiamo definire un branch remoto. Cerchiamo di chiarire meglio cosa intendiamo. Nel momento in cui abbiamo eseguito il comando git push, abbiamo inviato i commit al repository remoto e nel repository locale viene creato un nuovo branch ‘origin/master’ come possiamo vedere eseguendo i comandi riportati sotto. In particolare, il comando git branch con l’opzione -a mostra tutti i branch del repository sia locali che remoti. Questi ultimi sono dei puntatori come quelli locali con l’unica differenza che non possiamo effettuare il comando git checkout sui branch remoti. È infatti Git che si occupa di muoverli correttamente e aggiornare le informazioni sui commit del repository remoto. Il branch ‘origin/master’ è quindi una copia, presente nel nostro repository locale, del branch master del repository remoto. Ovviamente tocca a noi aggiornare il branch ‘origin/master’ in modo da avere gli ultimi commit eventualmente aggiunti da altri collaboratori al branch master del repository remoto. Vedremo a breve come fare grazie al comando git fetch.
[remote_repo_1] (master) $ git branch -a
* master
remotes/origin/master
[remote_repo_1] (master) $ ls .git/refs
heads remotes tags
[remote_repo_1] (master) $ cat .git/refs/remotes/origin/master
efca4c11a77386a4905d353dcbc26e3b1a7fa91b
Nel momento in cui effettuiamo il comando git push, vengono trasferiti i dati al server remoto e viene aggiunto un nuovo branch origin/master al repository locale che punta allo stesso commit a cui punta il branch master nel repository remoto.
Se vengono aggiunti nuovi commit al repository remoto da altri collaboratori, il branch master del repository remoto viene aggiornato, ma il branch origin/master non viene modificato fin quando non viene effettuato il comando git fetch che recupera le informazioni aggiornate dal repository remoto. Dopo il comando git fetch vengono recuperati dal repository remoto eventuali nuovi commit e viene in caso modificato il valore di origin/master, ma non del branch master. Se vogliamo incorporare le modifiche di origin/master nel branch master, dobbiamo eseguire git merge origin/master dal branch master.
Le due operazioni git fetch e git merge vengono spesso eseguite insieme. Per questo motivo Git mette a disposizione il comando equivalente git pull.
Continuiamo il nostro esempio e creiamo un nuovo branch nel repository locale. Eseguiamo un nuovo commit e proviamo a lanciare il comando git push.
[remote_repo_1] (master) $ git checkout -b negozio_1
Switched to a new branch 'negozio_1'
[remote_repo_1] (negozio_1) $ echo 'AMD Ryzen 3 1200 - 119€' > preventivo_negozio_1.txt
[remote_repo_1] (negozio_1) $ git add .
[remote_repo_1] (negozio_1) $ git commit -m 'aggiunge il file preventivo_negozio_1 con il costo del processore AMD Ryzen 3 1200'
[negozio_1 2c58e79] aggiunge il file preventivo_negozio_1 con il costo del processore AMD Ryzen 3 1200
1 file changed, 1 insertion(+)
create mode 100644 preventivo_negozio_1.txt
[remote_repo_1] (negozio_1) $ git push
fatal: The current branch negozio_1 has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin negozio_1
Come potevamo immaginare, Git non riesce a compiere l’operazione richiesta. A questo punto potremmo lanciare il comando suggerito da Git e far in modo che il branch locale negozio_1 sia ‘collegato’ all’omonimo branch remoto. Ci limitiamo invece a eseguire il comando git push come mostrato in basso.
[remote_repo_1] (negozio_1) $ git push origin negozio_1
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 416 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://bitbucket.org/clauudio/remote_repo_test.git
* [new branch] negozio_1 -> negozio_1
Vengono quindi inviati i commit al repository remoto, ma non viene inserita nessuna configurazione nel file .git/config. Per cui ogni volta che vogliamo eseguire il comando git push dal branch negozio_1, dobbiamo specificare il nome del repository e del branch remoto.
[remote_repo_1] (negozio_1) $ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://clauudio@bitbucket.org/clauudio/remote_repo_test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
Se volessimo rimediare, possiamo comunque lanciare il seguente comando.
# git branch --set-upstream origin/negozio_1
# Se non siamo sul branch negozio_1 dobbiamo invece lanciare il seguente comando
# git branch --set-upstream origin/negozio_1 negozio_1
# L'opzione -u è equivalente a --set-upstream
[remote_repo_1] (negozio_1) $ git branch -u origin/negozio_1
cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://clauudio@bitbucket.org/clauudio/remote_repo_test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "negozio_1"]
remote = origin
merge = refs/heads/negozio_1
Modifichiamo allora il file preventivo_negozio_1.txt ed eseguiamo un nuovo commit.
[remote_repo_1] (negozio_1) $ echo 'Asrock A320M - 52€' > preventivo_negozio_1.txt
[remote_repo_1] (negozio_1) $ git commit -am 'aggiunge la scheda madre Asrock A320M al file preventivo_negozio_1.txt'
[negozio_1 521dab6] aggiunge la scheda madre Asrock A320M al file preventivo_negozio_1.txt
1 file changed, 1 insertion(+)
[remote_repo_1] (negozio_1) $ git status
On branch negozio_1
Your branch is ahead of 'origin/negozio_1' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
Siamo pronti a questo punto a eseguire il comando git push.
[remote_repo_1] (negozio_1) $ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 345 bytes | 345.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://bitbucket.org/clauudio/remote_repo_test.git
2c58e79..521dab6 negozio_1 -> negozio_1
Possiamo provare ora a cambiare directory. Ci spostiamo quindi nella cartella di un livello superiore rispetto a quella corrente e lanciamo il comando git clone che, come possiamo immaginare dal nome, clona un repository remoto in una nuova directory. Se non passiamo il nome di una cartella come argomento, verrà usata la directory corrente. Nel nostro caso vogliamo clonare il repository nella cartella remote_repo_2. Possiamo trovare l’indirizzo da usare nel comando git clone all’interno della sezione ‘Overview’ del repository su Bitbucket.
[~] $ git clone https://clauudio@bitbucket.org/clauudio/remote_repo_test.git remote_repo_2
Cloning into 'remote_repo_2'...
Password for 'https://clauudio@bitbucket.org':
remote: Counting objects: 15, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 15 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (15/15), done.
Se ci spostiamo nella nuova cartella e lanciamo il comando git branch -a possiamo verificare che non è stato copiato il branch negozio_1, ma solo il branch master che è il branch di default del repository remoto. (Possiamo cambiare il branch di default nelle impostazioni del repository su Bitbucket)
[remote_repo_2] (master) $ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/negozio_1
[remote_repo_2] (master) $ ls
README.md configurazione_pc.txt
[remote_repo_2] (master) $ git log --oneline --decorate --all
521dab6 (origin/negozio_1) aggiunge la scheda madre Asrock A320M al file preventivo_negozio_1.txt
2c58e79 aggiunge il file preventivo_negozio_1 con il costo del processore AMD Ryzen 3 1200
efca4c1 (HEAD -> master, origin/master, origin/HEAD) aggiunge il file README.md
d0dcf38 aggiunge il processore AMD Ryzen 3 1200 al file configurazione_pc.txt
9221bff first commit
[remote_repo_2] (master) $ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://clauudio@bitbucket.org/clauudio/remote_repo_test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
Come possiamo vedere dall’output del comando git log, sono state scaricate tutte le informazioni relative ai branch remoti. Non possiamo effettuare il comando git checkout con i branch remoti, ma possiamo ricreare il branch negozio_1 a partire da quello remoto usando il comando mostrato sotto.
# In alternativa è possibile eseguire il comando
# git checkout -b negozio_1 origin/negozio_1
# che permette di anche di usare un nome diverso per il branch locale
[remote_repo_2] (master) $ git checkout --track origin/negozio_1
Branch 'negozio_1' set up to track remote branch 'negozio_1' from 'origin'.
Switched to a new branch 'negozio_1'
[remote_repo_2] (negozio_1) $ git branch -a
master
* negozio_1
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/negozio_1
[remote_repo_2] (negozio_1) $ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://clauudio@bitbucket.org/clauudio/remote_repo_test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "negozio_1"]
remote = origin
merge = refs/heads/negozio_1
[remote_repo_2] (negozio_1) $ git log --oneline --decorate --graph --all
* 521dab6 (HEAD -> negozio_1, origin/negozio_1) aggiunge la scheda madre Asrock A320M al file preventivo_negozio_1.txt
* 2c58e79 aggiunge il file preventivo_negozio_1 con il costo del processore AMD Ryzen 3 1200
* efca4c1 (origin/master, origin/HEAD, master) aggiunge il file README.md
* d0dcf38 aggiunge il processore AMD Ryzen 3 1200 al file configurazione_pc.txt
* 9221bff first commit
Essendoci spostati sul nuovo branch possiamo creare un nuovo commit ed eseguire l’operazione di push per aggiornare il repository remoto.
[remote_repo_2] (negozio_1) $ echo 'Ballistix Sport LT 8 GB Kit DDR4 - 98€' >> preventivo_negozio_1.txt
[remote_repo_2] (negozio_1) $ git commit -am 'aggiunge le RAM Ballistix al preventivo_negozio_1.txt'
[negozio_1 00a06c6] aggiunge le RAM Ballistix al preventivo_negozio_1.txt
1 file changed, 1 insertion(+)
[remote_repo_2] (negozio_1) $ git status
On branch negozio_1
Your branch is ahead of 'origin/negozio_1' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
[remote_repo_2] (negozio_1) $ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 375 bytes | 375.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://bitbucket.org/clauudio/remote_repo_test.git
521dab6..00a06c6 negozio_1 -> negozio_1
[remote_repo_2] (negozio_1) $ git log --oneline --decorate
00a06c6 (HEAD -> negozio_1, origin/negozio_1) aggiunge le RAM Ballistix al preventivo_negozio_1.txt
521dab6 aggiunge la scheda madre Asrock A320M al file preventivo_negozio_1.txt
2c58e79 aggiunge il file preventivo_negozio_1 con il costo del processore AMD Ryzen 3 1200
efca4c1 (origin/master, origin/HEAD, master) aggiunge il file README.md
d0dcf38 aggiunge il processore AMD Ryzen 3 1200 al file configurazione_pc.txt
9221bff first commit
Torniamo ora nella cartella remote_repo_1, spostiamoci sul branch negozio_1 e lanciamo il comando git fetch per recuperare il nuovo commit che abbiamo appena aggiunto al repository remoto.
[remote_repo_1] (negozio_1) $ git fetch
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://bitbucket.org/clauudio/remote_repo_test
521dab6..00a06c6 negozio_1 -> origin/negozio_1
[remote_repo_1] (negozio_1) $ git log --oneline --all
00a06c6 (origin/negozio_1) aggiunge le RAM Ballistix al preventivo_negozio_1.txt
521dab6 (HEAD -> negozio_1) aggiunge la scheda madre Asrock A320M al file preventivo_negozio_1.txt
2c58e79 aggiunge il file preventivo_negozio_1 con il costo del processore AMD Ryzen 3 1200
efca4c1 (master, origin/master) aggiunge il file README.md
d0dcf38 aggiunge il processore AMD Ryzen 3 1200 al file configurazione_pc.txt
9221bff first commit
[remote_repo_1] (negozio_1) $ git merge origin/negozio_1
Updating 521dab6..00a06c6
Fast-forward
preventivo_negozio_1.txt | 1 +
1 file changed, 1 insertion(+)
Abbiamo così aggiornato il branch locale con il commit che era stato aggiunto al branch negozio_1 del repository remoto. Come possiamo notare, abbiamo eseguito il comando git merge così come avremmo fatto se si fosse trattato di un branch locale.
In questo caso l’operazione eseguita è stata abbastanza semplice. Se invece avessimo aggiunto dei nuovi commit al branch locale mentre veniva aggiornato il repository remoto da un altro membro del team e avessimo provato a eseguire il comando git push, avremmo ricevuto un messaggio d’errore come quello mostrato in basso.
[remote_repo_1] (negozio_1) $ git push
To https://bitbucket.org/clauudio/remote_repo_test.git
! [rejected] negozio_1 -> negozio_1 (fetch first)
error: failed to push some refs to 'https://clauudio@bitbucket.org/clauudio/remote_repo_test.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Come mostrato nell’output del comando, Git ci avverte che non è possibile eseguire git push perché il branch sul repository remoto contiene dei commit che non sono presenti in origin/negozio_1. In situazioni del genere, dopo aver effettuato la consueta operazione di fetch dovremmo comunque eseguire il comando git merge (non si sarebbe trattato di un Fast-forward merge) e risolvere eventuali conflitti. Solo a questo punto è possibile eseguire il comando git push con successo.
Nell’esempio visto finora, abbiamo usato lo stesso utente per collegarsi al repository remoto. In situazioni reali, i diversi collaboratori dovrebbero essere aggiunti all’elenco delle persone autorizzate ad accedere e/o modificare il repository remoto. Per ogni collaboratore è possibile definire una serie di permessi specifici. A tal proposito Bitbucket fornisce una breve guida.
Ciascun collaboratore aggiunto riceve una mail e accedendo al proprio account può visualizzare tutte le informazioni necessarie per iniziare a lavorare al nuovo progetto.
Il nuovo membro del team può a questo punto decidere di clonare il repository sul proprio computer e lavorare al progetto seguendo gli stessi passi visti in precedenza.
Eseguire il fork del repository
Non sempre si ha accesso completo a un repository remoto e non sempre si ha il permesso inviare nuovi commit a un branch di un repository remoto con il comando git push. Se si vuole però contribuire a un progetto, per esempio un progetto open-source, possiamo effettuare il fork del repository.
Vuol dire che, se è permesso eseguire il fork di un progetto, copiamo i file di un repository originale in un nuovo repository remoto nel nostro account. A quel punto possiamo clonare il repository sul nostro computer e lavorare allo sviluppo di una certa funzionalità.
Possiamo eseguire il comando git push e i nuovi commit saranno inclusi nella nostra copia del repository. Tutte le modifiche da noi effettuate non riguarderanno in alcun modo il repository originale. Nel caso di fork di un repository, è opportuno aggiungere il repository originale nella configurazione del nostro repository locale. Per far ciò possiamo usare il seguente comando.
$ git remote add upstream https://bitbucket.org/UTENTE_ORIGINALE/REPOSITORY_ORIGINALE.git
Per riferirsi al repository originale si usa solitamente il nome upstream, mentre useremo origin per riferirci alla nostra copia remota del repository.
$ git remote -v
origin https://bitbucket.org/NOSTRO_NOME_UTENTE/FORK_DEL_REPOSITORY_ORIGINALE.git (fetch)
origin https://bitbucket.org/NOSTRO_NOME_UTENTE/FORK_DEL_REPOSITORY_ORIGINALE.git (push)
upstream https://bitbucket.org/UTENTE_ORIGINALE/REPOSITORY_ORIGINALE.git (fetch)
upstream https://bitbucket.org/UTENTE_ORIGINALE/REPOSITORY_ORIGINALE.git (push)
In questo modo potremo sempre includere nel nostro repository eventuali modifiche che sono state aggiunte al repository originale dopo l’operazione di fork.
Se dopo aver lavorato a una certa funzionalità, vogliamo chiedere di integrarla nel repository originale, possiamo farlo attraverso il meccanismo delle Pull Request.
Quando effettuiamo una Pull Request chiediamo agli sviluppatori del progetto originale se sono interessati a incorporare e fondere un branch della nostra versione del repository in quello originale. Dopo aver revisionato e controllato che tutto vada bene, la funzionalità sviluppata può essere eventualmente inclusa nel repository originale.
Conclusioni
In questa lezione abbiamo illustrato come sia possibile usare Git in repository remoti per collaborare con altre persone. Git e i diversi servizi online di hosting di repository come Github o Birbucket mettono a disposizione una serie di strumenti che facilitano il lavoro in team. In questo modo è possibile lavorare in maniera più efficiente e condividere con estrema semplicità i file di un progetto. Nella prossima lezione continueremo a parlare di repository remoti e vedremo alcuni esempi di workflow usati in Git per migliorare il processo di collaborazione in un team.