<div class="page">
<div class="cover text-center">
<img class="mx-auto" src=/itb/images/logo_mislata.png alt="logo">
# Repositori Remot
<div class="text-end fit-content ms-auto my-3 mt-auto pt-3">
<p><strong>Autor:</strong> Joan Puigcerver Ibáñez</p>
<p><strong>Correu electrònic:</strong> j.puigcerveribanez@edu.gva.es</p>
<p><strong>Curs:</strong> 2024/2025</p>
</div>
<div>
<p class="fw-bold mb-0">Llicència: BY-NC-SA</p>
<p class="d-none d-md-block">(Reconeixement - No Comercial - Compartir Igual)</p>
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.ca" target="_blank">
<img class="mx-auto" src="/itb/images/license.png" alt="Licence"/>
</a>
</div><!--license-->
</div><!--cover-->
</div><!--page-->
{:toc}
## Introducció
Fins aquest moment ens hem centrat a estudiar quin és el funcionament d'un repositori de Git,
conéixer la seua estructura i realitzar accions bàsiques per realitzar canvis sobre aquest.
A més a més, també hem vist com es poden crear diferents branques per poder treballar d'una manera
independent a l'estat de la branca principal i després, incorporar els canvis d'una branca a una altra.
No obstant això, totes aquestes operacions s'han realitzat en __local__, és a dir, en el vostre dispositiu,
i no s'han publicat els canvis enlloc.
En aquest material ens centrarem amb què és un __repositori remot__ i les principals
operacions de sincronització entre el repositori local i el repositori remot.
## Repositori Remot
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.
#2.2[Repositori remot vinculat a múltiples repositoris locals](/itb/DAM-ED/UD2/img/git_material/02_remots/multiple_local_repo.png)
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.
Alguns dels serveis d'allotjament repositoris remots en línia més coneguts són:
- __[GitHub](https://github.com/)__: 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](https://gitlab.com/)__: Servei d'allotjament de repositoris. GitLab és una plataforma de codi obert.
- __[BitBucket](https://bitbucket.org/)__: Servei d'allotjament de repositoris propietat de l'empresa Atlassian,
s'integra estretament amb altres eines d'aquesta empresa, com Jira.
::: info
Més informació: https://about.gitlab.com/competition/github/
:::
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_).
## Publicar un repositori local existent
En els materials anteriors vam crear el repositori `git_tutorial`, en el qual
es van crear diferents commits de manera local.
```shell
joapuiib@FP:~/git_tutorial (main) $ git lg
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver (HEAD -> main)
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
```
### Creació Repositori Remot
Ara l'objectiu és publicar aquests canvis a un _Repositori Remot_.
El Repositori Remot pot estar allotjat en un servidor de l'empresa o
en un servei d'allotjament. En el nostre cas, crearem un repositori
en el servei d'allotjament GitHub.
En la pàgina https://github.com/new pots crear un nou repositori i especificar
les seues característiques, com el nom, la descripció i la visibilitat.
#3.1.1[Captura de pantalla de la creació d'un Repositori Remot a GitHub](/itb/DAM-ED/UD2/img/git_material/remotes/repo_new.png)
Una vegada creat, el repositori està buit i ens indiquen una sèrie de comandes per configurar el repositori.
Anem a estudiar-les.
#3.1.2[Captura de pantalla d'un Repositori Remot a GitHub el qual està buit](/itb/DAM-ED/UD2/img/git_material/remotes/repo_created.png)
### Afegir un remot
Intentarem publicar els canvis mitjançant l'ordre `git push`:
```shell
joapuiib@FP:~/git_tutorial (main) $ git push
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>
```
Com podeu observar, l'ordre `git push` ha fallat perquè el repositori local no té
assignat cap repositori remot i no sap on ha de publicar els canvis.
#3.2.1[Repositori Local no té cap remot configurat](/itb/DAM-ED/UD2/img/git_material/02_remots/unknown_remote.png)
::: docs
Podeu consultar totes les opcions de `git remote` en el manual:
```bash
man git remote
# O bé...
git remote --help
```
També disponible en línia: https://git-scm.com/docs/git-remote
:::
#3.2.2[Repsitori Local es vincula amb un Repositori Remot](/itb/DAM-ED/UD2/img/git_material/02_remots/add_remote.png)
L'ordre `git remote add` permet afegir un nou _Repositori Remot_:
- `<remote>`: Nom del repositori remot. Normalment, s'utilitza el nom `origin` per definir l'àlies del remot.
- `<url>`: Dirrecció URL del repositori remot.
```bash
git remote add <remote> <url>
```
Afegim el repositori creat en GitHub:
```shell
joapuiib@FP:~/git_tutorial (main) $ git remote add origin git@github.com:joapuiib/git_tutorial.git
```
::: warning
Vosaltres heu d'especificar l'enllaç del vostre repositori remot.
:::
::: note
En aquest cas s'ha utilitzat l'enllaç SSH del repositori
perquè hem configurat prèviament una clau SSH en el dispositiu.
Veure: [Autentificació SSH](/itb/DAM-ED/UD1/materials/04_preparacio_entorn.html#autentificaci%C3%B3-ssh)
:::
### Mostrar i eliminar un remot
L'ordre `git remote show` s'utilitza per mostrar tots els remots (pot ser més d'un!) del repositori.
A més, podem veure més informació de cada remot configurat amb:
```
git remote show <remote>
```
En aquest cas:
- __Fetch URL__: URL que s'utilitza per obtindre canvis.
- __Push URL__: URL que s'utilitza per publicar canvis.
- __HEAD branch__: Branca per defecte del repositori remot. De moment no hem publicat cap branca.
```shell
joapuiib@FP:~/git_tutorial (main) $ git remote show
origin
joapuiib@FP:~/git_tutorial (main) $ git remote show origin
* remote origin
Fetch URL: git@github.com:joapuiib/git_tutorial.git
Push URL: git@github.com:joapuiib/git_tutorial.git
HEAD branch: (unknown)
```
Si es dessitja, es pot eliminar un remot amb:
```bash
git remote remove <remote>
```
### Publicació
Una vegada ja s'ha configurat el remot, ja podem publicar els canvis amb `git push`:
```shell
joapuiib@FP:~/git_tutorial (main) $ git push
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 main
```
#3.3.1[Es publiquen els canvis de la branca 'main' al Repositori Remot](/itb/DAM-ED/UD2/img/git_material/02_remots/push_setupstream.png)
Podem observar que l'ordre `git push` ha tornat a fallar.
En aquest cas ens indica que la branca actual `main` no té assignada cap branca
en el remot i, per tant, no sap en quina branca ha de publicar els canvis.
Per indicar la branca remota a la qual s'associa una branca local cal
utilitzar l'opció `-u` o `--set-upstream`:
- `--set-upstream` o `-u`: Opció per especificar la branca remota
- `<remote>`: Nom del remot configurat.
- `<remote_branch>`: Nom de la branca en el repositori remot.
```bash
git push --set-upstream <remote> <remote_branch>
```
```shell
joapuiib@FP:~/git_tutorial (main) $ git push --set-upstram origin main
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 526 bytes | 526.00 KiB/s, done.
Total 6 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To github.com:joapuiib/git_tutorial.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
joapuiib@FP:~/git_tutorial (main) $ git lg
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver (HEAD -> main, origin/main, origin/HEAD)
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
```
Podeu observar que s'ha creat la branca `main` en el repositori remot i s'ha creat la referència `origin/main` i `origin/HEAD`.
També podem consultar els canvis publicats en el repositori remot:
#3.3.2[Estat del repositori remot a GitHub després del push](/itb/DAM-ED/UD2/img/git_material/remotes/repo_push.png)
Una vegada fet el push, podem tornar a consultar les dades del remot `origin`:
```shell
joapuiib@FP:~/git_tutorial (main) $ git remote show origin
* remote origin
Fetch URL: git@github.com:joapuiib/git_tutorial.git
Push URL: git@github.com:joapuiib/git_tutorial.git
HEAD branch: main
Remote branch:
main tracked
Local branch configured for 'git pull':
main merges with remote main
Local ref configured for 'git push':
main pushes to main (up to date)
```
- __HEAD branch__: La branca per defecte del repositori remot ha canviat a la branca `main`.
- __Remote branch__: Ens indica que la branca actual està associada en la branca remota `main`.
- __Local branch configured for 'git pull'__: Ens indica com s'incorporen els canvis de la branca actual
des del repositori remot al repositori local quan s'executa `git pull`.
- __Local branch configured for 'git push'__: Ens indica la branca del repositori remot on es publicaran els
canvis efectuats en el repositori local quan s'executa la branca `git push`.
## Clonar un repositori remot
En l'apartat anterior hem publicat un repositori local i sincronitzat els seus canvis amb un repositori remot buit.
#4.1[Clonació d'un repositori remot](/itb/DAM-ED/UD2/img/git_material/02_remots/clone.png)
Imagineu que hem compartit aquest repositori amb una altra persona. Aquesta persona necessita fer el contrari,
_descarregar-se_ el repositori remot a un repositori local. Aquesta acció es pot dur a terme amb l'ordre `git clone`:
- `<repository_url>`: Dirrecció URL del repositori remot.
- `[<directory>`]: Paràmetre opcional que permet especificar el nom del directori on es clonarà el repositori remot. Per defecte té el mateix nom que el repositori remot.
```
git clone <repository_url> [<directory>]
```
Per il·lustrar aquest exemple ens imaginarem que hem compartit el repositori amb Pau.
Clonem el repositori en el directori `git_tutorial_pau`, on Pau realitzarà els seus canvis.
::: note
Per a indicar la persona que fa els canvis, es mostrarà un nom d'usuari diferent en el _prompt_ de la terminal.
:::
```shell
pau@FP:~ $ git clone git@github.com:joapuiib/git_tutorial.git git_tutorial_pau
Cloning into 'git_tutorial_pau'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 1), reused 6 (delta 1), pack-reused 0
Receiving objects: 100% (6/6), done.
Resolving deltas: 100% (1/1), done.
pau@FP:~ $ cd git_tutorial_pau/
pau@FP:~/git_tutorial_pau (main) $ cd git_tutorial_pau/
pau@FP:~/git_tutorial_pau (main) $ ls
README.md
pau@FP:~/git_tutorial_pau (main) $ git lg
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver (HEAD -> main, origin/main, origin/HEAD)
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
pau@FP:~/git_tutorial_pau (main) $ git remotes show origin
* remote origin
Fetch URL: git@github.com:joapuiib/git_tutorial.git
Push URL: git@github.com:joapuiib/git_tutorial.git
HEAD branch: main
Remote branch:
main tracked
Local branch configured for 'git pull':
main merges with remote main
Local ref configured for 'git push':
main pushes to main (up to date)
```
S'ha realitzat el següent:
- `git clone`: S'ha clonat el repositori en el directori `git_tutorial_pau`.
- `cd`: Ens situem dins del directori.
- `ls`: Mostrem els continguts. Vegem que és el contingut que teniem en el repositori remot.
- `git lg`: S'observa que també s'ha copiat informació del repositori, com la història de _commits_.
També inclou informació sobre on se situen les branques remotes `origin/main` i `origin/HEAD`.
- `git remotes show`: Quan es clona el repositori, automàticament s'afegeix el remot `origin` i el _upstream_ de la branca principal.
En aquest punt, Pau pot fer canvis i contribuir en el repositori.
::: note
S'ha realitzat una configuració en el repositori per indicar que
els canvis els està realitzant Pau.
S'ha utilitzat l'ordre `git config` sense el paràmetre `--global`
per indicar que aquesta configuració sols afecta a aquest repositori.
:::
```shell
pau@FP:~/git_tutorial_pau (main) $ git config user.name "Pau"
pau@FP:~/git_tutorial_pau (main) $ git config user.email "pau@fpmislata.com"
pau@FP:~/git_tutorial_pau (main) $ echo "Modificació de Pau" > pau.txt
pau@FP:~/git_tutorial_pau (main) $ cat pau.txt
Modificació de Pau
pau@FP:~/git_tutorial_pau (main) $ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.red{pau.txt}
nothing added to commit but untracked files present (use "git add" to track)
pau@FP:~/git_tutorial_pau (main) $ git add pau.txt
pau@FP:~/git_tutorial_pau (main) $ git commit -m "Modificació de Pau"
pau@FP:~/git_tutorial_pau (main) $ git lg
* bdbfcb2 - (1 second ago) Modificació de Pau - Pau (HEAD -> main)
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver (origin/main, origin/HEAD)
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
pau@FP:~/git_tutorial_pau (main) $ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
```
Pau ha realitzat un nou _commit_ en el repositori on ha afegit el fitxer __pau.txt__.
Observem en `git status` que ens indica que podem publicar aquest nou canvi mitjançant `git push`.
```shell
pau@FP:~/git_tutorial_pau (main) $ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 297 bytes | 297.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:joapuiib/git_tutorial.git
c9fc6c8..bdbfcb2 main -> main
pau@FP:~/git_tutorial_pau (main) $ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
pau@FP:~/git_tutorial_pau (main) $ git lg
* bdbfcb2 - (1 second ago) Modificació de Pau - Pau (HEAD -> main, origin/main, origin/HEAD)
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
```
Observem que després de fer el `push`, el `status` ja ens indica que estem al dia
i s'han actualitzat les referències del repositori remot `origin/main` i `origin/HEAD`.
Si consultem el repositori remot, podrem veure els canvis publicats.
## Incorporar canvis des del remot
En aquest moment, Pau ha contribuït en el repositori, però nosaltres encara no ho sabem.
Aquest és l'estat del nostre repositori:
```shell
joapuiib@FP:~/git_tutorial (main) $ git lg
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver (HEAD -> main, origin/main, origin/HEAD)
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
```
Podem comprovar si han hagut modificacions o nous canvis en el repoitori remot mitjançant l'ordre `git fetch`.
#5.1[Operació `fetch` en un repositori de Git](/itb/DAM-ED/UD2/img/git_material/02_remots/fetch.png)
La comanda `git fetch` s'utilitza per recuperar els canvis des del repositori remot,
però no els incorpora a la branca actual.
```shell
joapuiib@FP:~/git_tutorial (main) $ git fetch
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 277 bytes | 277.00 KiB/s, done.
From github.com:joapuiib/git_tutorial
c9fc6c8..bdbfcb2 main -> origin/main
joapuiib@FP:~/git_tutorial (main) $ git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
joapuiib@FP:~/git_tutorial (main) $ git lga
* bdbfcb2 - (5 hours ago) Modificació de Pau - Pau (origin/main, origin/HEAD)
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver (HEAD -> main)
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
joapuiib@FP:~/git_tutorial (main) $ ls
README.md
joapuiib@FP:~/git_tutorial (main) $ cat pau.txt
cat: pau.txt: No such file or directory
```
S'observa que la referència `origin/main` ha avançat i ha aparegut el nou _commit_ que ha fet Pau.
No obstant la referència `main` no ha canviat i no existeix el fitxer __pau.txt__.
La comanda `git status` ens indica que la branca local està enrederida respecte
a la branca del repositori remot i com podem integrar els canvis amb `git pull`.
#[Operació `pull` en un repositori de Git](/itb/DAM-ED/UD2/img/git_material/02_remots/pull.png)
Si volem incorporar els canvis, hem de llançar l'ordre `git pull`,
que fusionarà els canvis entre la branca remota i la branca local mitjançant un `merge`.
Aquesta ordre executa primer un `git fetch` per comprovar si hi ha nous canvis en
el repositori remot.
::: note
La fusió entre branques `merge` s'estudia en el següent material.
:::
```shell
joapuiib@FP:~/git_tutorial (main) $ git pull
Updating c9fc6c8..bdbfcb2
Fast-forward
pau.txt | 1 .green{+}
1 file changed, 1 insertion(+)
create mode 100644 pau.txt
joapuiib@FP:~/git_tutorial (main) $ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
joapuiib@FP:~/git_tutorial (main) $ git lga
* bdbfcb2 - (5 hours ago) Modificació de Pau - Pau (HEAD -> main, origin/main, origin/HEAD)
* c9fc6c8 - (1 day ago) Changed README.md - Joan Puigcerver
* 8e70293 - (4 days ago) Added Readme.md - Joan Puigcerver
joapuiib@FP:~/git_tutorial (main) $ cat pau.txt
Modificació de Pau
```
Una vegada executada l'ordre `git pull`, podem observar que la referència `main` ja està en el _commit_ realitzat per Pau
i que els canvis que ha realitzat existeixen en el nostre repositori i directori de treball.
## Recursos addicionals
- Curs de Git des de zero per MoureDev: https://www.youtube.com/watch?v=3GymExBkKjE&ab_channel=MoureDevbyBraisMoure
- https://github.com/UnseenWizzard/git_training
## Bibliografia
- https://github.com/UnseenWizzard/git_training
- https://about.gitlab.com/competition/github/