La lliçó anterior va deixar en Diego amb la seva pull request oberta i l'Ana a punt de revisar-la. Ara toca el que passa dins d'aquest canal: la revisió de codi.

Gairebé tothom revisa codi de la mateixa manera: obre la pestanya de canvis al navegador, fa scroll, deixa tres comentaris sobre noms de variables i aprova. Això no és revisar; és fullejar. Una revisió de debò exigeix entendre el problema, entendre la solució i, moltes vegades, executar el codi. I per a això cal Git, no pas un navegador.

Aquesta lliçó té dues meitats. La primera és tècnica: quines ordres fer servir per revisar bé, incloent-hi una —git range-diff— que resol un problema que tothom pateix i gairebé ningú no sap que té solució. La segona és humana: què mirar, en quin ordre, com comentar sense desmoralitzar i què fer quan dues persones no es posen d'acord. Totes dues importen igual.

Contingut

  1. Per a què serveix realment una revisió (i per a què no)
  2. El diff correcte per revisar: per què tres punts
  3. Portar la branca i examinar-la amb Git
  4. Revisar commit a commit
  5. git range-diff: què ha canviat des de la revisió anterior
  6. Revisió per correu: request-pull, format-patch i am
  7. Què mirar, per ordre de prioritat
  8. Com comentar bé
  9. La mida importa: l'efecte de la mida de la PR
  10. Aprovar, demanar canvis i gestionar els desacords

  1. Per a què serveix realment una revisió (i per a què no)

Abans de les ordres, el propòsit. Una revisió de codi persegueix tres objectius, i no són al mateix pla:

1. Detectar defectes. L'obvi. Un segon parell d'ulls troba el cas límit que no vas contemplar, la condició invertida, la variable que es llegeix abans d'assignar-se. És real, però —i això sorprèn molta gent— no és el benefici principal. Les proves automàtiques i el CI (lliçó 07-06) atrapen més defectes que qualsevol revisió humana, i ho fan sense cansar-se.

2. Difondre coneixement. Aquest sí que és el gran. Quan l'Ana revisa el canvi de la Carla a app.js, dues persones acaben entenent aquella part del codi en comptes d'una. Quan en Diego, que ve de fora, llegeix els comentaris de l'Ana, aprèn com es fan les coses en aquest projecte. La revisió és el mecanisme pel qual un equip deixa de tenir illes de coneixement on només una persona sap com funciona alguna cosa. Aquell «només en Bruno entén el mòdul de sincronització» és un risc operatiu, i la revisió és la cura barata.

3. Mantenir la coherència. Un codi on cada fitxer sembla escrit per una persona diferent és més car de mantenir que un d'uniforme, encara que les decisions individuals siguin pitjors. La revisió és on es negocia aquesta uniformitat.

I ara, per a què no serveix:

No és feina de la revisió Qui ho hauria de fer
Comprovar la indentació i el format Un formatador automàtic (Prettier, gofmt, Black)
Detectar variables sense fer servir, imports morts El linter
Executar la bateria de proves El CI (lliçó 07-06)
Comprovar el format del missatge de commit El hook commit-msg (lliçó 06-01)
Verificar que compila El CI

La regla és demolidora en la seva simplicitat: si una màquina ho pot comprovar, que ho comprovi la màquina. Cada comentari humà sobre un espai en blanc és un comentari que no s'ha dedicat a la lògica, i a sobre genera ressentiment. Si el teu equip discuteix sobre cometes simples o dobles a les revisions, el problema no són les cometes: és que falta un formatador al pre-commit.

Aquesta idea té una conseqüència directa en com es dissenya el procés: les eines automàtiques van primer, al hook local o al CI, i la revisió humana comença on elles acaben. Si el CI està en vermell, no revisis: no té sentit gastar atenció humana en una cosa que ni tan sols passa les proves.

  1. El diff correcte per revisar: per què tres punts

Aquest apartat és el cor tècnic de la lliçó, i mereix que el llegeixis a poc a poc.

L'Ana vol veure «el que ha fet en Diego». Sembla trivial. No ho és.

Recordem la situació. En Diego va partir de main al commit C3. Mentre treballava, l'equip va integrar dos commits més a main. El graf (lliçó 03-01) és aquest:

gitGraph
   commit id: "C1"
   commit id: "C2"
   commit id: "C3"
   branch correccio/reordenar
   checkout correccio/reordenar
   commit id: "D1"
   commit id: "D2"
   checkout main
   commit id: "C4"
   commit id: "C5"

Ara les dues opcions:

git diff main..correccio/reordenar (dos punts)

Els dos punts, a git diff, són decoratius: git diff A..B és exactament el mateix que git diff A B. Compara les dues puntes: l'arbre de C5 contra l'arbre de D2.

Què mostra, això? La suma de dues coses diferents:

  • Els canvis d'en Diego (D1, D2), en el seu sentit correcte.
  • Els canvis de C4 i C5, del revés — perquè des del punt de vista de C5, la branca d'en Diego «ha desfet» el que van fer l'Ana i la Carla.

El resultat és un diff contaminat. L'Ana veu línies eliminades que ella mateixa va escriure ahir i que en Diego no ha tocat mai. És soroll pur.

git diff main...correccio/reordenar (tres punts)

Els tres punts a git diff volen dir una cosa molt concreta:

git diff A...B equival a git diff $(git merge-base A B) B

És a dir: compara des de l'ancestre comú. Al nostre graf, l'ancestre comú de main i la branca d'en Diego és C3. Per tant, git diff main...correccio/reordenar compara C3 amb D2.

I això és exactament el que ha fet en Diego, i res més. Els commits C4 i C5 no hi apareixen, perquè C3 és anterior a ells.

Comprova-ho tu mateix:

# Aquestes dues ordres donen el mateix resultat
git diff main...correccio/reordenar
git diff $(git merge-base main correccio/reordenar) correccio/reordenar

La taula resum, que convé memoritzar:

Forma Què compara Quan fer-la servir
git diff A B Punta d'A contra punta de B Comparar dos estats qualssevol
git diff A..B Idèntic a l'anterior Mai; només confon
git diff A...B Ancestre comú d'A i B contra punta de B Revisar una branca

Avís important: a git log els punts volen dir una altra cosa. Aquest és un dels paranys més pesats de Git, i ja el vam esmentar a la lliçó 06-04. A git log, A..B és «els commits de B que no són a A» (el que vols per revisar) i A...B és la diferència simètrica: els commits exclusius de cada costat. És a dir, per revisar es fan servir tres punts a diff i dos punts a log. No és intuïtiu. És així.

La raó de fons és que diff opera sobre arbres (dues fotos per comparar) i log opera sobre conjunts de commits. Són operacions diferents que reutilitzen la mateixa notació amb semàntiques diferents. Una decisió històrica desafortunada, però és la que hi ha.

I aquí hi ha la connexió important: quan la plataforma t'ensenya el diff d'una pull request, t'està ensenyant el de tres punts. Per això de vegades veus al web un diff net i, en fer git diff main branca en local, hi apareixen canvis aliens. No és un error de la plataforma: és que feies servir l'ordre equivocada.

  1. Portar la branca i examinar-la amb Git

L'Ana comença per portar-se la feina d'en Diego amb la referència de PR de la lliçó anterior:

git fetch origin pull/42/head:revisio/pr-42

Amb això ja pot treballar sense canviar de branca, perquè totes les ordres d'inspecció accepten referències:

# 1. Quants commits porta i quins són?
git log --oneline main..revisio/pr-42
a7c2e91 Repinta nomes si l'ordre ha canviat
b3f1a7d Reordena la llista en marcar una tasca com a completada

Dos punts, perquè és log. Llegeix: «els commits de la branca que no són a main».

# 2. Quins fitxers toca i quant? La foto de conjunt, abans de llegir res.
git diff --stat main...revisio/pr-42
 app.js     | 24 ++++++++++++++++--------
 estils.css |  3 +++
 2 files changed, 19 insertions(+), 8 deletions(-)

Aquesta és sempre la primera ordre que cal executar. En deu segons saps si tens al davant una revisió de cinc minuts o d'una hora, i si l'abast coincideix amb el que prometia la descripció. Si la PR diu «corregeix la reordenació» i toca divuit fitxers, ja tens el teu primer comentari.

# 3. El diff complet, amb context ampli
git diff -U10 main...revisio/pr-42

L'opció -U10 (lliçó 02-05) mostra deu línies de context en comptes de tres. En una revisió és gairebé sempre el que vols: el defecte sol ser a la interacció entre el que ha canviat i el que no.

# 4. Diff ignorant canvis d'espaiat
git diff -w main...revisio/pr-42

Si algú ha reindentat una funció en modificar-la, -w (equivalent a --ignore-all-space) revela el canvi real sota el soroll. Combinat amb --word-diff, molt útil per a canvis de documentació:

git diff --word-diff main...revisio/pr-42 -- README.md
# 5. Detectar codi mogut en comptes de reescrit
git diff --color-moved=dimmed-zebra main...revisio/pr-42

--color-moved pinta d'un altre color els blocs que simplement s'han mogut de lloc, distingint-los dels que s'han escrit de nou. En una PR de refactorització, la diferència entre «ha mogut 200 línies» i «ha reescrit 200 línies» canvia del tot el que cal revisar.

I, és clar, executar-lo. Aquí és on git worktree (lliçó 06-06) es guanya el sou:

git worktree add ../revisio-42 revisio/pr-42
cd ../revisio-42
# obrir index.html, reproduir els passos de la descripció de la PR

L'Ana comprova l'errada original, aplica el canvi, comprova que desapareix. Res d'això no es veu en un diff.

  1. Revisar commit a commit

Una PR ben construïda (lliçó 07-01) té commits que expliquen una història. Aprofita-ho: revisar tres commits de cinquanta línies cadascun és moltíssim més fàcil que revisar-ne un de cent cinquanta.

# Recórrer els commits un a un, amb el seu diff
git log --reverse -p main..revisio/pr-42
  • --reverse els presenta del més antic al més recent, que és l'ordre en què es van pensar.
  • -p hi afegeix el diff de cadascun.

Per saltar entre ells sense sortir del terminal:

# Només els missatges, per fer-se el mapa
git log --reverse --format='%h %s%n%n%b' main..revisio/pr-42

# El diff d'un commit concret
git show b3f1a7d

Una altra vista molt útil: qui ha tocat abans aquestes línies. Si el canvi d'en Diego modifica una funció que en Bruno va escriure fa dues setmanes per una raó concreta, convé saber-ho abans d'aprovar:

git log -L :renderitzaLlista:app.js

I git blame amb les opcions del mòdul 6:

git blame -L 40,80 -M -C main -- app.js

Fixa't en el main del final: blame sobre la versió anterior al canvi, per entendre el context que en Diego es va trobar.

Consell de mètode. Llegeix primer la descripció de la PR, després el --stat, després els missatges dels commits, i només llavors el codi. Arribar al diff sabent què esperes trobar converteix la revisió en una verificació d'hipòtesis en comptes d'una lectura a cegues. És diverses vegades més ràpid i detecta més coses.

  1. git range-diff: què ha canviat des de la revisió anterior

Aquest apartat és la joia de la lliçó.

Situació: l'Ana va revisar la PR d'en Diego i va demanar tres canvis. En Diego els va aplicar i, a més, va fer git rebase upstream/main perquè main havia avançat. Ara envia amb --force-with-lease i la PR s'actualitza.

L'Ana torna. I es troba amb un problema real: tots els commits tenen hashos nous. El rebase els va reescriure (lliçó 05-01). La plataforma li ofereix «veure els canvis des de la teva última revisió», però sovint es rendeix amb un missatge de l'estil «l'autor ha forçat l'enviament, no es pot mostrar la comparació». L'Ana no sap si en Diego només va aplicar els seus tres suggeriments o si de passada va canviar altres coses. La seva única opció aparent és revisar-ho tot un altre cop.

git range-diff resol exactament això:

git range-diff compara dues sèries de commits i et diu, per a cadascun, si s'ha mantingut igual, si ha desaparegut, si és nou o què ha canviat a dins. És un diff de diffs.

La manera de fer-lo servir requereix haver desat la versió anterior. L'Ana, previsora, ho va fer abans d'acabar la seva primera revisió:

# A la primera revisió, l'Ana desa una referència del que va veure
git branch revisio/pr-42-v1 revisio/pr-42

Ara, després de l'actualització d'en Diego:

git fetch origin pull/42/head:revisio/pr-42-v2

# Comparar les dues versions de la sèrie
git range-diff main...revisio/pr-42-v1 main...revisio/pr-42-v2

La sintaxi amb tres punts és una drecera. La forma completa és de tres arguments i de vegades és més clara:

git range-diff <base-antiga>..<punta-antiga> <base-nova>..<punta-nova>
git range-diff C3..revisio/pr-42-v1 C7..revisio/pr-42-v2

La sortida:

1:  b3f1a7d = 1:  9e4c2a8 Reordena la llista en marcar una tasca com a completada
2:  a7c2e91 ! 2:  4f8b1d3 Repinta nomes si l'ordre ha canviat
    @@ app.js: function marcaCompletada(id) {
       const ordrePrevi = llistaOrdenada.map(t => t.id).join(',');
       actualitzaEstat(id, true);
     - if (true) {
     + if (ordrePrevi !== llistaOrdenada.map(t => t.id).join(',')) {
           renderitzaLlista();
       }
3:  -------- > 3:  7a1c5e9 Afegeix prova de reordenacio

I ara la clau: com es llegeix aquesta sortida.

Marca Significat
= El commit és equivalent: mateix contingut, encara que el hash canviï pel rebase
! El commit ha canviat; a sota es mostra el diff de les seves diferències
< El commit era a la sèrie antiga i ja no hi és
> El commit és nou a la sèrie

A l'exemple, l'Ana llegeix en cinc segons: el primer commit no ha canviat (no cal rellegir-lo), el segon ha canviat exactament en la condició que ella va demanar corregir, i n'hi ha un tercer de nou que afegeix una prova. Revisió acabada. Sense range-diff, hauria rellegit cent cinquanta línies.

Detalls pràctics que fan que funcioni millor:

# Diff de diffs acolorit i més llegible
git range-diff --creation-factor=95 main...revisio/pr-42-v1 main...revisio/pr-42-v2

--creation-factor (per defecte 60) controla quant s'han d'assemblar dos commits per considerar-los «el mateix commit modificat» en comptes de «un d'esborrat i un altre de nou». Si range-diff et mostra un munt de < i > quan esperaves !, apuja el valor.

# Fer-lo servir també sobre la teva pròpia feina, abans d'enviar
git range-diff @{u}...HEAD

Aquest ús és igual de valuós: abans de forçar l'enviament després d'un rebase, comprova que no has espatllat res sense voler. @{u} és l'upstream de la branca (lliçó 04-06), és a dir, el que hi ha publicat; HEAD és el que estàs a punt de publicar. Si surt tot = llevat del que volies canviar, endavant amb confiança. Si hi apareix un commit modificat que no esperaves, acabes de detectar un conflicte mal resolt durant el rebase.

I un tercer ús: comparar com es va aplicar una sèrie de commits en dues branques diferents, per exemple després d'un cherry-pick massiu a una branca de manteniment (lliçó 05-03).

git range-diff v2.3.0..v2.3.1 main~5..main

git range-diff existeix des de Git 2.19 (2018) i continua sent poc conegut. És probablement l'ordre amb millor relació entre el que resol i el que es fa servir. Si t'endús una sola cosa tècnica d'aquesta lliçó, que sigui aquesta.

  1. Revisió per correu: request-pull, format-patch i am

Abans que existissin les plataformes web, i encara avui en projectes com el nucli de Linux, Git, PostgreSQL o Buildroot, la revisió passa en una llista de correu. Val la pena conèixer el mecanisme per tres raons: explica d'on ve l'expressió «pull request», funciona sense dependre de cap empresa, i apareix en projectes importants amb els quals potser voldràs col·laborar.

git request-pull: la pull request original

git request-pull v2.3.0 https://git.exemple.cat/drueda/gestor-tasques.git correccio/reordenar

Els tres arguments són: el punt de partida (una etiqueta o commit que el destinatari ja té), la URL des d'on es pot portar la feina, i la branca.

La sortida és un text llest per enganxar en un correu:

The following changes since commit 3f2a91c8d4b7e0a5c9f2d6b3a8e1c4f7d0b3a6e9:

  Publica la versio 2.3.0 (2026-07-12 09:14:22 +0200)

are available in the Git repository at:

  https://git.exemple.cat/drueda/gestor-tasques.git correccio/reordenar

for you to fetch changes up to a7c2e91f4d8b1c5e9a2f7d0b3c6e9a1f4d8b1c5e:

  Repinta nomes si l'ordre ha canviat (2026-07-28 17:03:45 +0200)

----------------------------------------------------------------
Diego Rueda (2):
      Reordena la llista en marcar una tasca com a completada
      Repinta nomes si l'ordre ha canviat

 app.js     | 24 ++++++++++++++++--------
 estils.css |  3 +++
 2 files changed, 19 insertions(+), 8 deletions(-)

Això és literalment una «pull request»: un missatge que diu «fes pull d'aquí». Els botons de les plataformes automatitzen aquest correu. Ara el nom té sentit.

format-patch i am: el model del nucli

Quan el destinatari no pot o no vol fer fetch des del teu servidor, s'envien els canvis com a pedaços dins del correu mateix:

# Generar un fitxer .patch per cada commit
git format-patch main..correccio/reordenar
0001-Reordena-la-llista-en-marcar-una-tasca-com-a-complet.patch
0002-Repinta-nomes-si-l-ordre-ha-canviat.patch

Cada fitxer és un correu complet: capçaleres, autor, data, missatge del commit i el diff. Opcions habituals:

# Amb una carta de presentació (el "0000-cover-letter.patch")
git format-patch --cover-letter -o /tmp/pedacos main..correccio/reordenar

# Segona ronda després de la revisió, marcada com a v2
git format-patch -v2 --cover-letter -o /tmp/pedacos main..correccio/reordenar

La carta de presentació és l'equivalent a la descripció de la PR, i el -v2 és com s'indica que aquesta és la segona versió de la sèrie després dels comentaris rebuts. En aquests projectes, git range-diff s'inclou habitualment a la carta de presentació de la v2, perquè els revisors vegin què va canviar respecte de la v1. És precisament el flux per al qual es va dissenyar l'ordre.

De l'altre costat, qui rep els pedaços els aplica amb git am (apply mailbox):

git switch -c revisio-pedacos main
git am /tmp/pedacos/*.patch

git am crea un commit per pedaç, conservant l'autor original, la seva data i el seu missatge. Aquesta és la diferència crucial amb git apply, que només aplica els canvis al directori de treball sense crear res. Si un pedaç no aplica netament:

git am --show-current-patch=diff    # veure què falla
git am --3way                       # reintentar amb fusió a tres bandes
git am --skip                       # saltar-se aquest pedaç
git am --abort                      # cancel·lar tota la sèrie

Per enviar-los per correu existeix git send-email, que parla directament amb un servidor SMTP. No el desenvoluparem: si algun dia col·labores amb un projecte d'aquest tipus, la seva documentació explicarà la configuració concreta.

Model Canal Eina Avantatge Inconvenient
Plataforma Web Pull request Accessible, integrada amb CI Depèn d'un proveïdor
request-pull Correu + fetch git request-pull Descentralitzat, sense intermediaris Requereix servidor propi
Pedaços Correu format-patch / am No requereix cap servidor Corba d'aprenentatge alta

  1. Què mirar, per ordre de prioritat

Aquí comença la meitat humana. L'error més comú d'un revisor novell és començar pel més petit: comenta el nom d'una variable a la línia 3, s'hi embolica, i mai no arriba a adonar-se que la solució sencera està mal plantejada.

Revisa en aquest ordre, i no baixis de nivell fins a haver tancat l'anterior:

Nivell 1 — Correcció: fa el que diu?

  • Resol realment el problema descrit? L'has reproduït?
  • Casos límit: llista buida, valors nuls, textos llarguíssims, caràcters estranys?
  • Condicions de cursa, estat compartit, ordre d'esdeveniments?
  • Tractament d'errors, o el catch és buit?
  • Hi ha proves? Proven el comportament o la implementació?
  • Seguretat: entrades sense validar, dades d'usuari inserides sense escapar, secrets al codi? (mòdul 8)

Si alguna cosa falla aquí, atura't i comenta-ho. No continuïs revisant noms de variables de codi que desapareixerà.

Nivell 2 — Disseny: és la manera correcta de resoldre-ho?

  • Encaixa amb l'arquitectura existent o introdueix un patró nou sense justificació?
  • És al lloc correcte? Hauria de viure a components-ui en comptes de a app.js?
  • Duplica alguna cosa que ja existeix?
  • És més complicat del que cal? I massa genèric «per si de cas»?
  • Trenca alguna interfície de la qual depengui un altre codi?

Aquest nivell és el més valuós i el que més es descuida, perquè exigeix entendre el sistema. També és el que costa més car de corregir després: un problema de disseny detectat en revisió són dues hores; el mateix problema detectat sis mesos més tard és una refactorització.

Nivell 3 — Llegibilitat: ho entendrà algú d'aquí a un any?

  • Els noms diuen el que les coses són?
  • Hi ha comentaris on calen —el perquè, no el què— i absència de comentaris obvis?
  • Les funcions fan una sola cosa?
  • La complexitat està justificada o hi ha un if imbricat a quatre nivells?
  • Els missatges dels commits expliquen el perquè? (lliçó 08-01)

Nivell 4 — Estil: convencions

I aquí, recorda l'apartat 1: si el linter ho pot comprovar, no ho comentis. Aquest nivell hauria d'estar pràcticament buit en un projecte amb bones eines. Si no ho està, la conclusió correcta no és «cal comentar més», sinó «cal configurar el formatador».

  1. Com comentar bé

Una revisió mal escrita fa més mal que cap revisió. Quatre regles.

Regla 1: sobre el codi, no sobre la persona

En comptes de Escriu
«No has controlat el cas de llista buida» «Si tasques arriba buit, tasques[0] dóna undefined aquí»
«Això està malament» «Això falla quan el títol té cometes: es trenca l'innerHTML»
«Per què ho has fet així?» «Què t'ha portat a aquest enfocament? Ho pregunto perquè a renderitzaLlista fem servir l'altre i em pregunto si hi ha una raó»

No és qüestió de suavitzar per educació: és que la formulació centrada en el codi inclou la informació necessària per arreglar-ho, i la centrada en la persona no. «Està malament» no es pot accionar; «falla amb cometes al títol» sí.

Regla 2: distingeix el bloquejant de l'opcional

El revisor sap quins dels seus comentaris són imprescindibles i quins són preferències. L'autor no ho sap si no li ho dius. Marcar-ho explícitament estalvia moltíssima fricció, i hi ha una convenció força estesa:

Prefix Significat Bloqueja?
bloquejant: Cal arreglar-ho abans d'integrar
pregunta: No entenc alguna cosa; pot ser que estigui bé Depèn de la resposta
suggeriment: Crec que seria millor així, però és decisió teva No
nit: (de nitpick) Detall menor, agafa'l o deixa'l No
elogi: Això està ben resolt No

Exemple sobre la PR d'en Diego:

bloquejant: si `tasques` està buit, `tasques[0].id` llança una excepció
            a la línia 47. Cal la comprovació abans de l'accés.

suggeriment: `renderitzaLlista()` recorre l'array dues vegades (línies 52 i 58).
             Es podria fer en una sola passada, tot i que amb llistes de menys
             de mil elements no crec que es noti. Tu decideixes.

nit: `l` com a nom de variable a la línia 61. `llistaOrdenada`?

elogi: bona idea comparar l'ordre abans de repintar. No se m'havia
       acudit i evita el parpelleig.

L'últim punt no és farciment. Comentar el que està bé no és cortesia buida: li diu a l'autor què ha de continuar fent, i en un equip on només es comenta el dolent la revisió es viu com un càstig.

Regla 3: suggereix codi quan sigui més ràpid que explicar-ho

Les plataformes permeten proposar un canvi concret que l'autor accepta amb un clic. Si el teu comentari ocuparà tres paràgrafs explicant com reescriure quatre línies, escriu les quatre línies.

Regla 4: revisa aviat

Una PR que espera dos dies bloqueja el seu autor, acumula conflictes amb main i perd context (l'autor ja ha oblidat per què va fer el que va fer). Molts equips acorden un compromís explícit de l'estil «tota PR rep una primera resposta abans de 24 hores». El compromís és respondre, no necessàriament aprovar: un «m'ho miro demà al matí» ja desbloqueja la planificació de l'altra persona.

  1. La mida importa: l'efecte de la mida de la PR

Si d'aquesta lliçó només s'apliqués una cosa a l'equip, hauria de ser aquesta.

La capacitat d'un revisor humà no escala amb la mida del canvi: s'ensorra. Els estudis sobre revisió de codi fa dècades que apunten en la mateixa direcció, i l'experiència de qualsevol que hagi revisat molt ho confirma:

Línies canviades Què passa a la pràctica Defectes detectats
< 50 Es revisa sencera i amb atenció, en minuts Molt alta
50 – 200 Revisió sòlida i realista. El punt òptim Alta
200 – 400 Es comença bé i s'acaba en diagonal Mitjana
400 – 1000 Es revisa la primera part; la resta es fulleja Baixa
> 1000 «Em sembla bé» en quatre minuts Gairebé nul·la

Hi ha una paradoxa cruel amagada aquí: com més gran és un canvi, més risc té i menys es revisa. Una PR de mil cinc-centes línies, que és justament la que més atenció necessitaria, és la que rep una aprovació en quatre minuts perquè ningú no té el temps ni l'energia per fer-ho bé.

I hi ha un segon efecte, menys evident: el nombre de comentaris no creix amb la mida, decreix. Un revisor deixa deu comentaris en una PR de cent línies i tres en una de mil, perquè a la segona es rendeix. L'autor interpreta el silenci com una aprovació.

Què fer amb un canvi gran de debò

Alguns canvis són grans per naturalesa. Estratègies, per ordre de preferència:

  1. Trossejar en diverses PRs encadenades. Cadascuna completa, coherent i revisable per separat; cadascuna parteix de l'anterior. És més feina per a l'autor i moltíssim millor per a l'equip.
  2. Separar el mecànic del substancial. Una PR amb el reanomenament massiu o el reformatatge (revisable en dos minuts amb git diff -w) i una altra amb el canvi de comportament. I apunta el commit del reformatatge a .git-blame-ignore-revs (lliçó 06-03).
  3. Revisar commit a commit, si l'autor els va construir bé (apartat 4).
  4. Revisió en parella, en directe. Per a canvis arquitectònics grans, mitja hora de conversa ret més que dos-cents comentaris asíncrons.

I una recomanació a l'autor: si la teva PR serà inevitablement gran, avisa-ho a la descripció i suggereix un ordre de lectura. «Comença per app.js línies 40-90, que és el canvi real; la resta és propagació mecànica» estalvia mitja hora al revisor.

  1. Aprovar, demanar canvis i gestionar els desacords

Els tres veredictes

Veredicte Quan Efecte
Aprovar No hi ha res bloquejant Habilita la integració
Demanar canvis Hi ha almenys un bloquejant: Sol impedir la integració fins a resoldre'l
Comentar Has opinat però no vols decidir Neutre

Dos matisos sobre «aprovar» que eviten molta fricció:

  • Aprovar no vol dir «és perfecte», vol dir «això millora l'estat actual del projecte i no introdueix problemes». Perseguir la perfecció a cada PR paralitza l'equip i crema la gent.
  • Es pot aprovar amb comentaris menors. És la sortida sana per als nit: i els suggeriment:: aproves, l'autor decideix si aplicar-los, i ningú no espera una altra ronda de revisió per un nom de variable. Molts equips en diuen «aprovar confiant» (LGTM with nits).

Què fer amb els desacords

Els desacords tècnics són normals i sans. El que cal evitar és que s'enquistin al fil de la PR durant dies.

Protocol recomanat, per ordre:

  1. Aporta dades, no opinions. «Això és lent» no avança; «ho he mesurat amb mil tasques: 340 ms davant de 12 ms» avança.
  2. Distingeix l'important de l'estètic. Si no pots explicar quin problema real causa el que estàs criticant, probablement sigui una preferència. Marca-la com a nit: i continua.
  3. Si després de dues rondes continueu sense acord, surt del text. Una trucada de deu minuts resol el que vint comentaris no. Després, escriu la conclusió a la PR perquè quedi constància.
  4. Si continua sense resoldre's, escala amb un criteri acordat per endavant: la persona responsable d'aquella part del codi decideix, o un tercer desempata. L'important és que la regla existeixi abans del conflicte, no que s'improvisi durant.
  5. Documenta la decisió per no repetir la discussió d'aquí a tres mesos. Si és una convenció general, va al CONTRIBUTING.md; si és una decisió d'arquitectura, a un document de decisió.

I una asimetria útil que molts equips adopten: qui proposa un canvi a l'statu quo té la càrrega de la prova. Si el projecte ja fa les coses d'una manera i el revisor en prefereix una altra, el revisor hauria de justificar el canvi, no l'autor defensar el que ja hi ha. Evita que cada PR es converteixi en un referèndum sobre l'estil del projecte.

Sobre els missatges de commit

Un tipus de comentari apareix a gairebé totes les revisions: el missatge del commit no explica el perquè, no segueix el format acordat, o diu «arreglos diversos». És un comentari legítim i val la pena fer-lo —l'historial és documentació permanent— però les regles concretes de redacció són el contingut de la lliçó 08-01. Allà veurem quin format fer servir, com estructurar el cos i com enllaçar els tiquets GT-NNN que els hooks del mòdul 6 ja validen.

Errors Habituals i Consells

Error 1: fer servir git diff main branca (o main..branca) per revisar. Barreja la feina de l'autor amb el que ha avançat main des que es va separar. Tres punts: git diff main...branca.

Error 2: confondre la semàntica dels punts entre diff i log. A diff vols ...; a log vols ... És contraintuïtiu i és així.

Error 3: revisar només al navegador. Sense executar el codi, la revisió detecta errades tipogràfiques i poca cosa més. Porta't la branca amb la referència de PR i prova-la.

Error 4: començar per l'estil. Es gasta tota l'atenció en el trivial i s'aprova un disseny equivocat. Correcció, disseny, llegibilitat, estil. En aquest ordre.

Error 5: comentar el que ja comprova el linter. És soroll, genera ressentiment i revela un buit a les eines del projecte, no al codi de l'autor.

Error 6: no distingir el bloquejant de l'opcional. L'autor es queda sense saber què ha de canviar per poder integrar. Fes servir prefixos explícits.

Error 7: rellegir la PR sencera després d'un rebase de l'autor. Per a això existeix git range-diff. Desa una branca amb el que vas revisar i compara.

Error 8: aprovar una PR de mil línies en cinc minuts. És pitjor que no revisar-la, perquè genera una falsa sensació de control. Demana que es trossegi.

Error 9: convertir la revisió en una demostració de superioritat tècnica. Destrueix la disposició de l'equip a proposar canvis, que és l'actiu que la revisió pretenia protegir.

Consell 1: git diff --stat main...branca sempre primer. Deu segons que orienten tota la revisió.

Consell 2: desa una branca marcadora després de revisar. git branch revisio/pr-42-v1 revisio/pr-42. El teu jo futur t'ho agrairà quan arribi la v2.

Consell 3: git range-diff @{u}...HEAD abans de cada push --force-with-lease. Verifica que el rebase no ha trencat res. Trenta segons ben invertits.

Consell 4: -U10 i --color-moved per defecte a les revisions. Més context i distinció entre codi mogut i reescrit.

Consell 5: un worktree dedicat a revisar. git worktree add ../revisio <branca>. Revisar deixa de costar canvi de context.

Consell 6: àlies per al que repeteixes. Per exemple git config --global alias.revisar '!f() { git fetch origin pull/$1/head:revisio/pr-$1 && git diff --stat main...revisio/pr-$1; }; f' (lliçó 06-04).

Exercicis

Exercici 1: dos punts i tres punts

  1. Crea un repositori amb app.js i estils.css i tres commits a main.
  2. Crea funcionalitat/filtres des d'allà i fes dos commits que només toquin app.js.
  3. Torna a main i fes dos commits més que toquin només estils.css.
  4. Executa git diff main funcionalitat/filtres, git diff main..funcionalitat/filtres i git diff main...funcionalitat/filtres. Explica què mostra cadascun i per què el tercer és el correcte per revisar.
  5. Demostra l'equivalència de la forma de tres punts fent servir git merge-base.
  6. Executa git log --oneline main..funcionalitat/filtres i git log --oneline main...funcionalitat/filtres --left-right. Explica la diferència amb el cas de diff.

Exercici 2: revisar com l'Ana

Sobre el repositori anterior:

  1. Obtén el resum de fitxers i línies del canvi.
  2. Llista els commits de la branca amb els seus missatges complets.
  3. Recorre'ls un a un del més antic al més nou amb el seu diff.
  4. Mostra el diff complet amb deu línies de context i ignorant l'espaiat.
  5. Crea un worktree a /tmp/revisio apuntant a la branca, sense abandonar main.
  6. Esbrina qui va escriure per última vegada les línies que la branca modifica, abans del canvi.

Exercici 3: range-diff en acció

  1. Desa una referència de la branca tal com està: git branch revisio/v1 funcionalitat/filtres.
  2. Simula la resposta de l'autor a una revisió: rebasa funcionalitat/filtres sobre main, modifica una línia d'un dels commits amb un rebase interactiu (edit) i afegeix un commit nou al final.
  3. Executa git range-diff main...revisio/v1 main...funcionalitat/filtres.
  4. Identifica a la sortida quin commit és equivalent, quin ha canviat i quin és nou.
  5. Prova d'apujar --creation-factor i observa com canvia l'aparellament.
  6. Genera els pedaços de la branca amb git format-patch -v2 --cover-letter i aplica'ls en una branca nova amb git am. Comprova que l'autor original es conserva.

Solucions

Solució 1:

mkdir /tmp/practica-revisio && cd /tmp/practica-revisio
git init -qb main
printf 'const tasques = [];\n' > app.js
printf 'body { margin: 0; }\n' > estils.css
git add . && git commit -q -m "Estructura inicial"
echo "function afegeix(t) { tasques.push(t); }" >> app.js
git commit -qam "Afegeix la funcio d'alta de tasques"
echo "function esborra(i) { tasques.splice(i, 1); }" >> app.js
git commit -qam "Afegeix la funcio d'esborrat"
git switch -qc funcionalitat/filtres
echo "function filtra(f) { return tasques.filter(f); }" >> app.js
git commit -qam "Afegeix el filtratge de tasques"
echo "function comptaPendents() { return filtra(t => !t.feta).length; }" >> app.js
git commit -qam "Afegeix el comptador de pendents"
git switch -q main
echo ".tasca { padding: 8px; }" >> estils.css
git commit -qam "Estila l'element de tasca"
echo ".tasca.feta { opacity: 0.5; }" >> estils.css
git commit -qam "Atenua les tasques completades"
# 4. Les tres comparacions
git diff --stat main funcionalitat/filtres
git diff --stat main..funcionalitat/filtres
git diff --stat main...funcionalitat/filtres
 app.js     | 2 ++
 estils.css | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)
 app.js     | 2 ++
 estils.css | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)
 app.js | 2 ++
 1 file changed, 2 insertions(+)

Les dues primeres formes són idèntiques i mostren estils.css amb línies eliminades que la branca no va tocar mai: són els commits de main vistos del revés. La tercera mostra només app.js, que és el que realment va fer la branca.

# 5. Equivalència
BASE=$(git merge-base main funcionalitat/filtres)
git diff --stat "$BASE" funcionalitat/filtres     # idèntic al de tres punts
# 6. A log, la semàntica s'inverteix
git log --oneline main..funcionalitat/filtres
c9f1a2d Afegeix el comptador de pendents
7b3e0c4 Afegeix el filtratge de tasques
git log --oneline --left-right main...funcionalitat/filtres
< 4e8a1f7 Atenua les tasques completades
< 2d6c9b3 Estila l'element de tasca
> c9f1a2d Afegeix el comptador de pendents
> 7b3e0c4 Afegeix el filtratge de tasques

A log, .. dóna els commits exclusius de la branca (el que vols) i ... dóna els dels dos costats. A diff és a l'inrevés. La causa és que diff compara arbres i log selecciona conjunts de commits.

Solució 2:

# 1, 2, 3
git diff --stat main...funcionalitat/filtres
git log --format='%h %s%n%n%b' main..funcionalitat/filtres
git log --reverse -p main..funcionalitat/filtres
# 4
git diff -U10 -w main...funcionalitat/filtres
# 5
git worktree add /tmp/revisio funcionalitat/filtres
git worktree list
# 6: blame sobre la versió anterior al canvi
git blame -M -C main -- app.js

Solució 3:

# 1
git branch revisio/v1 funcionalitat/filtres

# 2. L'autor rebasa i corregeix
git switch -q funcionalitat/filtres
git rebase -q main
GIT_SEQUENCE_EDITOR="sed -i '1s/^pick/edit/'" git rebase -i main
sed -i 's/return tasques.filter(f);/return (tasques || []).filter(f);/' app.js
git commit -qam "Afegeix el filtratge de tasques" --amend
git rebase --continue
echo "function neteja() { tasques.length = 0; }" >> app.js
git commit -qam "Afegeix la neteja de la llista"
# 3
git range-diff main...revisio/v1 main...funcionalitat/filtres
1:  7b3e0c4 ! 1:  a1f4d82 Afegeix el filtratge de tasques
    @@ app.js
      function esborra(i) { tasques.splice(i, 1); }
     -function filtra(f) { return tasques.filter(f); }
     +function filtra(f) { return (tasques || []).filter(f); }
2:  c9f1a2d = 2:  5e2b7c9 Afegeix el comptador de pendents
3:  -------- > 3:  8d3a6f1 Afegeix la neteja de la llista
# 4. Lectura:
#   commit 1 -> '!' : va canviar, i es veu exactament què (la guarda `|| []`)
#   commit 2 -> '=' : equivalent, no cal rellegir-lo
#   commit 3 -> '>' : nou, cal revisar-lo sencer
# 5
git range-diff --creation-factor=95 main...revisio/v1 main...funcionalitat/filtres
# 6. Pedaços i aplicació
git format-patch -v2 --cover-letter -o /tmp/pedacos main..funcionalitat/filtres
ls /tmp/pedacos
git switch -qc revisio-pedacos main
git am /tmp/pedacos/v2-000[123]*.patch
git log --format='%h %an <%ae> %s' -3

L'autor i la data originals es conserven: això és el que distingeix git am de git apply.

Conclusió

Revisar codi bé és una habilitat, i la meitat d'aquesta habilitat és tècnica. L'essencial:

  • Una revisió serveix sobretot per difondre coneixement i mantenir la coherència; detectar defectes és important però és on menys aporta davant de les proves automàtiques. El que pot comprovar una màquina, que ho comprovi la màquina.
  • El diff correcte per revisar és git diff main...branca, amb tres punts: compara des de l'ancestre comú, no des de la punta de main, i per tant mostra només el que va fer l'autor. És el mateix que ensenyen les plataformes.
  • Compte amb l'asimetria: tres punts a diff, dos punts a log. git log --oneline main..branca per veure els commits proposats.
  • El repertori d'inspecció: --stat primer sempre, -U10 per a més context, -w per ignorar l'espaiat, --color-moved per distingir codi mogut de reescrit, --reverse -p per recórrer commit a commit, i un worktree per executar-lo de debò.
  • git range-diff compara dues versions de la mateixa sèrie de commits i marca cadascun com a igual (=), modificat (!), eliminat (<) o nou (>). Converteix una segona revisió després d'un rebase en cinc segons de feina. Fes-lo servir també sobre tu mateix abans de cada push --force-with-lease.
  • git request-pull genera el correu que va donar nom a la «pull request», i format-patch/am són el model de revisió per correu del nucli de Linux, on range-diff a la carta de presentació de la v2 és pràctica habitual.
  • Revisa per ordre: correcció → disseny → llegibilitat → estil, i no baixis de nivell sense tancar l'anterior.
  • Comenta sobre el codi, no sobre la persona; marca explícitament el bloquejant: davant del suggeriment: i el nit:; i comenta també el que està bé.
  • La mida de la PR és el factor que més determina la qualitat de la revisió. Entre 50 i 200 línies és el punt òptim; per damunt de mil, la revisió és pràcticament fictícia. Trosseja, separa el mecànic del substancial, o revisa en parella.
  • Aprovar vol dir «això millora el projecte», no «és perfecte». I tingues acordat per endavant com es desempaten els desacords.

L'equip ja sap proposar canvis i revisar-los. Però encara falta la peça de dalt: quines branques existeixen, per a què serveix cadascuna i cap a on van les propostes? En Diego obre la seva PR contra main… i si el projecte tingués una branca develop? I si calgués arreglar una errada urgent en una versió antiga que ja és en producció? Això són els fluxos de treball, i comencem pel més estructurat i clàssic de tots a la lliçó 07-03: Flux de Treball Git Flow.

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