Fins ara sempre hem mirat endavant: crear el repositori, preparar canvis, confirmar-los, revisar el diff abans de registrar-lo. Aquesta lliçó canvia el sentit de la mirada. Anem a consultar el passat.

I aquí hi ha el veritable valor de Git. Desar versions no serveix de gaire si després no pots respondre preguntes com ara: quan es va introduir aquesta funció? Qui va tocar estils.css la setmana passada i per què? En quina confirmació va desaparèixer aquella línia que juraries haver escrit? Què es va fer al projecte entre dilluns i dijous?

git log les respon totes, però la seva sortida per defecte és només la punta de l'iceberg. És una ordre enormement configurable: formats compactes, gràfics, resums per fitxer, plantilles pròpies i una bateria de filtres que permeten localitzar una confirmació entre milers. En aquesta lliçó la recorrerem sencera, juntament amb git show per inspeccionar una confirmació concreta i les diferents formes de referir-se a un commit, que hem anat fent servir de passada (HEAD, HEAD~1) sense explicar-les del tot.

Contingut

  1. El repositori d'en Bruno: el nostre banc de proves
  2. git log per defecte
  3. Formats compactes: --oneline i --graph
  4. Veure què va canviar: --stat i --patch
  5. Formats personalitzats amb --pretty=format:
  6. Filtrar l'historial: quantitat, dates, autor i missatge
  7. Filtrar per ruta i la cerca «pickaxe» (-S i -G)
  8. git show: inspeccionar una confirmació
  9. Com referir-se a una confirmació
  10. Combinacions útils per al dia a dia

  1. El repositori d'en Bruno: el nostre banc de proves

Han passat uns dies des que en Bruno va clonar el projecte. L'Ana ja tenia quatre confirmacions quan ell hi va arribar, i des de llavors en Bruno n'ha fet tres més a la seva pròpia còpia. Aquest és l'historial que té al seu MacBook:

cd ~/Projectes/gestor-tasques
git log --oneline
b2e6d3f (HEAD -> main) Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 Aplica estil a les tasques completades
3d5b8e1 Afegeix el filtre de tasques pendents
c5d9b1e (origin/main, origin/HEAD) Documenta la instal·lació al README
4e7f2a9 Afegeix l'esborrat de tasques al llistat
8b6d3c2 Afegeix els estils base del llistat
1a4c8d6 Estructura inicial del gestor de tasques

Set confirmacions: les quatre de l'Ana que van arribar amb el clon i les tres que ha fet en Bruno en local. Fixa't en (origin/main): marca el punt on era el servidor quan en Bruno va clonar. Les seves tres confirmacions són per davant d'aquella marca perquè encara no les ha enviat; això és matèria del mòdul 4.

Aquest historial mixt ens anirà molt bé: té dos autors, dates diferents i canvis sobre fitxers diferents, que és justament el que necessitem per practicar els filtres.

  1. git log per defecte

git log
commit b2e6d3f8a1c5e9d2b4f7a3c6e8d1b5f9a2c4e7d3 (HEAD -> main)
Author: Bruno Salas <[email protected]>
Date:   Fri Jul 31 09:14:22 2026 +0200

    Corregeix el focus del camp després d'afegir una tasca

    En enviar el formulari el cursor es perdia i calia tornar
    a clicar al camp. Ara es retorna el focus.

commit 7c1f4a9e2b6d8f3a5c1e7b9d4f2a6c8e3b5d1f7a
Author: Bruno Salas <[email protected]>
Date:   Thu Jul 30 17:42:08 2026 +0200

    Aplica estil a les tasques completades

commit 3d5b8e1c4a7f2d9b6e3c8a1f5d2b7e4c9a6f3d8b
Author: Bruno Salas <[email protected]>
Date:   Wed Jul 29 11:05:47 2026 +0200

    Afegeix el filtre de tasques pendents

(La sortida continua; se surt del paginador amb q.)

Cada entrada té quatre elements:

Element Què és
commit <hash> El SHA complet de 40 caràcters del commit
Author Qui va escriure el canvi, amb el user.name i user.email que va configurar
Date Data d'autoria, amb zona horària
Missatge Indentat quatre espais; primera línia i cos

Un parell de precisions importants:

  • L'ordre és cronològic invers: el més recent a dalt. És el que vols el 95 % de les vegades. S'inverteix amb --reverse.
  • Author i Committer són camps diferents. Recorda del model de dades que un commit desa tots dos. Normalment coincideixen i git log només mostra el primer; se separen quan algú aplica un pedaç aliè o en fer rebase. Per veure'ls tots dos:
git log --pretty=fuller
commit b2e6d3f8a1c5e9d2b4f7a3c6e8d1b5f9a2c4e7d3 (HEAD -> main)
Author:     Bruno Salas <[email protected]>
AuthorDate: Fri Jul 31 09:14:22 2026 +0200
Commit:     Bruno Salas <[email protected]>
CommitDate: Fri Jul 31 09:14:22 2026 +0200
  • git log només mostra l'historial assolible des d'on ets. Per defecte parteix de HEAD i va seguint els enllaços als pares. Confirmacions que existeixin en altres branques no hi apareixen llevat que les demanis explícitament o facis servir --all.

  1. Formats compactes: --oneline i --graph

--oneline

git log --oneline
b2e6d3f (HEAD -> main) Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 Aplica estil a les tasques completades
3d5b8e1 Afegeix el filtre de tasques pendents
c5d9b1e (origin/main, origin/HEAD) Documenta la instal·lació al README
4e7f2a9 Afegeix l'esborrat de tasques al llistat
8b6d3c2 Afegeix els estils base del llistat
1a4c8d6 Estructura inicial del gestor de tasques

Una línia per confirmació: hash abreujat, referències que hi apunten i primera línia del missatge. És el format que més es fa servir, i explica per què aquella primera línia ha de funcionar tota sola: en aquesta vista és l'únic que es veu.

--oneline és en realitat una drecera de --pretty=oneline --abbrev-commit.

--graph

Dibuixa el graf de confirmacions amb caràcters de text:

git log --oneline --graph
* b2e6d3f (HEAD -> main) Corregeix el focus del camp després d'afegir una tasca
* 7c1f4a9 Aplica estil a les tasques completades
* 3d5b8e1 Afegeix el filtre de tasques pendents
* c5d9b1e (origin/main, origin/HEAD) Documenta la instal·lació al README
* 4e7f2a9 Afegeix l'esborrat de tasques al llistat
* 8b6d3c2 Afegeix els estils base del llistat
* 1a4c8d6 Estructura inicial del gestor de tasques

Amb una sola línia de desenvolupament, el gràfic és una columna d'asteriscs i no aporta gaire. El seu valor apareix quan hi ha branques i fusions, on mostra les bifurcacions i els punts d'unió:

*   9f3a2c1 (HEAD -> main) Fusiona la branca filtres
|\
| * 5e8b1d4 Afegeix el filtre per data
| * 2c7f9a3 Afegeix el selector de filtres
* | 8d4e6b2 Corregeix el comptador
|/
* c5d9b1e Documenta la instal·lació al README

Aquest és l'aspecte que tindrà l'historial de l'equip a partir del mòdul 3. Per veure el graf de totes les branques, no només l'actual:

git log --oneline --graph --all --decorate

--decorate mostra les referències (branques, etiquetes, HEAD) al costat de cada confirmació. A Git modern està activat per defecte al terminal, però convé conèixer-lo.

  1. Veure què va canviar: --stat i --patch

--stat: resum per fitxers

git log --stat -3
commit b2e6d3f8a1c5e9d2b4f7a3c6e8d1b5f9a2c4e7d3 (HEAD -> main)
Author: Bruno Salas <[email protected]>
Date:   Fri Jul 31 09:14:22 2026 +0200

    Corregeix el focus del camp després d'afegir una tasca

 app.js | 2 ++
 1 file changed, 2 insertions(+)

commit 7c1f4a9e2b6d8f3a5c1e7b9d4f2a6c8e3b5d1f7a
Author: Bruno Salas <[email protected]>
Date:   Thu Jul 30 17:42:08 2026 +0200

    Aplica estil a les tasques completades

 estils.css | 7 +++++++
 1 file changed, 7 insertions(+)

commit 3d5b8e1c4a7f2d9b6e3c8a1f5d2b7e4c9a6f3d8b
Author: Bruno Salas <[email protected]>
Date:   Wed Jul 29 11:05:47 2026 +0200

    Afegeix el filtre de tasques pendents

 app.js     | 18 ++++++++++++++++--
 index.html |  6 ++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

És la vista més útil per fer-se una idea ràpida de la mida i l'abast de cada canvi sense llegir el codi. Variants:

git log --shortstat -3     # només la línia de totals
git log --name-only -3     # només els noms de fitxer
git log --name-status -3   # noms amb M/A/D/R

--patch (o -p): el diff complet

git log -p -1
commit b2e6d3f8a1c5e9d2b4f7a3c6e8d1b5f9a2c4e7d3 (HEAD -> main)
Author: Bruno Salas <[email protected]>
Date:   Fri Jul 31 09:14:22 2026 +0200

    Corregeix el focus del camp després d'afegir una tasca

    En enviar el formulari el cursor es perdia i calia tornar
    a clicar al camp. Ara es retorna el focus.

diff --git a/app.js b/app.js
index 3c9d4a2..5f8b2e1 100644
--- a/app.js
+++ b/app.js
@@ -58,5 +58,6 @@ document.querySelector('#nova-tasca').addEventListener('submit', function (esdev
   if (camp.value.trim() !== '') {
     afegeixTasca(camp.value.trim());
     camp.value = '';
+    camp.focus();
   }
 });

Mostra l'historial amb el diff de cada confirmació, en el format unified diff que vas aprendre a llegir a la lliçó anterior. És la manera més completa de revisar feina, i també la més llarga: fes-la servir sempre amb un límit (-1, -5) o combinada amb un filtre.

Una combinació especialment valuosa:

git log -p -- app.js

Mostra l'evolució completa d'un sol fitxer, confirmació a confirmació, amb el diff de cadascuna. És com veure una pel·lícula del fitxer des del seu naixement.

  1. Formats personalitzats amb --pretty=format:

Quan cap dels formats predefinits no encaixa, pots dissenyar el teu amb una plantilla:

git log --pretty=format:"%h · %an · %ar · %s"
b2e6d3f · Bruno Salas · fa 5 hores · Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 · Bruno Salas · fa 20 hores · Aplica estil a les tasques completades
3d5b8e1 · Bruno Salas · fa 2 dies · Afegeix el filtre de tasques pendents
c5d9b1e · Ana Ferrer · fa 5 dies · Documenta la instal·lació al README
4e7f2a9 · Ana Ferrer · fa 7 dies · Afegeix l'esborrat de tasques al llistat
8b6d3c2 · Ana Ferrer · fa 9 dies · Afegeix els estils base del llistat
1a4c8d6 · Ana Ferrer · fa 11 dies · Estructura inicial del gestor de tasques

Els marcadors comencen per %. Aquests són els que de debò es fan servir:

Marcador Contingut Exemple
%H Hash complet b2e6d3f8a1c5e9d2b4f7a3c6e8d1b5f9a2c4e7d3
%h Hash abreujat b2e6d3f
%T / %t Hash de l'arbre (complet / abreujat) 9f4c2a8
%P / %p Hash dels pares 7c1f4a9
%an Nom de l'autor Bruno Salas
%ae Correu de l'autor [email protected]
%ad Data d'autoria Fri Jul 31 09:14:22 2026 +0200
%ar Data d'autoria relativa fa 5 hores
%as Data d'autoria curta 2026-07-31
%cn / %ce / %cd / %cr El mateix per al committer
%s Assumpte (primera línia del missatge) Corregeix el focus…
%b Cos del missatge
%d Referències (branques, etiquetes) (HEAD -> main)
%D Referències sense parèntesis HEAD -> main
%n Salt de línia
%% Un signe de percentatge literal

Afegir color

Els marcadors %C... controlen el color i fan la sortida molt més llegible:

git log --pretty=format:"%C(yellow)%h%C(reset) %C(blue)%ad%C(reset) %C(green)%an%C(reset) %s" --date=short
b2e6d3f 2026-07-31 Bruno Salas Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 2026-07-30 Bruno Salas Aplica estil a les tasques completades
3d5b8e1 2026-07-29 Bruno Salas Afegeix el filtre de tasques pendents
c5d9b1e 2026-07-26 Ana Ferrer Documenta la instal·lació al README

Colors disponibles: red, green, yellow, blue, magenta, cyan, white, i %C(auto) perquè Git decideixi. %C(reset) torna al color normal, i %C(bold …) dona negreta.

Controlar el format de la data

git log --date=short --pretty=format:"%ad %s"      # 2026-07-31
git log --date=relative --pretty=format:"%ad %s"   # fa 5 hores
git log --date=iso --pretty=format:"%ad %s"        # 2026-07-31 09:14:22 +0200
git log --date=format:"%d/%m/%Y" --pretty=format:"%ad %s"   # 31/07/2026

Un àlies que val la pena

Aquesta plantilla és un clàssic i mereix desar-se com a àlies:

git config --global alias.lg "log --graph --pretty=format:'%C(yellow)%h%C(reset)%C(auto)%d%C(reset) %s %C(dim)(%ar) <%an>%C(reset)' --abbrev-commit"
git lg -5
* b2e6d3f (HEAD -> main) Corregeix el focus del camp després d'afegir una tasca (fa 5 hores) <Bruno Salas>
* 7c1f4a9 Aplica estil a les tasques completades (fa 20 hores) <Bruno Salas>
* 3d5b8e1 Afegeix el filtre de tasques pendents (fa 2 dies) <Bruno Salas>
* c5d9b1e (origin/main, origin/HEAD) Documenta la instal·lació al README (fa 5 dies) <Ana Ferrer>
* 4e7f2a9 Afegeix l'esborrat de tasques al llistat (fa 7 dies) <Ana Ferrer>

Els àlies es desen al ~/.gitconfig amb el mecanisme que vam veure a Configurant Git, i es tracten a fons a Git Log i Àlies.

  1. Filtrar l'historial: quantitat, dates, autor i missatge

En un projecte de dos anys, git log retorna milers d'entrades. Els filtres són el que converteix l'ordre en una eina de cerca.

Per quantitat

git log -3                 # les 3 últimes
git log -n 3               # equivalent
git log --skip=3 -3        # les 3 anteriors a aquestes

Per data

git log --since="2026-07-29"
git log --after="2026-07-29"        # sinònim de --since
git log --until="2026-07-30"
git log --before="2026-07-30"       # sinònim de --until

# Combinades: una finestra temporal
git log --since="2026-07-25" --until="2026-07-30" --oneline
3d5b8e1 Afegeix el filtre de tasques pendents
c5d9b1e Documenta la instal·lació al README

Git accepta expressions en llenguatge natural (en anglès), cosa que és molt còmoda:

git log --since="2 weeks ago"
git log --since="yesterday"
git log --since="last monday"
git log --since="3 days ago" --until="1 day ago"

Per autor

git log --author="Ana" --oneline
c5d9b1e Documenta la instal·lació al README
4e7f2a9 Afegeix l'esborrat de tasques al llistat
8b6d3c2 Afegeix els estils base del llistat
1a4c8d6 Estructura inicial del gestor de tasques

El valor és una expressió regular que es busca tant al nom com al correu, així que n'hi ha prou amb un fragment:

git log --author="exemple.cat"         # tot l'equip
git log --author="Ana\|Bruno"          # qualsevol dels dos

I el filtre simètric per al confirmador:

git log --committer="Carla"

Per missatge

git log --grep="filtre" --oneline
3d5b8e1 Afegeix el filtre de tasques pendents

També és una expressió regular, i per defecte distingeix majúscules. Per ignorar-les:

git log --grep="FILTRE" -i --oneline

Diversos --grep es combinen amb O lògic per defecte; --all-match els converteix en I:

git log --grep="tasca" --grep="estil" --oneline              # qualsevol dels dos
git log --grep="tasca" --grep="estil" --all-match --oneline  # tots dos alhora

I compte amb això: quan combines filtres de tipus diferent, s'apliquen amb I lògic:

git log --author="Bruno" --since="2026-07-30" --grep="estil" --oneline
7c1f4a9 Aplica estil a les tasques completades

Confirmacions d'en Bruno, del 30 de juliol endavant, el missatge de les quals contingui «estil». Una de sola.

  1. Filtrar per ruta i la cerca «pickaxe» (-S i -G)

Per ruta

git log --oneline -- estils.css
7c1f4a9 Aplica estil a les tasques completades
8b6d3c2 Afegeix els estils base del llistat

Només les confirmacions que van modificar aquell fitxer. Igual que a git diff, el -- separa opcions de rutes i és obligatori quan el nom es podria confondre amb una branca.

Accepta directoris i patrons:

git log --oneline -- src/
git log --oneline -- "*.css"
git log --oneline -- app.js index.html

Combinat amb -p, és la millor manera d'entendre com va arribar un fitxer a ser el que és:

git log -p --follow -- estils.css

--follow segueix el fitxer a través de reanomenaments. Sense aquesta opció, l'historial es tallaria en el moment en què el fitxer va canviar de nom. Només funciona amb un fitxer alhora.

La cerca «pickaxe»: -S

Aquí arriba una de les capacitats més útils i menys conegudes de Git. -S busca les confirmacions en què va canviar el nombre d'aparicions d'una cadena. A la pràctica: quan es va introduir o es va eliminar aquell text.

git log -S "esborraTasca" --oneline
4e7f2a9 Afegeix l'esborrat de tasques al llistat

Una sola confirmació: aquella en què va aparèixer la funció. Si més endavant algú l'esborrés, aquella confirmació també hi sortiria.

Compara-ho amb --grep, que és una cosa completament diferent:

Opció Busca a Respon a
--grep="X" El missatge del commit Qui va escriure «X» en un missatge?
-S "X" El contingut dels fitxers Quan va aparèixer o desaparèixer «X» al codi?
-G "X" El contingut, per expressió regular Quins commits van tocar línies que casen amb «X»?

El cas d'ús estrella de -S és aquest: trobes al codi una línia estranya, vols saber per què hi és, i git blame només et diu qui la va tocar per última vegada. Amb -S trobes la confirmació original que la va introduir, amb el seu missatge explicatiu.

git log -S "cursor: pointer" -p --oneline -- estils.css

Mostra la confirmació on va aparèixer aquella declaració CSS, amb el seu diff. Cerca quirúrgica.

Per veure-ho amb més detall:

git log -S "focus()" --pretty=format:"%h %ad %an — %s" --date=short
b2e6d3f 2026-07-31 Bruno Salas — Corregeix el focus del camp després d'afegir una tasca

-G: la variant per expressió regular

git log -G "console\.log" --oneline

La diferència amb -S és subtil però important:

  • -S "text" troba els commits on va canviar el nombre de vegades que apareix aquell text. Si mous una línia de lloc dins del mateix fitxer, el nombre no canvia i -S no la troba.
  • -G "regex" troba tots els commits el diff dels quals conté alguna línia afegida o eliminada que casi amb l'expressió. Un moviment sí que hi apareix.

Regla pràctica: -S per a «quan es va introduir això?»; -G per a «quins commits van tocar alguna cosa semblant a això?».

Totes dues accepten --pickaxe-regex i es combinen amb la resta de filtres:

git log -S "tasques.filter" --author="Bruno" --since="1 week ago" -p

  1. git show: inspeccionar una confirmació

Quan ja has localitzat la confirmació que t'interessa, git show te l'ensenya sencera:

git show 3d5b8e1
commit 3d5b8e1c4a7f2d9b6e3c8a1f5d2b7e4c9a6f3d8b
Author: Bruno Salas <[email protected]>
Date:   Wed Jul 29 11:05:47 2026 +0200

    Afegeix el filtre de tasques pendents

diff --git a/app.js b/app.js
index 5f8b2e1..8c3a7d9 100644
--- a/app.js
+++ b/app.js
@@ -30,6 +30,9 @@ function pintaLlista() {
   const llista = document.querySelector('#llista');
   llista.innerHTML = '';
-  for (const tasca of tasques) {
+  const visibles = nomesPendents
+    ? tasques.filter(function (t) { return !t.feta; })
+    : tasques;
+  for (const tasca of visibles) {
...

Metadades i diff en una sola vista. És equivalent a git log -p -1 <commit>, però més directe.

git show és més versàtil del que sembla, perquè accepta qualsevol objecte de Git:

# Una confirmació
git show 3d5b8e1

# La confirmació actual
git show
git show HEAD

# Només el resum per fitxers
git show --stat 3d5b8e1

# Només el missatge, sense diff
git show --no-patch 3d5b8e1
git show -s 3d5b8e1                # abreujat

# Només el nom dels fitxers afectats
git show --name-only 3d5b8e1

# Un fitxer TAL COM ERA en aquella confirmació
git show 3d5b8e1:app.js

# El mateix fitxer fa tres confirmacions
git show HEAD~3:estils.css

# Un arbre (el contingut d'un directori en aquell moment)
git show 3d5b8e1^{tree}

La sintaxi <commit>:<ruta> és especialment útil. Ja la vam fer servir al mòdul anterior per comprovar quina versió d'un fitxer havia quedat registrada. Serveix, per exemple, per recuperar una versió antiga sense tocar res més:

git show 8b6d3c2:estils.css > estils-antic.css

I combinada amb -s i un format, git show serveix per extreure dades concretes:

git show -s --format="%an va escriure això el %as" HEAD
# → Bruno Salas va escriure això el 2026-07-31

  1. Com referir-se a una confirmació

Portem estona fent servir HEAD, HEAD~1 i hashos sense haver sistematitzat la notació. Tanquem-la, perquè apareix pràcticament a totes les ordres de Git.

El hash

git show b2e6d3f8a1c5e9d2b4f7a3c6e8d1b5f9a2c4e7d3    # complet
git show b2e6d3f                                     # abreujat
git show b2e6                                        # encara més curt

N'hi ha prou d'escriure un prefix inequívoc. Git necessita almenys 4 caràcters i en fa servir 7 per defecte en mostrar-los. En repositoris molt grans pot caldre'n algun més; si el prefix és ambigu, Git t'avisa:

error: short object ID b2e is ambiguous

Les referències simbòliques

Referència Significa
HEAD La confirmació on ets ara
main La confirmació a la qual apunta la branca main
origin/main L'última confirmació coneguda de main al remot
v1.0 La confirmació etiquetada com a v1.0
@ Sinònim abreujat de HEAD

Els operadors ~ i ^

Aquests dos són els que confonen, i la diferència només importa quan hi ha fusions (commits amb més d'un pare):

Notació Significa
HEAD~1 o HEAD~ El primer pare de HEAD (la confirmació anterior)
HEAD~2 El primer pare del primer pare: dues confirmacions enrere
HEAD~n n confirmacions enrere, seguint sempre el primer pare
HEAD^1 o HEAD^ El primer pare de HEAD — idèntic a HEAD~1
HEAD^2 El segon pare de HEAD (només existeix en una fusió)
HEAD^^ El pare del pare — idèntic a HEAD~2

En resum:

  • ~ recorre generacions cap enrere per la línia principal. ~3 = tres passos enrere.
  • ^ tria entre els pares d'un mateix commit. ^2 = el segon pare.

En un historial lineal com el d'en Bruno, HEAD~2 i HEAD^^ són exactament el mateix:

git rev-parse HEAD~2
# → 3d5b8e1c4a7f2d9b6e3c8a1f5d2b7e4c9a6f3d8b
git rev-parse HEAD^^
# → 3d5b8e1c4a7f2d9b6e3c8a1f5d2b7e4c9a6f3d8b

El diagrama ho aclareix:

graph RL
    C7["b2e6d3f<br/>HEAD"] --> C6["7c1f4a9<br/>HEAD~1<br/>HEAD^"]
    C6 --> C5["3d5b8e1<br/>HEAD~2<br/>HEAD^^"]
    C5 --> C4["c5d9b1e<br/>HEAD~3"]
    C4 --> C3["4e7f2a9<br/>HEAD~4"]
    C3 --> C2["8b6d3c2<br/>HEAD~5"]
    C2 --> C1["1a4c8d6<br/>HEAD~6<br/>(root-commit)"]

Les fletxes apunten cap enrere perquè així és com funciona Git: cada commit coneix el seu pare, no els seus fills. Per això és fàcil recórrer l'historial cap al passat i no existeix una notació senzilla per anar cap al futur.

I quan hi hagi fusions (mòdul 3), ^ prendrà sentit:

graph RL
    M["9f3a2c1<br/>fusió"] -->|"^1 (o ~1)"| A["8d4e6b2<br/>main"]
    M -->|"^2"| B["5e8b1d4<br/>branca filtres"]

Rangs

Dos punts defineixen un rang de confirmacions:

git log 8b6d3c2..c5d9b1e --oneline
c5d9b1e Documenta la instal·lació al README
4e7f2a9 Afegeix l'esborrat de tasques al llistat

Es llegeix com «les confirmacions assolibles des de c5d9b1e però no des de 8b6d3c2». És a dir: el que hi ha després de 8b6d3c2 fins a c5d9b1e inclòs. Fixa't que l'extrem esquerre queda fora.

Formes molt utilitzades:

git log HEAD~3..HEAD --oneline      # les 3 últimes confirmacions
git log origin/main..HEAD --oneline # el que tinc i el remot no
git log HEAD..origin/main --oneline # el que té el remot i jo no

Aquest penúltim és exactament el que en Bruno té pendent d'enviar:

git log origin/main..HEAD --oneline
b2e6d3f Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 Aplica estil a les tasques completades
3d5b8e1 Afegeix el filtre de tasques pendents

Les seves tres confirmacions locals. Tot això es desenvoluparà al mòdul 4.

Resoldre qualsevol referència

git rev-parse tradueix qualsevol notació a un hash complet, i és la manera de sortir de dubtes:

git rev-parse HEAD~3        # → c5d9b1e...
git rev-parse main          # → b2e6d3f...
git rev-parse --short HEAD  # → b2e6d3f

  1. Combinacions útils per al dia a dia

Un receptari de consultes que resolen preguntes reals:

# Què s'ha fet aquesta setmana?
git log --since="1 week ago" --oneline

# Què he fet jo aquesta setmana? (per a l'informe del divendres)
git log --author="$(git config user.name)" --since="1 week ago" --oneline

# Quantes confirmacions té el projecte?
git rev-list --count HEAD

# Qui hi ha contribuït i quant?
git shortlog -sn
      4  Ana Ferrer
      3  Bruno Salas
# Com va evolucionar aquest fitxer?
git log -p --follow -- estils.css

# Quan es va introduir aquesta cadena?
git log -S "actualitzaComptador" --oneline

# Quins fitxers toca més el projecte?
git log --name-only --pretty=format: | sort | uniq -c | sort -rn | head

# L'última confirmació que va tocar cada fitxer
git log --name-status -5

# Historial en una línia amb data i autor
git log --pretty=format:"%h %as %an %s"

# Quines confirmacions NO són al remot?
git log origin/main..HEAD --oneline

I una advertència pràctica: git log obre un paginador. Es recorre amb les fletxes o la barra espaiadora, s'hi busca amb /text i se'n surt amb q. Si prefereixes la sortida directa:

git --no-pager log --oneline -5

Errors Habituals i Consells

  • Confondre --grep amb -S. --grep busca al missatge de la confirmació; -S busca al contingut dels fitxers. Són preguntes completament diferents i és l'error més freqüent en buscar a l'historial.
  • Oblidar el -- abans d'una ruta. git log estils.css funciona si no hi ha ambigüitat, però git log main interpretarà main com una branca. Posa-hi -- sempre que puguis dubtar.
  • Esperar que git log mostri totes les branques. Per defecte només recorre l'historial assolible des de HEAD. Per veure-ho tot, --all.
  • Interpretar malament els rangs a..b. L'extrem esquerre no s'hi inclou. git log HEAD~3..HEAD retorna tres confirmacions, no quatre.
  • Fer servir ~ quan es vol ^. En un historial lineal són intercanviables, però en una fusió HEAD^2 (el segon pare) i HEAD~2 (dues generacions enrere) apunten a llocs diferents.
  • Quedar-se atrapat al paginador. Se'n surt amb q. És una de les primeres frustracions de tothom amb Git.
  • Buscar dins de git log -p a ull. Si busques on va aparèixer un text concret, -S t'ho dona en una ordre en lloc de fer-te llegir cent diffs.
  • No fer servir --follow en mirar l'historial d'un fitxer reanomenat. Veuràs un historial que «comença» al reanomenament i conclouràs erròniament que el fitxer és recent.
  • Consell: defineix l'àlies lg de l'apartat 5. El faràs servir a diari i fa l'historial molt més llegible.
  • Consell: git shortlog -sn és la manera més ràpida de saber qui treballa en un projecte que acabes de clonar. I git log --oneline -20 et dona el pols del que s'està fent ara mateix.
  • Consell: si vols exportar l'historial per a un informe, --pretty=format: combinat amb --date=short produeix línies fàcils de processar amb qualsevol full de càlcul.

Exercicis

Exercici 1: Consultes sobre l'historial de gestor-tasques

Partint de l'historial d'en Bruno tal com apareix a l'apartat 1:

b2e6d3f  Bruno  2026-07-31  Corregeix el focus del camp després d'afegir una tasca  (app.js)
7c1f4a9  Bruno  2026-07-30  Aplica estil a les tasques completades                  (estils.css)
3d5b8e1  Bruno  2026-07-29  Afegeix el filtre de tasques pendents                   (app.js, index.html)
c5d9b1e  Ana    2026-07-26  Documenta la instal·lació al README                     (README.md)
4e7f2a9  Ana    2026-07-24  Afegeix l'esborrat de tasques al llistat                (app.js)
8b6d3c2  Ana    2026-07-22  Afegeix els estils base del llistat                     (estils.css, index.html)
1a4c8d6  Ana    2026-07-20  Estructura inicial del gestor de tasques                (els 4 fitxers)

Escriu l'ordre exacta per a cada consulta i prediu-ne la sortida:

  1. Les tres últimes confirmacions, en una línia cadascuna.
  2. Totes les confirmacions de l'Ana.
  3. Tot el que s'ha fet entre el 23 i el 27 de juliol, tots dos inclosos.
  4. Les confirmacions que van tocar estils.css.
  5. Les confirmacions el missatge de les quals contingui «tasca», sense distingir majúscules.
  6. Un llistat amb format hash | data curta | autor | assumpte.
  7. Quantes confirmacions hi ha en total i quantes n'ha fet cada persona.
  8. El contingut de README.md tal com era a 4e7f2a9.

Exercici 2: La cerca pickaxe

Crea un repositori amb un historial en què una línia apareix, es mou i desapareix:

mkdir -p ~/practica/pickaxe && cd ~/practica/pickaxe
git init

printf 'function inici() {\n  return true;\n}\n' > app.js
git add app.js && git commit -m "Afegeix la funció d'inici"

printf 'function inici() {\n  console.log("DEPURACIO: entrant");\n  return true;\n}\n' > app.js
git commit -am "Afegeix la traça de depuració"

printf 'function inici() {\n  return true;\n}\n\nfunction fi() {\n  console.log("DEPURACIO: entrant");\n  return false;\n}\n' > app.js
git commit -am "Mou la traça a la funció fi i afegeix-la"

printf 'function inici() {\n  return true;\n}\n\nfunction fi() {\n  return false;\n}\n' > app.js
git commit -am "Elimina la traça de depuració"
  1. Què retorna git log --oneline -S "DEPURACIO"? Explica per què apareix cada confirmació i per què en falta alguna.
  2. Què retorna git log --oneline -G "DEPURACIO"? Compara-ho amb el resultat anterior i explica la diferència.
  3. Què retorna git log --oneline --grep="DEPURACIO"? I --grep="depuració"?
  4. Escriu l'ordre que mostri el diff de la confirmació exacta en què es va eliminar la traça.
  5. Redacta en una frase la regla que et permetrà triar entre -S, -G i --grep en el futur.

Exercici 3: Navegar per referències

Sobre el repositori de l'exercici 2 (quatre confirmacions, historial lineal):

  1. Escriu quatre formes diferents de referir-te a la segona confirmació de l'historial (la que va afegir la traça).
  2. Comprova amb git rev-parse que HEAD~2 i HEAD^^ apunten al mateix objecte.
  3. Mostra el contingut d'app.js tal com era a la primera confirmació, sense modificar el teu directori de treball.
  4. Mostra únicament els missatges de les dues últimes confirmacions, sense diff.
  5. Fes servir un rang per llistar només les dues últimes confirmacions i explica per què HEAD~2..HEAD en retorna dues i no tres.
  6. Esbrina quins fitxers va modificar cadascuna de les quatre confirmacions amb una sola ordre.

Solucions

Solució a l'Exercici 1

1. Les tres últimes:

git log --oneline -3
b2e6d3f (HEAD -> main) Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 Aplica estil a les tasques completades
3d5b8e1 Afegeix el filtre de tasques pendents

2. Les de l'Ana:

git log --author="Ana" --oneline
c5d9b1e Documenta la instal·lació al README
4e7f2a9 Afegeix l'esborrat de tasques al llistat
8b6d3c2 Afegeix els estils base del llistat
1a4c8d6 Estructura inicial del gestor de tasques

3. Entre el 23 i el 27, tots dos inclosos:

git log --since="2026-07-23" --until="2026-07-28" --oneline
c5d9b1e Documenta la instal·lació al README
4e7f2a9 Afegeix l'esborrat de tasques al llistat

Atenció al detall: --until="2026-07-27" s'interpreta com les 00:00 d'aquell dia, així que exclouria les confirmacions del mateix dia 27. Com que aquí volem incloure el dia 27 sencer, hi posem --until="2026-07-28". És un error clàssic que fa «desaparèixer» confirmacions de l'últim dia del rang.

4. Les que van tocar estils.css:

git log --oneline -- estils.css
7c1f4a9 Aplica estil a les tasques completades
8b6d3c2 Afegeix els estils base del llistat

Nota: 1a4c8d6 va crear el fitxer, així que en un historial real també hi apareixeria. A l'enunciat s'indica que la confirmació inicial contenia els quatre fitxers, de manera que la sortida completa seria de tres entrades.

5. Missatges amb «tasca», sense distingir majúscules:

git log --grep="tasca" -i --oneline
b2e6d3f Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 Aplica estil a les tasques completades
3d5b8e1 Afegeix el filtre de tasques pendents
4e7f2a9 Afegeix l'esborrat de tasques al llistat
1a4c8d6 Estructura inicial del gestor de tasques

Cinc de les set. En queden fora c5d9b1e («Documenta la instal·lació al README») i 8b6d3c2 («Afegeix els estils base del llistat»), els missatges de les quals no contenen la paraula.

6. Format personalitzat:

git log --pretty=format:"%h | %as | %an | %s"
b2e6d3f | 2026-07-31 | Bruno Salas | Corregeix el focus del camp després d'afegir una tasca
7c1f4a9 | 2026-07-30 | Bruno Salas | Aplica estil a les tasques completades
3d5b8e1 | 2026-07-29 | Bruno Salas | Afegeix el filtre de tasques pendents
c5d9b1e | 2026-07-26 | Ana Ferrer | Documenta la instal·lació al README
4e7f2a9 | 2026-07-24 | Ana Ferrer | Afegeix l'esborrat de tasques al llistat
8b6d3c2 | 2026-07-22 | Ana Ferrer | Afegeix els estils base del llistat
1a4c8d6 | 2026-07-20 | Ana Ferrer | Estructura inicial del gestor de tasques

7. Totals:

git rev-list --count HEAD
# → 7

git shortlog -sn
# →      4  Ana Ferrer
# →      3  Bruno Salas

8. El README a 4e7f2a9:

git show 4e7f2a9:README.md

Mostra el contingut del fitxer tal com era en aquella confirmació, sense tocar el directori de treball. Si el volguéssim desar a part:

git show 4e7f2a9:README.md > README-antic.md

Solució a l'Exercici 2

1. Amb -S:

git log --oneline -S "DEPURACIO"
1f4c8a2 Elimina la traça de depuració
9b3e5d7 Afegeix la traça de depuració

Dues confirmacions. -S busca canvis en el nombre d'aparicions de la cadena:

  • 9b3e5d7: va passar de 0 aparicions a 1. Va canviar → hi apareix.
  • 1f4c8a2: va passar d'1 a 0. Va canviar → hi apareix.

Hi falta 7a2d6f9 («Mou la traça a la funció fi i afegeix-la»). I aquí hi ha el matís que cal entendre: en aquella confirmació la traça es va moure d'inici() a fi(), així que continua apareixent una sola vegada. Com que el recompte no varia (1 → 1), -S la considera irrellevant i no la mostra.

2. Amb -G:

git log --oneline -G "DEPURACIO"
1f4c8a2 Elimina la traça de depuració
7a2d6f9 Mou la traça a la funció fi i afegeix-la
9b3e5d7 Afegeix la traça de depuració

Tres confirmacions. -G no compta aparicions: mira si el diff de la confirmació conté alguna línia afegida o eliminada que casi amb l'expressió. A 7a2d6f9 hi ha una línia amb DEPURACIO eliminada i una altra d'afegida, així que sí que hi apareix.

Aquesta és exactament la diferència entre totes dues opcions, i l'exercici l'aïlla en la seva forma més pura.

3. Amb --grep:

git log --oneline --grep="DEPURACIO"
# → (sense resultats)

Cap, perquè --grep busca al missatge, i cap missatge no conté la paraula en majúscules.

git log --oneline --grep="depuració"
1f4c8a2 Elimina la traça de depuració
9b3e5d7 Afegeix la traça de depuració

Dues: les que porten aquella paraula al missatge. Que coincideixin amb el resultat de -S és pura casualitat de l'exemple; es deu al fet que els missatges descriuen bé el que fan.

4. El diff de l'eliminació:

git log -p -S "DEPURACIO" --diff-filter=D --oneline

O, més directe i més llegible, localitzar el commit i mostrar-lo:

git show 1f4c8a2
commit 1f4c8a2...
    Elimina la traça de depuració

diff --git a/app.js b/app.js
@@ -4,4 +4,3 @@ function inici() {
 function fi() {
-  console.log("DEPURACIO: entrant");
   return false;
 }

Una manera robusta d'encadenar-ho, sense conèixer el hash per endavant:

git show "$(git log --format=%H -S 'DEPURACIO' -1)"

que mostra la confirmació més recent en què va canviar el recompte d'aquella cadena: precisament l'eliminació.

5. La regla:

--grep busca al missatge («qui va dir que feia això?»); -S busca quan va aparèixer o desaparèixer un text al codi («d'on va sortir aquesta línia?»); -G busca quines confirmacions van tocar línies que casen amb un patró, moviments inclosos («qui ha rondat per aquí?»).

Solució a l'Exercici 3

1. Quatre formes de referir-se a la segona confirmació (amb HEAD a la quarta):

git show 9b3e5d7      # 1. hash abreujat
git show HEAD~2       # 2. dues generacions enrere
git show HEAD^^       # 3. el pare del pare
git show HEAD~1^      # 4. el pare de l'anterior

I n'hi ha més: el hash complet, main~2, @~2… Totes resolen al mateix objecte.

2. Comprovació:

git rev-parse HEAD~2
# → 9b3e5d7f4a2c8e1b5d3f7a9c2e6b4d8f1a3c5e7b

git rev-parse HEAD^^
# → 9b3e5d7f4a2c8e1b5d3f7a9c2e6b4d8f1a3c5e7b

Hashos idèntics. En un historial lineal ~n i n símbols ^ són equivalents, perquè cada commit té un únic pare i «triar el primer pare» i «retrocedir una generació» són la mateixa operació. La diferència només emergeix a les fusions.

3. El fitxer a la primera confirmació:

git show HEAD~3:app.js
function inici() {
  return true;
}
git status -s
# → (buit: el directori de treball no s'ha tocat)

git show <commit>:<ruta> llegeix de l'historial i escriu a la sortida estàndard. No modifica res, a diferència de git restore --source=..., que sí que sobreescriuria el fitxer del disc.

4. Només els missatges de les dues últimes:

git log -2 --pretty=format:"%h %s"
1f4c8a2 Elimina la traça de depuració
7a2d6f9 Mou la traça a la funció fi i afegeix-la

O, si prefereixes la vista completa sense el diff:

git log -2 --no-patch

5. El rang:

git log HEAD~2..HEAD --oneline
1f4c8a2 Elimina la traça de depuració
7a2d6f9 Mou la traça a la funció fi i afegeix-la

Dues confirmacions, no tres, perquè l'extrem esquerre del rang queda exclòs. a..b significa «tot el que és assolible des de b que no ho sigui des d'a», i HEAD~2 és assolible des d'ell mateix, així que es descarta. La manera de llegir-ho és: «el que ha passat després de HEAD~2».

Si també volguessis incloure HEAD~2, hauries d'escriure HEAD~3..HEAD.

6. Fitxers modificats per cada confirmació:

git log --name-status --oneline
1f4c8a2 Elimina la traça de depuració
M	app.js
7a2d6f9 Mou la traça a la funció fi i afegeix-la
M	app.js
9b3e5d7 Afegeix la traça de depuració
M	app.js
4c1e8b5 Afegeix la funció d'inici
A	app.js

Les tres últimes confirmacions modifiquen app.js (M) i la primera l'afegeix (A), cosa que és coherent: era el root-commit i el fitxer no existia abans.

Conclusió

Amb aquesta lliçó tanquem el cicle bàsic de Git i el mòdul 2. Recapitulant el que hem après aquí:

  • git log recorre l'historial cap enrere des de HEAD, en ordre cronològic invers, seguint els enllaços als pares.
  • Els formats canvien completament el que veus: --oneline per a la vista de treball, --graph per a l'estructura (imprescindible tan bon punt hi hagi branques), --stat per a l'abast de cada canvi i -p per al diff complet.
  • --pretty=format: permet dissenyar la teva pròpia sortida amb marcadors com %h, %an, %ar i %s, i val la pena desar-la com a àlies.
  • Els filtres converteixen git log en un cercador: -n per quantitat, --since/--until per data, --author per persona, --grep per missatge i -- <ruta> per fitxer. Filtres de tipus diferent es combinen amb I lògic.
  • La cerca «pickaxe» és la joia amagada: -S troba quan va aparèixer o desaparèixer un text al codi, i -G quines confirmacions van tocar línies que casen amb un patró. No confonguis cap de les dues amb --grep, que mira el missatge.
  • git show inspecciona una confirmació concreta —metadades i diff— i amb la sintaxi <commit>:<ruta> recupera qualsevol fitxer tal com era en qualsevol moment del passat.
  • Referir-se a una confirmació es pot fer per hash (complet o abreujat), per referència simbòlica (HEAD, main, origin/main, una etiqueta) o per navegació relativa: ~ retrocedeix generacions i ^ tria entre pares. Els rangs a..b exclouen l'extrem esquerre.

El que portes del mòdul 2

Has recorregut el cicle complet de treball amb Git en solitari:

  1. Crear el repositori (git init) o unir-te a un d'existent (git clone).
  2. Treballar seguint el cicle editar → preparar → confirmar, amb git status com a brúixola.
  3. Triar amb precisió què entra a cada confirmació, fins i tot a nivell de fragment amb git add -p.
  4. Revisar els canvis amb git diff abans de registrar-los.
  5. Consultar el passat amb git log i git show.

Amb això ja pots fer servir Git de manera productiva en qualsevol projecte propi. Però hi ha un problema esperant.

El que ve: l'equip comença a trepitjar-se

Fixa't en la situació real en què són l'Ana i en Bruno ara mateix. Tots dos han estat treballant sobre main, cadascú al seu portàtil, sense coordinar-se. L'Ana ha afegit el comptador de tasques i el marcatge de completades; en Bruno ha afegit el filtre de pendents i ha tocat els mateixos fitxers. Cap dels dos no ha vist la feina de l'altre.

Quan intentin ajuntar tot això, es trobaran amb dues versions diferents d'app.js que han evolucionat per separat des del mateix punt de partida. I això és només amb dues persones i una setmana de feina: quan la Carla s'incorpori des de Windows i hi hagi tres línies de desenvolupament simultànies, treballar tots sobre main serà insostenible.

A més, hi ha un problema més subtil. Ara mateix, si l'Ana vol provar una idea arriscada, no té on fer-ho: qualsevol cosa que confirmi va directa a l'única línia del projecte. I si a mitja tasca urgent apareix una fallada crítica, ha d'abandonar el que està fent o confirmar-ho a mitges.

La resposta a tot això són les branques, i són la característica que va convertir Git en l'estàndard de la indústria. Al mòdul 3: Branques i Fusió veurem què és realment una branca (spoiler: ja ho saps, és un fitxer amb un hash a dins, com vam comprovar en crear el primer commit), com crear-les i moure's entre elles, com fusionar la feina de diverses persones, quines estratègies fa servir Git per fer-ho, com resoldre els conflictes quan dues persones toquen la mateixa línia, i com mantenir endreçat un repositori amb moltes branques vives.

Tot el que has après en aquest mòdul —les tres zones, l'àrea de preparació, el diff, l'historial— continua sent vàlid exactament igual. Només que a partir d'ara hi haurà més d'una línia de treball alhora.

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