Vam tancar el mòdul 3 amb un problema obert: tota la feina de gestor-tasques viu dins d'un únic .git/, el del portàtil Ubuntu de l'Ana. Les branques d'en Bruno només existien a la nostra imaginació, i la Carla porta tres mòduls esperant al seu Windows 11 que algú li digui d'on descarregar el projecte.

Aquest mòdul tanca el cercle, i comença per on cal començar: entenent què és un remot. I la resposta decebrà qui esperés màgia, perquè un remot no és un servidor, ni un servei, ni una còpia sincronitzada del teu projecte. Un remot és un nom curt per a un URL. Res més. Tota la resta —fetch, pull, push, les branques de seguiment— es construeix damunt d'aquesta idea minúscula.

En aquesta lliçó encara no registrarem cap remot (això és la lliçó següent). Construirem el model mental correcte: per què en un sistema distribuït no existeix tècnicament un servidor central, què és un repositori bare i per què el del servidor no té fitxers amb què treballar, què són exactament aquestes referències origin/main que van apareixent des de la lliçó 02-02, i què afegeixen plataformes com GitHub o GitLab damunt del Git que ja coneixes.

Contingut

  1. Què és un remot: un nom curt per a un URL
  2. Per què no hi ha servidor central (tècnicament)
  3. El repositori de referència: una convenció, no una imposició
  4. Repositoris bare: el servidor no necessita fitxers
  5. Les referències remotes: .git/refs/remotes/
  6. origin/main és una referència local de només lectura
  7. Convencions de nom: origin, upstream i els altres
  8. Plataformes d'allotjament: què afegeixen damunt de Git
  9. El mapa mental complet

  1. Què és un remot: un nom curt per a un URL

Comencem per la definició exacta, perquè gairebé tot el desconcert posterior neix de no tenir-la clara.

Un remot és una entrada a la configuració del teu repositori que associa un nom curt a un URL (i a unes regles sobre quines referències portar d'allà).

Això és literalment tot. Quan escrius origin, Git busca a .git/config una secció [remote "origin"], llegeix l'URL que hi ha dins i el fa servir. És exactament el mateix mecanisme que un àlies de shell o una entrada a /etc/hosts: un nom còmode per a una cosa llarga i incòmoda de teclejar.

Compara les dues maneres de fer el mateix:

# Sense remot registrat: l'URL sencer, cada vegada
git fetch https://git.exemple.cat/equip/gestor-tasques.git main

# Amb el remot registrat: un nom curt
git fetch origin main

Totes dues funcionen. La primera demostra el punt: Git pot parlar amb qualsevol repositori donant-li el seu URL directament, sense registrar res. Els remots existeixen per no repetir l'URL quaranta vegades al dia i per poder-hi associar configuració addicional.

El que un remot NO és

És igual d'important saber què no hi ha darrere d'aquesta paraula:

Un remot no és… Per què la gent s'ho pensa
Una carpeta sincronitzada tipus Dropbox Res no se sincronitza sol: els objectes viatgen únicament quan executes fetch, pull o push
Una connexió permanent Git és completament asíncron: treballa sense xarxa i només es connecta en aquestes tres ordres
Una còpia idèntica del teu repositori El remot té les seves pròpies branques, que poden anar per davant o per darrere de les teves
Un servidor amb intel·ligència L'altre extrem executa Git, igual que tu; allà no hi ha lògica de negoci
Una cosa obligatòria Un repositori Git és perfectament funcional sense cap remot, com el de l'Ana durant tres mòduls

Aquest darrer punt mereix èmfasi. Tot el que has fet fins ara —confirmar, ramificar, fusionar, resoldre conflictes, consultar l'historial— funciona sense xarxa i sense remots. Els remots no afegeixen capacitats a Git: hi afegeixen transport. Són el mecanisme pel qual els objectes d'un .git/objects/ acaben en un altre .git/objects/.

Els URL que admet un remot

Un remot pot apuntar a llocs molt diferents, i no tots són a Internet:

# HTTPS: el més habitual amb plataformes d'allotjament
https://git.exemple.cat/equip/gestor-tasques.git

# SSH, forma abreujada tipus scp (la més vista)
[email protected]:equip/gestor-tasques.git

# SSH, forma d'URL completa (equivalent a l'anterior)
ssh://[email protected]/equip/gestor-tasques.git

# Ruta local: una carpeta del mateix ordinador o d'un disc muntat
/home/ana/copies/gestor-tasques.git

# Ruta local en format file://
file:///home/ana/copies/gestor-tasques.git

# Protocol git:// (sense autenticació, només lectura, pràcticament en desús)
git://git.exemple.cat/equip/gestor-tasques.git

Els protocols ja els vas veure a la lliçó 02-02 en parlar de git clone; són exactament els mateixos, perquè clone no és més que «crear un repositori + registrar un remot + endur-s'ho tot».

Un detall que convé interioritzar: una ruta local és un URL perfectament vàlid. Pots tenir un remot que apunti a una carpeta del teu propi disc, i tot el mòdul funciona igual. Això és magnífic per practicar, i ho farem servir als exercicis: no necessites compte enlloc ni connexió a Internet per aprendre remots.

  1. Per què no hi ha servidor central (tècnicament)

A la lliçó 01-01 vam veure la diferència entre control de versions centralitzat i distribuït. Ara toca la conseqüència pràctica d'allò, que és més radical del que sol semblar.

A Subversion o CVS, el servidor és estructuralment diferent del client: conté l'historial, decideix quins números de revisió s'assignen i és imprescindible per a gairebé qualsevol operació. Sense servidor, no hi ha control de versions.

A Git no existeix aquesta distinció. Tots els repositoris són iguals. El repositori que hi ha a git.exemple.cat executa el mateix Git, desa els mateixos objectes amb el mateix format i no té cap privilegi especial sobre el de l'Ana. Si el servidor cremés aquesta tarda, qualsevol dels tres podria muntar-ne un de nou amb la seva pròpia còpia i l'equip seguiria treballant en cinc minuts.

flowchart TB
    subgraph ANA["Portàtil de l'Ana · Ubuntu"]
        A1["Repositori complet<br/>.git/objects + .git/refs<br/>+ directori de treball"]
    end
    subgraph BRUNO["MacBook d'en Bruno · macOS"]
        B1["Repositori complet<br/>.git/objects + .git/refs<br/>+ directori de treball"]
    end
    subgraph CARLA["Portàtil de la Carla · Windows 11"]
        C1["Repositori complet<br/>.git/objects + .git/refs<br/>+ directori de treball"]
    end
    subgraph SRV["git.exemple.cat · repositori bare"]
        S1["Repositori complet<br/>objects + refs<br/><b>sense</b> directori de treball"]
    end

    A1 <-->|push / fetch| S1
    B1 <-->|push / fetch| S1
    C1 <-->|push / fetch| S1
    A1 <-.->|tècnicament possible:<br/>intercanvi directe| B1

Fixa't en la línia discontínua entre l'Ana i en Bruno. No és cap adorn: és Git funcionant exactament com va ser dissenyat. En Bruno pot registrar el portàtil de l'Ana com a remot i endur-se els seus commits directament, sense que el servidor hi intervingui. Linus Torvalds va dissenyar Git per al nucli de Linux, on centenars de persones s'intercanvien pedaços i branques sense cap repositori central obligatori.

Aleshores, per què tothom fa servir un servidor?

Perquè les raons per tenir un repositori de referència no són tècniques, sinó organitzatives:

  • Disponibilitat. El portàtil de l'Ana està apagat a les nits, a l'avió i quan se'n va de vacances. Un servidor està encès sempre.
  • Punt d'acord. Amb un repositori de referència, la pregunta «quina és la versió bona de main?» té una resposta única i avorrida. Sense ell, hi ha tres respostes i tres opinions.
  • Còpia de seguretat implícita. Si el disc d'en Bruno mor, la feina que ha enviat continua existint.
  • Control d'accés. Algú ha de decidir qui pot escriure a main. Això requereix un lloc on aplicar aquestes regles.
  • Automatització. Les proves automàtiques, els desplegaments i els avisos necessiten un punt fix on enganxar-se (mòdul 7).
  • Direccionalitat de xarxa. L'Ana no es pot connectar al portàtil de la Carla: és darrere de l'encaminador de casa seva, amb IP canviant i sense ports oberts. Un servidor amb adreça estable resol el problema que tothom pugui arribar a algun lloc comú.

Aquesta darrera raó és la més subestimada i probablement la més decisiva a la pràctica.

  1. El repositori de referència: una convenció, no una imposició

De tot això en surt una idea que convé fixar bé:

El repositori «oficial» d'un projecte ho és perquè l'equip ha acordat que ho sigui, no perquè Git el distingeixi de cap manera.

Si demà l'equip decideix que el repositori bo passa a ser en un altre servidor, n'hi ha prou que tots tres canviïn una línia de configuració —l'URL del seu remot origin— i aquell altre serà l'oficial. Git no s'assabenta del canvi i tant li fa. És una migració de cinc segons per persona, una cosa impensable en un sistema centralitzat.

Aquesta flexibilitat té una cara incòmoda: Git no protegeix res per si mateix. No hi ha cap concepte natiu de «aquesta branca és sagrada» ni de «només l'Ana hi pot escriure». Qualsevol amb permís d'escriptura pot, en principi, reescriure main al servidor. Les proteccions que fan servir els equips —branques protegides, revisions obligatòries, comprovacions que han de passar abans d'integrar— les afegeixen les plataformes d'allotjament damunt de Git, no Git.

Ho veurem amb detall al mòdul 7, però interioritza ja la separació: Git mou objectes; la plataforma posa les regles.

  1. Repositoris bare: el servidor no necessita fitxers

A la lliçó 02-01 vam deixar una idea a mitges: git init --bare crea un repositori sense directori de treball, i vam dir que s'entendria en parlar de remots. Ha arribat el moment.

Què és exactament

Un repositori normal té aquesta forma:

gestor-tasques/
├── .git/            ← el repositori (objectes, referències, configuració)
│   ├── objects/
│   ├── refs/
│   ├── HEAD
│   └── config
├── index.html       ← el directori de treball
├── estils.css
├── app.js
└── README.md

Un repositori bare té aquesta altra:

gestor-tasques.git/
├── objects/         ← el que a l'altre era dins de .git/
├── refs/
├── HEAD
├── config
├── description
└── hooks/

És el contingut de .git/ promogut a l'arrel, i ni un sol fitxer del projecte. Per això es diu bare, «nu»: no té còpia de treball amb què vestir-se.

Per convenció, els directoris de repositoris bare acaben en .gitgestor-tasques.git— perquè es vegi d'un cop d'ull què són. D'aquí ve, precisament, el .git final dels URL que portes veient tot el curs.

Per què el repositori del servidor ha de ser bare

Imagina't per un moment que no ho fos: que al servidor hi hagués un repositori normal, amb el seu index.html i el seu app.js al disc, i amb HEAD apuntant a main.

L'Ana executa git push i envia tres commits nous a main. Què hauria de passar al servidor?

  • Si Git actualitzés la branca main i els fitxers del directori de treball, estaria modificant fitxers d'una màquina on potser hi ha algú editant-los en aquell precís moment. Podria destruir feina sense avisar.
  • Si actualitzés la branca però no els fitxers, el repositori del servidor quedaria en un estat incoherent: git status allà diria que hi ha desenes de fitxers modificats i esborrats, quan en realitat ningú no ha tocat res.

Cap de les dues opcions és acceptable, així que Git n'escull una tercera: negar-s'hi. Si proves d'enviar a la branca que està activa en un repositori no bare, obtens això:

! [remote rejected] main -> main (branch is currently checked out)
error: failed to push some refs to '/home/ana/copies/gestor-tasques'

Amb un repositori bare el problema desapareix d'arrel: com que no hi ha directori de treball, no hi ha res que pugui quedar incoherent. Rebre un push es redueix a afegir objectes i moure un punter, que és una operació neta i segura.

Repositori normal Repositori bare
Directori de treball No
Es crea amb git init / git clone git init --bare / git clone --bare
Estructura projecte/.git/… projecte.git/… (tot a l'arrel)
Serveix per a Treballar: editar, confirmar Compartir: rebre i servir
Admet git push a la seva branca activa No Sí (no té branca «activa» en aquest sentit)
S'hi pot editar codi No hi ha fitxers per editar
git status Informatiu Error: no hi ha còpia de treball

El que hi ha a l'altre costat de GitHub, GitLab o Gitea és sempre un repositori bare. Quan clones, la plataforma serveix els objectes des d'un; quan envies, els rep en un.

Crear-ne un per practicar

Això et servirà a tots els exercicis del mòdul, així que comprova-ho ara:

mkdir -p /tmp/servidor
git init --bare /tmp/servidor/gestor-tasques.git
Initialized empty Git repository in /tmp/servidor/gestor-tasques.git/
ls /tmp/servidor/gestor-tasques.git/
HEAD  branches  config  description  hooks  info  objects  refs

Exactament el que esperàvem: el contingut d'un .git/, sense fitxers de projecte. I la seva configuració ho declara:

git -C /tmp/servidor/gestor-tasques.git config core.bare
true

Aquest git -C <ruta> és un truc còmode: executa l'ordre com si fossis dins d'aquell directori, sense haver d'anar-hi i tornar.

Aquest directori és un «servidor» perfectament vàlid. Li pots enviar canvis i clonar-ne. L'única diferència amb GitHub és que és al teu disc i no té interfície web.

  1. Les referències remotes: .git/refs/remotes/

Aquí hi ha la peça central de la lliçó, i probablement el concepte que més malentesos genera a tot Git.

Al mòdul 3 vas aprendre que una branca és un fitxer de 41 bytes a .git/refs/heads/ amb un hash a dins. Doncs bé: existeix un segon directori germà, .git/refs/remotes/, amb fitxers exactament iguals.

Mirem el repositori que en Bruno va clonar a la lliçó 02-02:

find .git/refs -type f
.git/refs/heads/main
.git/refs/remotes/origin/main
.git/refs/remotes/origin/HEAD
cat .git/refs/heads/main
cat .git/refs/remotes/origin/main
c5d9b1e8a3f2b7d4c6e9a1f5b8d2c4e7a9f3b6d1
c5d9b1e8a3f2b7d4c6e9a1f5b8d2c4e7a9f3b6d1

Dos fitxers amb el mateix hash a dins. El primer és la branca main d'en Bruno; el segon és la referència remota origin/main.

L'estructura completa de referències queda així:

Directori Conté Exemple de nom
.git/refs/heads/ Les teves branques locals main, funcionalitat/exportacio-csv
.git/refs/remotes/<remot>/ Referències remotes origin/main, origin/documentacio/notes
.git/refs/tags/ Etiquetes (lliçó 05-05) v1.2.0

I, com vas veure a la lliçó 03-01, moltes d'aquestes referències poden acabar comprimides a .git/packed-refs en lloc d'existir com a fitxers solts. Es consulten igual:

git rev-parse origin/main
c5d9b1e8a3f2b7d4c6e9a1f5b8d2c4e7a9f3b6d1

git rev-parse resol qualsevol nom de referència al seu hash, sigui on sigui desada. És la manera robusta de consultar-les i la que has de fer servir en scripts.

  1. origin/main és una referència local de només lectura

Ara l'afirmació important, la que cal entendre perquè la resta del mòdul tingui sentit:

origin/main no és al servidor. És al teu disc. És una nota que Git es va deixar a si mateix dient «l'última vegada que vaig parlar amb origin, la seva branca main era en aquest commit».

Pensa-hi com en una fotografia amb data, no com en una finestra en directe. I d'aquí se'n deriven tres conseqüències que convé tenir gravades:

Primera: origin/main pot estar desactualitzat, i normalment ho està. Si en Bruno ha enviat tres commits fa deu minuts i tu no has executat cap fetch, el teu origin/main continua assenyalant el commit d'ahir. Git no té manera de saber-ho: no hi ha cap connexió oberta ni cap avís. Només se n'assabenta quan li demanes que parli amb el servidor.

Segona: només s'actualitza en moments concrets. Les referències remotes canvien quan executes git fetch, git pull (que fa un fetch per dins), git clone o un git push amb èxit. En qualsevol altre moment estan congelades.

Tercera: no hi pots treballar directament. És de només lectura des del punt de vista de la teva feina diària:

git switch origin/main
Note: switching to 'origin/main'.

You are in 'detached HEAD' state...

Git no et canvia a una branca origin/main, perquè no és una branca teva: et deixa en HEAD desacoblat damunt d'aquell commit, exactament l'estat que vas estudiar a la lliçó 03-02. I si hi confirmes, els teus commits quedaran penjant sense cap branca que els sostingui.

De la mateixa manera, no hi pots confirmar ni fusionar dins d'ella. El que sí que pots —i faràs constantment— és fer-la servir com a referència, igual que qualsevol altre nom de commit:

# Què tinc jo que el servidor no tenia l'última vegada que vaig mirar?
git log --oneline origin/main..main

# Què tenia el servidor que jo no tinc?
git log --oneline main..origin/main

# Quines diferències de contingut hi ha?
git diff origin/main main

# Crear una branca a partir d'ella
git switch -c correccio/urgent origin/main

# Fusionar el seu contingut a la meva branca actual
git merge origin/main

Tota la sintaxi de rangs i referències del mòdul 2 (.., ~, ^) funciona amb elles sense cap diferència, perquè són referències normals i corrents: només canvia el directori on viuen i qui les actualitza.

El diagrama que cal recordar

flowchart LR
    subgraph LOCAL["Repositori local d'en Bruno"]
        M["main<br/>(branca local)<br/>refs/heads/main"]
        OM["origin/main<br/>(referència remota)<br/>refs/remotes/origin/main"]
    end
    subgraph SERVER["git.exemple.cat (bare)"]
        SM["main<br/>(la branca de debò)<br/>refs/heads/main"]
    end

    M -->|"git merge origin/main<br/>(integració local)"| OM
    OM -->|"git fetch<br/>(actualitza la foto)"| SM
    M -->|"git push<br/>(envia objectes i mou la branca)"| SM

Tres coses diferents amb noms semblants: el teu main, el teu origin/main i el main del servidor. La lliçó 04-06 està dedicada íntegrament a aquesta distinció, perquè és la font de la majoria de les confusions. De moment queda't amb això: les dues primeres són al teu disc; la tercera no.

Com veure-les

# Només les referències remotes
git branch -r
  origin/HEAD -> origin/main
  origin/main
# Totes: locals i remotes
git branch -a
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/main

Aquest origin/HEAD és un extra que crea git clone: recorda quina és la branca per defecte del servidor. És el que permet escriure git log origin com a drecera de git log origin/main, i el que fa que un clon et situï a main i no a qualsevol altra branca.

  1. Convencions de nom: origin, upstream i els altres

El nom d'un remot és lliure. Pot ser origin, servidor, pepet o x. Però hi ha convencions molt assentades que convé respectar, perquè qualsevol persona que s'incorpori al projecte —o qualsevol tutorial que llegeixis— les dona per descomptades:

Nom Significat convencional Quan apareix
origin El repositori del qual vas clonar; el de referència de l'equip El posa git clone automàticament
upstream El repositori original del qual va sortir la teva còpia personal En treballar amb forks (mòdul 7)
fork La teva còpia personal, quan origin és el projecte original Convenció alternativa a l'anterior
staging, produccio Repositoris de desplegament En fluxos de desplegament per push (mòdul 10)
backup, mirall Còpia secundària del repositori Redundància

Sobre upstream convé dir-ne dues paraules ara per evitar una confusió clàssica, perquè la paraula es fa servir a Git amb dos significats completament diferents:

  1. upstream com a nom de remot: el projecte original del qual vas fer un fork. És una simple convenció de nom, sense res d'especial. Es desenvolupa a la lliçó 07-01.
  2. upstream com a branca de seguiment: la referència remota amb què està emparellada una branca local teva. Això sí que és un concepte de Git amb configuració pròpia, i és el tema de la lliçó 04-06.

Són coses diferents que comparteixen paraula. Quan llegeixis «la branca no té upstream», es refereix al segon sentit.

Recomanació pràctica: anomena origin el repositori de referència del teu equip i no et compliquis. La convenció està tan assentada que desviar-se'n només genera preguntes.

  1. Plataformes d'allotjament: què afegeixen damunt de Git

Arribats aquí convé ser taxatiu per desfer un malentès molt estès: GitHub no és Git. GitHub és una empresa que allotja repositoris Git i els afegeix serveis al voltant. Git funcionava abans que GitHub existís i funcionaria igual si desaparegués demà.

Tot el que has fet en tres mòduls, i tot el que faràs en aquest, funciona contra un repositori bare en un servidor amb SSH, sense cap plataforma pel mig. Les plataformes aporten allò que Git deliberadament no fa.

Plataforma Model Trets característics
GitHub Servei comercial; opció autoallotjada (Enterprise Server) El major ecosistema; Actions per a automatització; enorme comunitat de projectes oberts
GitLab Servei comercial; edició comunitària autoallotjable i gratuïta Plataforma DevOps completa: CI/CD, registre de contenidors, gestió d'incidències, desplegament
Gitea / Forgejo Programari lliure autoallotjat Molt lleuger (un sol binari); ideal per a servidors petits o xarxes internes
Bitbucket Servei comercial (Atlassian) Integració estreta amb Jira i la resta d'eines d'Atlassian
Codeberg Servei sense ànim de lucre damunt de Forgejo Allotjament lliure per a projectes de codi obert
SourceHut Servei comercial minimalista Flux basat en correu i pedaços, a l'estil del nucli de Linux

Què afegeix exactament una plataforma

  • Allotjament amb disponibilitat i còpies de seguretat: la màquina encesa que cap portàtil no pot ser.
  • Control d'accés: qui llegeix, qui escriu, qui administra; i branques protegides, que impedeixen reescriure main o esborrar-la.
  • Propostes de canvi (pull requests a GitHub, merge requests a GitLab): la conversa, la revisió i l'aprovació d'un conjunt de commits abans d'integrar-lo. És una capa social damunt del git merge que ja coneixes. Mòdul 7.
  • Gestió d'incidències, fites i taulers de treball.
  • Integració contínua: executar proves i desplegaments automàticament a cada enviament. Mòduls 7 i 10.
  • Interfície web: navegar pel codi, llegir l'historial, comparar branques i veure els diffs sense clonar res.
  • Documentació: README.md renderitzat, wikis, pàgines web del projecte.
  • Cerca i descobriment: trobar codi i projectes, que és el que va convertir GitHub en el que és.

El que importa per a aquest mòdul: cap d'aquests serveis no canvia com funciona fetch, push o merge. Aprendre bé Git et serveix a les sis plataformes per igual, i canviar d'una a una altra és canviar un URL.

  1. El mapa mental complet

Abans de passar a la pràctica, unifiquem tot el que hem vist en un sol esquema del recorregut que fa un commit des del teclat de l'Ana fins al disc de la Carla:

flowchart TB
    subgraph A["Ana · Ubuntu"]
        A1["Directori<br/>de treball"] -->|"git add"| A2["Índex"]
        A2 -->|"git commit"| A3["Repositori local<br/>.git/objects"]
    end

    A3 -->|"git push origin main"| S["Servidor bare<br/>git.exemple.cat"]

    subgraph C["Carla · Windows 11"]
        C3["Repositori local<br/>.git/objects<br/>+ refs/remotes/origin/main"] -->|"git merge origin/main"| C1["Directori<br/>de treball"]
    end

    S -->|"git fetch origin"| C3

Presta atenció a l'asimetria de la part inferior. El git fetch de la Carla només arriba fins al seu repositori local: actualitza origin/main i descarrega objectes, però no toca ni un fitxer del seu disc de treball. Cal un segon pas —una integració, normalment un merge— perquè la feina de l'Ana aparegui als seus fitxers. Aquesta separació en dos passos és el cor de la lliçó 04-04, i és el que distingeix fetch de pull.

I observa també el que no apareix al diagrama: res no passa sol. Cada fletxa és una ordre que algú executa.

Errors Habituals i Consells

Error 1: creure que origin és una paraula reservada de Git. No ho és: és el nom que git clone posa per defecte al remot, i podria ser qualsevol altre. A git fetch origin, la paraula origin és un nom configurat al teu .git/config, no una part de la sintaxi de l'ordre.

Error 2: pensar que origin/main consulta el servidor. És un fitxer del teu disc amb un hash a dins. Si no has fet fetch, pot portar dies desactualitzat. Quan algú et digui «doncs al servidor ja hi és», el teu primer reflex ha de ser git fetch, no discutir.

Error 3: creure que el servidor «té» el teu repositori. El teu repositori és teu i és complet al teu disc. El servidor té un altre repositori, que casualment comparteix història amb el teu. Per això pots treballar sense xarxa durant una setmana sencera.

Error 4: provar d'enviar a un repositori no bare. Si muntes el teu propi servidor amb git init en lloc de git init --bare, el primer push fallarà amb branch is currently checked out. Els repositoris que reben enviaments s'han de crear amb --bare.

Error 5: confondre la plataforma amb Git. «GitHub no em deixa fer force push a main» no és una limitació de Git, sinó una regla de branca protegida configurada a la plataforma. Distingir quina capa t'està parlant estalvia moltíssim temps depurant.

Consell 1: munta un bare local per practicar. git init --bare /tmp/servidor/projecte.git et dona un servidor real, sense comptes, sense contrasenyes i sense Internet. Tot el mòdul es pot fer així, i és la millor manera d'aprendre sense por de trencar res.

Consell 2: acostuma't a git remote -v com a primera ordre en arribar a un repositori desconegut. Juntament amb git status i git log --oneline -5, és el que et diu on ets i amb qui parles.

Consell 3: pensa sempre en «tres coses diferents». main, origin/main i el main del servidor. Tan bon punt un problema de remots et desconcerti, pregunta't de quina de les tres estàs parlant. Nou de cada deu vegades, la resposta és aquí.

Exercicis

Exercici 1: anatomia d'un repositori bare

Crea un repositori bare i un de normal a /tmp i respon amb ordres:

  1. Quines diferències hi ha en l'estructura de directoris de cadascun?
  2. Què diu core.bare a la configuració de cadascun?
  3. Què passa si executes git status dins del bare?
  4. Quant ocupa cadascun acabat de crear i per què la diferència és mínima?

Exercici 2: referències remotes al descobert

Partint d'un repositori bare amb contingut, clona'l dues vegades simulant en Bruno i la Carla. Després:

  1. Localitza al disc el fitxer de la referència origin/main de la Carla i mostra'n el contingut.
  2. Comprova que aquest hash coincideix amb el de la seva branca local main.
  3. Fes que en Bruno enviï un commit nou al bare.
  4. Sense executar fetch, comprova que l'origin/main de la Carla continua apuntant al commit antic. Explica per què.
  5. Comprova amb git rev-parse quin és l'estat real de la branca al bare.

Exercici 3: explicar-ho amb les teves paraules

La Carla s'acaba d'incorporar i t'escriu: «Aleshores, quan faig git clone, em descarrego una carpeta compartida? Si canvio alguna cosa, se n'assabenta la resta?»

Redacta una resposta d'entre 150 i 250 paraules que aclareixi: què és un remot, per què el seu repositori és complet i independent, què és origin/main i quan se sincronitza alguna cosa. Sense fer servir la paraula «màgic» i sense donar per sabut res que no s'hagi vist al curs.

Solucions

Solució 1:

mkdir -p /tmp/comparativa && cd /tmp/comparativa

git init normal
git init --bare nu.git
Initialized empty Git repository in /tmp/comparativa/normal/.git/
Initialized empty Git repository in /tmp/comparativa/nu.git/

Ja al missatge es veu la diferència: un inicialitza normal/.git/ i l'altre nu.git/ directament.

# 1. Estructura
ls -A /tmp/comparativa/normal
ls -A /tmp/comparativa/nu.git
.git

HEAD  branches  config  description  hooks  info  objects  refs

El repositori normal només conté .git; el bare té aquest mateix contingut a la seva arrel.

# 2. La marca a la configuració
git -C /tmp/comparativa/normal config core.bare
git -C /tmp/comparativa/nu.git config core.bare
false
true
# 3. git status al bare
git -C /tmp/comparativa/nu.git status
fatal: this operation must be run in a work tree

El missatge és literal: status compara el directori de treball amb l'índex, i aquí no hi ha directori de treball per comparar.

# 4. Mida
du -sh /tmp/comparativa/normal /tmp/comparativa/nu.git
44K	/tmp/comparativa/normal
44K	/tmp/comparativa/nu.git

Pràcticament idèntics: en tots dos casos el que ocupa és l'estructura buida de directoris i els fitxers de plantilla de hooks/. La diferència real apareixeria amb contingut, i tot i així seria petita: el bare només s'estalvia la còpia desplegada dels fitxers, no els objectes.

Solució 2:

# Preparar el «servidor» amb una mica de contingut
mkdir -p /tmp/practica && cd /tmp/practica
git init --bare servidor.git

# Un repositori de partida que l'alimenti
git clone servidor.git inicial
cd inicial
echo "<h1>Gestor de tasques</h1>" > index.html
git add . && git commit -m "Estructura inicial del gestor de tasques"
git push origin main
cd ..

# Els dos clons
git clone servidor.git bruno
git clone servidor.git carla
# 1. El fitxer de la referència remota de la Carla
find /tmp/practica/carla/.git/refs -type f
cat /tmp/practica/carla/.git/refs/remotes/origin/main
/tmp/practica/carla/.git/refs/heads/main
/tmp/practica/carla/.git/refs/remotes/origin/main
/tmp/practica/carla/.git/refs/remotes/origin/HEAD
4f8c2a1e9b3d7f6a2c8e4b1d9f3a7c5e2b8d6f4a

(El hash serà diferent a la teva màquina; l'important és l'estructura.)

# 2. Coincideix amb la seva branca local
git -C /tmp/practica/carla rev-parse main origin/main
4f8c2a1e9b3d7f6a2c8e4b1d9f3a7c5e2b8d6f4a
4f8c2a1e9b3d7f6a2c8e4b1d9f3a7c5e2b8d6f4a

Acabat de clonar, les dues referències assenyalen el mateix commit.

# 3. En Bruno treballa i envia
cd /tmp/practica/bruno
echo "body { font-family: sans-serif; }" > estils.css
git add . && git commit -m "Afegeix els estils base del llistat"
git push origin main
# 4. La Carla, sense fer fetch
git -C /tmp/practica/carla rev-parse origin/main
4f8c2a1e9b3d7f6a2c8e4b1d9f3a7c5e2b8d6f4a

El mateix hash d'abans. I l'explicació és exactament la idea central de la lliçó: origin/main és un fitxer al disc de la Carla que ningú no ha tocat. En Bruno ha escrit al bare, no al portàtil de la Carla. Git no té cap mecanisme d'avís: la referència només s'actualitzarà quan la Carla executi fetch o pull.

# 5. L'estat real del servidor
git -C /tmp/practica/servidor.git rev-parse main
7a2e5c8b4f1d3a9e6c2b8f4d1a7e3c9b5f2d8a6e

Un hash diferent: el commit d'en Bruno. La referència de la Carla està desactualitzada, i ho estarà fins que parli amb el servidor.

# Comprovació final: després del fetch, es posa al dia
git -C /tmp/practica/carla fetch origin
git -C /tmp/practica/carla rev-parse origin/main
7a2e5c8b4f1d3a9e6c2b8f4d1a7e3c9b5f2d8a6e

I fixa't en un detall que anticipa la lliçó 04-04: el main de la Carla continua al commit antic i els seus fitxers no han canviat. El fetch només ha actualitzat la foto.

Solució 3:

Hola, Carla. No, no és una carpeta compartida: és força millor que això.

Quan clones, no et descarregues un enllaç a alguna cosa remota, sinó una còpia completa i independent del projecte, amb tot l'historial, totes les branques i tota la base de dades d'objectes. A partir d'aquell moment pots confirmar, crear branques, fusionar-les i consultar l'historial de fa dos anys sense connexió i sense permís de ningú. El teu repositori és tan vàlid com el del servidor.

El que sí que desa el clon és d'on va venir: registra l'URL sota el nom curt origin. Això és un remot, ni més ni menys: un nom per a un URL.

Sobre si la resta se n'assabenta: no, i això és important. Res no se sincronitza automàticament. Els teus commits són només al teu disc fins que executes git push, i els dels altres no arriben fins que executes git fetch o git pull. Veuràs referències que es diuen origin/main: no són el servidor, són una nota que Git desa al teu propi disc amb l'aspecte que tenia el servidor l'última vegada que hi vas parlar. Si portes dos dies sense fer fetch, aquesta nota té dos dies d'antiguitat.

En resum: treballes en local, i decideixes tu quan enviar i quan rebre.

Conclusió

Aquesta lliçó ha construït el model mental que sosté tot el mòdul. L'essencial:

  • Un remot és un nom curt per a un URL desat a .git/config. No és una còpia sincronitzada, ni una connexió oberta, ni res obligatori. Git pot parlar amb un repositori donant-li l'URL directament; el remot només evita repetir-lo.
  • Tècnicament no hi ha servidor central. Tots els repositoris Git són iguals i complets. El repositori «de referència» ho és per acord de l'equip, i les raons per tenir-ne un són organitzatives: disponibilitat, punt d'acord, còpia de seguretat, control d'accés, automatització i direccionalitat de xarxa.
  • Un repositori bare és un repositori sense directori de treball: el contingut de .git/ a l'arrel. És la manera correcta de muntar un repositori que rep enviaments, perquè així no pot quedar en un estat incoherent. El que hi ha darrere de GitHub o GitLab és sempre un bare.
  • Les referències remotes viuen a .git/refs/remotes/ i són fitxers idèntics als de les branques locals. origin/main és una referència local de només lectura que recorda on era el remot l'última vegada que s'hi va parlar. S'actualitza només amb fetch, pull, clone o push.
  • main, origin/main i el main del servidor són tres coses diferents. Les dues primeres són al teu disc.
  • origin i upstream són convencions de nom, no paraules reservades. I compte: upstream significa a més una altra cosa —la branca de seguiment— que veurem a la lliçó 04-06.
  • Les plataformes d'allotjament afegeixen serveis damunt de Git (control d'accés, propostes de canvi, integració contínua, interfície web), però no canvien com funciona Git. Aprendre Git et serveix a totes per igual.

El que ve

Ja saps què és un remot. A la lliçó 04-02: Afegint un Repositori Remot passem a la pràctica: l'Ana publica per fi gestor-tasques. Registrarem el remot amb git remote add, inspeccionarem el que apareix amb git remote -v i git remote show, aprendrem a reanomenar-lo, eliminar-lo i canviar-li l'URL, i —sobretot— obrirem .git/config per esmicolar amb calma aquella línia fetch = +refs/heads/*:refs/remotes/origin/* que portem dos mòduls veient de reüll sense explicar. És el refspec, la peça que gairebé ningú entén i que, un cop compresa, fa que fetch i push deixin de semblar arbitraris.

Dominant Git: De Principiant a Avançat

Mòdul 1: Introducció a Git

Mòdul 2: Operacions Bàsiques de Git

Mòdul 3: Branques i Fusió

Mòdul 4: Treballant amb Repositoris Remots

Mòdul 5: Operacions Avançades de Git

Mòdul 6: Eines i Tècniques de Git

Mòdul 7: Estratègies de Col·laboració i Flux de Treball

Mòdul 8: Bones Pràctiques i Consells de Git

Mòdul 9: Resolució de Problemes i Depuració

Mòdul 10: Git al Món Real

© Copyright 2026. Tots els drets reservats