En el blocs anteriors, ens hem centrat en conéixer la seua estructura i
realitzar accions bàsiques per realitzar canvis sobre aquest.
No obstant això, totes les accions que hem realitzat fins ara han sigut
sobre un repositori local, és a dir, un repositori que es troba en
el nostre dispositiu i aquests canvis no han segut publicats en cap
lloc.
En aquest bloc, ens centrarem en la creació de repositoris remots;
repositoris que es troben allotjats en un servidor, que permeten
l'accés a altres usuaris i la col·laboració en el desenvolupament de
projectes.
Figura 1. Estructura d'un repositori local i remot
Preparació repositori local
En aquests apunts treballarem sobre un nou repositori local.
Danger
Crea el nou repositori en una carpeta independent per evitar
problemes amb els exemples i exercicis anteriors.
Inicialització:
#!/bin/bash# Elimina els repositori si existeixif[-d~/git_remots];thenrm-rf~/git_remots
fimkdir-p~/git_remots
cd~/git_remots
gitinit
gitbranch-mmain# (1)!echo"# Remots a Git">README.md
echo"Repositori del __Bloc: Remots__ del curs __\"Introducció a Git i la seua aplicació a l’aula\"__">>README.md
gitaddREADME.md
gitcommit-m"Commit inicial"gitlga
jpuigcerver@fp:~$mkdir-p~/git_remots
jpuigcerver@fp:~$cd~/git_remots
jpuigcerver@fp:~/git_remots$gitinit
Initialized empty Git repository in ~/git_remots/.git/jpuigcerver@fp:~/git_remots(main)$gitbranch-mmain# (1)!jpuigcerver@fp:~/git_remots(main)$echo"# Remots a Git">README.md
jpuigcerver@fp:~/git_remots(main)$echo"Repositori del __Bloc: Remots__ del curs __\"Introducció a Git i la seua aplicació a l’aula\"__">>README.md
jpuigcerver@fp:~/git_remots(main)$gitaddREADME.md
jpuigcerver@fp:~/git_remots(main)$gitcommit-m"Commit inicial"[main (root-commit) 113f1d4] Commit inicial 1 file changed, 2 insertions(+) create mode 100644 README.mdjpuigcerver@fp:~/git_remots(main)$gitlga
*113f1d4-(0 seconds ago)Commit inicial-Joan Puigcerver(HEAD -> main)
Canviem el nom de la branca principal a main.
README.md
# Remots a GitRepositori del __Bloc: Remots__ del curs __"Introducció a Git i la seua aplicació a l’aula"__
Un Repositori Remot és una còpia d'un repositori de Git que es troba allotjat en un servidor
o en un altre lloc fora del teu propi sistema local.
Aquesta còpia conté una rèplica completa de la història del repositori,
incloses totes les revisions i les branques.
Els repositoris remots permeten la col·laboració i el seguiment del desenvolupament del codi
entre múltiples persones, o tu mateix en diferents dispositius.
Figura 2. Repositori remot vinculat a múltiples repositoris locals
Entre les finalitats dels repositoris remots podem trobar:
Col·laboració: Permeten que diversos desenvolupadors treballen junts en un mateix projecte.
Cada desenvolupador pot treballar en la seua còpia local del repositori remot i,
una vegada fetes les seues modificacions, pot pujar els canvis al repositori remot perquè altres membres
de l'equip puguen veure i incorporar aquestes modificacions.
Còpia de seguretat: Un repositori remot pot servir com a còpia de seguretat del teu projecte.
Si el teu sistema local es danya o es perd, encara tindràs accés a la teua història completa
i als fitxers del projecte mitjançant el repositori remot.
Distribució: Els repositoris remots permeten distribuir el teu codi a altres llocs.
Això pot ser útil per compartir el teu codi amb altres persones
o per desplegar el teu projecte en un servidor en línia.
Gràcies a aquestes característiques, Git s'ha convertit en una eina clau en qualsevol desenvolupament,
però sobretot en els projectes de codi obert (open source), ja que permet la col·laboració
de desenvolupadors de tot el món en un mateix projecte de manera senzilla i distribuïda.
Els repositoris remots es poden allotjar en qualsevol màquina o servidor dedicat.
No obstant això, hi ha serveis d'allotjament de repositoris remots en línia que faciliten la creació
i la gestió de repositoris remots.
Alguns dels serveis d'allotjament repositoris remots en línia més coneguts són:
GitHub: Servei d'allotjament de repositoris creat en 2008 i adquirit per Microsoft en 2018.
És el servei d'allotjament de repositoris de Git més utilitzat.
Ofereix una opció gratuïta, que permet crear projectes públics i privats, però amb algunes restriccions.
També ofereix plans de pagament per projectes empresarials.
GitLab: Servei d'allotjament de repositoris. GitLab és una plataforma de codi obert.
Bitbucket: Servei d'allotjament de repositoris propietat de l'empresa Atlassian,
s'integra estretament amb altres eines d'aquesta empresa, com Jira.
Omple el formulari amb la informació del teu repositori:
Nom del repositori. Ha de ser un nom únic en el teu compte de GitHub.
Descripció del repositori. Opcional.
Visibilitat del repositori. Pots triar entre públic o privat.
Públic: Qualsevol persona pot veure el teu repositori. Sols les persones autoritzades poden fer canvis.
Privat: Només tu i les persones que tu autoritzes poden veure el teu repositori. Sols les persones autoritzades poden fer canvis.
README: Indica si vols afegir un README al teu repositori.
.gitignore: Indica si vols afegir un fitxer .gitignore per ignorar fitxers en el teu repositori.
Llicència: Indica si vols afegir una llicència al teu repositori.
Exemple: Creació d'un repositori a GitHub
Creem un repositori amb les següents característiques:
Nom: git_remots
Descripció: Repositori del Bloc: Remots del curs "Introducció a Git i la seua aplicació a l’aula"
Visibilitat: Públic
README: No
.gitignore: No
Llicència: No
Figura 3. Formulari de creació d'un nou repositori a GitHub
Una vegada omplert el formulari, fes clic a "Create repository" per crear el teu repositori.
El teu repositori s'hauria de crear buit i hauries de veure una pàgina com la següent:
Figura 4. Repositori buit creat a GitHub
La Figura 3 mostra els passos per enllaçar el teu repositori local amb el repositori remot creat a GitHub.
En els següents apartats, explicarem aquestes ordres amb més detall.
Per afegir un repositori remot, utilitzarem la comanda git remote add.
La sintaxi és la següent:
gitremoteadd<alies><url>
<alies>: Nom o àlies del repositori remot en el teu repositori local.
Normalment, s'utilitza el nom origin per referir-se al repositori remot principal.
<url>: URL del repositori remot.
Figura 5. Repositori Local vinculat amb un Repositori Remot
Warning
Si intentes publicar amb git push
els canvis en un repositori remot
sense haver enllaçat el teu repositori local,
Git et mostrarà un missatge d'error:
jpuigcerver@fp:~/git_remots(main)$gitpush
fatal: No configured push destination.Either specify the URL from the command-line or configure a remote repository using git remote add <name> <url>and then push using the remote name git push <name>
Exemple: Afegir un repositori remot
Enllaçarem el nostre repositori local amb el repositori
remot creat anteriorment a GitHub.
La URL del repositori remot és git@github.com:jpuigcerver/git_remots.git.
Utilitzem la URL SSH ja que he decidit utilitzar aquest mètode d'autenticació.
Aquesta comanda funciona sobre la branca on estem situats (HEAD).
Figura 6. Publicació d'una branca local a una branca remota
Exemple: Publicació i associació branca local i remota
Vegem que inicialment la branca main no està associada a cap branca remota.
Si intentem fer un git push, ens mostrarà un missatge d'error com que
hem d'anar associar una branca remota.
jpuigcerver@fp:~/git_remots(main)$gitlga
*113f1d4-(4 seconds ago)Commit inicial-Joan Puigcerver(HEAD -> main)jpuigcerver@fp:~/git_remots(main)$gitpush
fatal: The current branch main has no upstream branch.To push the current branch and set the remote as upstream, use git push --set-upstream origin mainTo have this happen automatically for branches without a trackingupstream, see 'push.autoSetupRemote' in 'git help config'.
Associem les branques main local i remota amb l'ordre git push --set-upstream.
Localment, s'ha creat la referència origin/main que apunta a la branca remota main.
jpuigcerver@fp:~/git_remots(main)$gitpush--set-upstreamoriginmain
branch 'main' set up to track 'origin/main'.To github.com:joapuiib/git_remots.git * [new branch] main -> mainjpuigcerver@fp:~/git_remots(main)$gitlga
*113f1d4-(6 seconds ago)Commit inicial-Joan Puigcerver(HEAD -> main, origin/main)
Vegem que els canvis s'han publicat correctament al repositori remot:
Les branques locals poden ser associades a branques remotes
mitjançant l'opció -u o --set-upstream de la comanda git push.
git push [-u | --set-upstream] <remot> <branca>
Aquesta associació li permet a Git saber sobre quina branca remota
ha de realitzar les operacions quan no s'especifica explicitament,
com ara `git pull` o `git push`.
!!! tip "Consell"
Pots configurar git perquè configure automàticament la branca local
perquè s'associe amb la branca remota amb el mateix nom
amb l'opció `push.autoSetupRemote`.
```bash
git config --global push.autoSetupRemote true
```
L'associació d'una branca local pot ser eliminada
mitjançant l'ordre `git branch --unset-upstream`.
```bash
git branch --unset-upstream [<branca>]
L'ordre git clone permet copiar un repositori remot a un repositori local en el teu sistema,
des del qual podràs realitzar canvis.
Aquesta ordre còpia els continguts del Directori de Treball i tota la informació del Repositori Local,
incloent la història de canvis. A més, configura automàticament el repositori remot com a origin.
La sintaxi és la següent:
gitclone<url>[<directori>]
<url>: URL del repositori remot. Pot ser una URL HTTPS o SSH.
<directori>: Opcional. Nom del directori on es copiarà el repositori. Per defecte, es crea un directori amb
el nom del repositori remot.
Figura 7. Clonació d'un repositori remot
Exemple: Clonació d'un repositori remot
Com que ja tenim els canvis publicats al repositori remot,
podem clonar el repositori remot al nostre sistema local.
Esborrem el directori git_remots i el clonarem des del repositori remot.
jpuigcerver@fp:~/git_remots(main)$cd~
jpuigcerver@fp:~$rm-rf~/git_remots
jpuigcerver@fp:~$ls-l~/git_remots
ls: cannot access '~/git_remots': No such file or directoryjpuigcerver@fp:~$gitclonegit@github.com:joapuiib/git_remots.git
Cloning into 'git_remots'...jpuigcerver@fp:~$cd~/git_remots
jpuigcerver@fp:~/git_remots(main)$gitlga
*113f1d4-(8 seconds ago)Commit inicial-Joan Puigcerver(HEAD -> main, origin/main, origin/HEAD)
S'observa que s'ha clonat correctament el repositori remot git_remots
que conté els fitxers i la història de canvis del repositori remot.
L'ordre git fetch actualitza la informació de les branques remotes origin/<branca>
al nostre repositori local, però no aplica els canvis a les nostres branques locals.
gitfetch[<options>][<remot>]
<options>: Opcions de la comanda.
<remot>: Àlies del repositori remot. Per defecte, s'utilitza origin.
Figura 8. Sincronització entre repositoris amb git fetch
Aquesta ordre és útil per obtindre la informació dels canvis realitzats en el repositori remot
i decidir si volem incorporar-los al nostre repositori local.
La fusió (merge) implícita de git pull pot ser una Fusió directa
o es pot produir una Fusió de branques divergents si
la branca local i la branca remota divergeixen.
En aquest últim cas:
Poden produir conflictes. Si es produeixen, caldrà resoldre'ls manualment.
Executar directament git pullgenerarà un commit de fusió,
que pot ser no és desitjable si es vol mantenir una història lineal.
Consell
Per evitar la fusió de branques divergents en git pull,
es pot fer el següent:
git pull --ff-only: Incorpora els canvis de la branca remota
només si es pot fer una fusió directa (fast-forward).
En cas contrari, es produirà un error i no s'incorporaran els canvis.
A més, Git pot ser configurat perquè incloga aquesta opció
en la comanda git pull.
git config --global pull.ff only
git pull --rebase: Incorpora els canvis de la branca remota
mitjançant un rebase, és a dir, aplica els canvis de la branca local
després dels canvis de la branca remota.
Aquest comportament també es pot configurar per defecte en la comanda git pull.
git config --global pull.rebase true
Exemple: Incorporació de canvis fusió directa (pull --ff-only)
Vegem com el commit 1b3b4b0 forma part de la branca remota origin/main,
però no de la branca local main.
Realitza els següents canvis en el repositori remot directament a GitHub.
Modifica el fitxer menjar.txt amb el següent contingut:
menjar.txt
Pa
Macarrons
Pomes
Crea un commit amb el missatge Més menjar.
Exemple: Incorporació de canvis amb fusió de branques divergents (pull --no-ff i pull --rebase)
Una de les situacions més comunes que ens porten a que la branca local divergisca de la branca remota és
quan realitzem canvis sobre la branca local sense haver sincronitzat abans el seu estat amb la branca remota associada.
En aquest cas, s'ha realitzat un altre canvi en el repositori remot,
que nosaltres no hem incorporat.
No obstant això, anem a fer un canvi a la branca local main,
simulant la situació anteriorment descrita.
El canvi Més menjar no està reflectit en la branca remota origin/main
perquè no hem sincronitzat el nostre repositori local amb el repositori remot.
En aquest moment, podríem intentar publicar aquest canvi al repositori remot,
però com que el repositori remot té canvis que no estan reflectits en el nostre repositori local,
Git ens mostrarà un missatge d'error.
jpuigcerver@fp:~/git_remots(main)$gitpush
To github.com:joapuiib/git_remots.git ! [rejected] main -> main (fetch first)error: failed to push some refs to 'github.com:joapuiib/git_remots.git'hint: Updates were rejected because the remote contains work that you do nothint: have locally. This is usually caused by another repository pushing tohint: the same ref. If you want to integrate the remote changes, usehint: 'git pull' before pushing again.hint: See the 'Note about fast-forwards' in 'git push --help' for details.jpuigcerver@fp:~/git_remots(main)$gitfetch
From github.com:joapuiib/git_remots 8594cb9..8c604a3 main -> origin/mainjpuigcerver@fp:~/git_remots(main)$gitlga
*95b8d62-(4 seconds ago)Beguda-Joan Puigcerver(HEAD -> main)| *8c604a3-(6 seconds ago)Més menjar-Joan Puigcerver(origin/main, origin/HEAD)|/ *8594cb9-(12 seconds ago)Menjar-Joan Puigcerver*113f1d4-(22 seconds ago)Commit inicial-Joan Puigcerver
Vegem que l'ordre git push ens recomana fer un git pull per incorporar els canvis,
ja que les dues branques han divergit.
Si executem git pull, es produirà una fusió de branques divergents, que crearà un commit de fusió
i resultarà en una història no lineal.
Vegem que no podem incorporar els canvis amb una fusió directa git pull --ff-only.
jpuigcerver@fp:~/git_remots(main)$gitpull--ff-only
hint: Diverging branches can't be fast-forwarded, you need to either:hint:hint: git merge --no-ffhint:hint: or:hint:hint: git rebasehint:hint: Disable this message with "git config advice.diverging false"fatal: Not possible to fast-forward, aborting.
En aquest cas, haurem d'incorporar els canvis de dues maneres diferents.
Un commit de fusió: git pull --no-ff.
Aquest és el procés que seguirà git pull si no
indiquem cap opció addicional.
En aquest cas crearà un commit de fusió,
que no és desitjable si es vol mantenir una història lineal.
jpuigcerver@fp:~/git_remots(main)$gitpull--no-ff--no-edit# (1)!Merge made by the 'ort' strategy. menjar.txt | 1 + 1 file changed, 1 insertion(+)jpuigcerver@fp:~/git_remots(main)$gitlga
*a0b012f-(1 second ago)Merge branch 'main' of github.com:joapuiib/git_remots-Joan Puigcerver(HEAD -> main)|\ | *8c604a3-(10 seconds ago)Més menjar-Joan Puigcerver(origin/main, origin/HEAD)* |95b8d62-(8 seconds ago)Beguda-Joan Puigcerver|/ *8594cb9-(16 seconds ago)Menjar-Joan Puigcerver*113f1d4-(26 seconds ago)Commit inicial-Joan Puigcerver
L'opció --no-edit indica que no volem editar el missatge de commit de fusió i deixem el missatge per defecte.
Un canvi de base: git pull --rebase.
Aquesta opció aplica els canvis de la branca local després dels canvis de la branca remota,
mantenint una història lineal.