Git - Bàsic

Git és un sistema de control de versions.

Introducció

Avui en dia tothom espera que facis servir un sistema de gestió de control de versions, que acostuma a ser git.

Per això les IDE ja no s’encarreguen de recuperar fitxers esborrats, o versions anteriors d’un fitxer perquè donen per suposat que estas fent servir git.

Però tu fas servir git? Més aviat no.

Instal.la git amb Windows - Scoop:

scoop install git

Primers passos

Configura git:

> git config --global init.defaultBranch main

Crea un directori test per començar a treballar, i entra en ell:

mkdir test
cd test

Crea un fitxer hola.txt, escriu alguna cosa en ell i borra el fitxer:

echo "Hola" > hola.txt
ls
rm hola.txt
ls

Et pot semblar un exercici una mica ximple, però esborrar el que no toca acostuma a passar i no és gens divertit.

Aquest cop versionem el directori amb git:

git init -b main
echo "Hola" > hola.txt
ls
rm hola.txt
ls

Pots verificar que hem tornat a perdre el fitxer perquè Git només guarda aquells fitxers que li han dit que guardi!

Tornem a començar, però aquest cop preguntem a git:

echo "Hola" > hola.txt
git status

Pots veure que git sap que el fitxer hola.txt està en la carpeta, i t’avisa que no l’està controlant.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        hola.txt

Si vols que git controli el fitxer, has de dir a git que ho faci amb la comanda git add:

git add hola.txt
git status

Perfecte!

Changes to be committed:
    	new file:   hola.txt

Ara esborrem el fitxer i llestos

$ rm hola.txt
$ ls

Doncs el fitxer s’ha esborrat 😐

I que ha fet git al respecte?

git status

Com que git ara controla tot el que passa amb el fitxer hola.txt saps que l’has esborrat.

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   hola.txt

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    hola.txt

git et dona dues opcions:

  1. Oblidar del fitxer → git rm hola.txt
  2. Restaurar el fitxer → git restore hola.txt

En aquest cas el que volem és recuperar el fitxer:

$ git restore hola.txt

Si has esborrat el fitxer, ¿com és que git el pot recuperar?

Doncs perquè quan vas fer git add hola.txt es va guardar una còpia en la carpeta .git

Si fas un ls -forece

$ ls -force

Pots veure la carpeta oculta que es va crear abans quan vas executar l’ordre git init

d--h--         20/9/2025     11:21                .git
-a----         20/9/2025     11:21             14 hola.txt

Si fas un git status

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   hola.txt

Modifica el fitxer hola.txt i mira que passa quan fas git status:

echo "Adeu" > hola.txt
git status
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   hola.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   hola.txt

Git té una còpia del fitxer hola.txt que fas afegir quan vas fer git add (té aquella versió).

També sap que no es correspon al fitxer actual (algú l’ha modificat).

Si vols recuperar la versió guardada en la carpeta .git has de fer un git restore tal com t’explica el mateix git:

git restore hola.txt

Verifica que el fitxer hola.txt s’ha restaurat amb cat hola.txt:

git restore hola.txt
cat hola.txt

Commit

El que fa molt interessant a un sistema de control de versions és que pots anar guardant els canvis un darrere l’altre i tornar enrere quan vulguis.

Si vols guardar els canvis de forma permanent has de fer un commit:

$ git commit -m "He afegit el fitxer hola.txt"
Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.

git no et deixa fer un commit!

Per fer un commit has de configurar el teu nom i correu electrònic perquè quedi constància de qui ha fet que.

I a qui li interessa això si jo ja sé qui soc?

Doncs perquè git crea el que es coneix com un repositori que es pot compartir de manera col·laborativa amb altra gent i ha de quedar constància de qui ha fet que.

Configura el teu nom i correu electrònic:

git config --global user.email "ddemingo@xtec.cat""
git config --global user.name "David de Mingo"

I ja pots fer un commit:

git commit -m "He afegit el fitxer hola.txt"
[main (root-commit) 7161397] He afegit el fitxer hola.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 hola.txt
main7161397

Si demanes a git que et mostri el log

git log

Pots veure que David de Mingo ha afegit el fitxer hola.txt al repositori.

commit 71613970c7c8829e5ff71f3d8e8c01fd6984b4d5 (HEAD -> main)
Author: David de Mingo <david@optersoft.com>
Date:   Sat Sep 20 11:34:04 2025 +0200

    He afegit el fitxer hola.txt

Suposo que encara no saps exactament de que va tot això i ho trobes poc interessant

Doncs fem un commit:

echo "Dilluns" > hola.txt
git add hola.txt
git commit -m "Ara és dilluns"
main71613975a9aa4d

I ara un altre commit:

echo "Dimarts" > hola.txt
git add hola.txt
git commit -m "Ara és dimarts"
main71613975a9aa4d1d30a16

Si fas git log pots veure totes les modificacions que s’han guardat:

commit 1d30a16b5d624a172c590b34807729cb4d49d228 (HEAD -> main)
Author: David de Mingo <david@optersoft.com>
Date:   Sat Sep 20 11:43:07 2025 +0200

    Ara és dimarts

commit 5a9aa4d9f636bf6813f97ea0b011c738decc6d63
Author: David de Mingo <david@optersoft.com>
Date:   Sat Sep 20 11:42:51 2025 +0200

    Ara és dilluns

commit 71613970c7c8829e5ff71f3d8e8c01fd6984b4d5
Author: David de Mingo <david@optersoft.com>
Date:   Sat Sep 20 11:34:04 2025 +0200

    He afegit el fitxer hola.txt

Checkout

Cada modificació (commit) tè un identificador únic tal com pots veure a la sortida de la comanda git log.

Aquest identificador és un hash criptogràfic (mira Seguretat - Criptografia)

Que haig de fer per poder veure les diferents versions del fitxer hola?

Demanar a git que restauri la versió que tu vols amb la comanda checkout:

git checkout 7161
main71613975a9aa4d1d30a16

A continuació apareix un missatge molt llarg i interessant:

Note: switching to '7161'.

You are in 'detached HEAD' state.
You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 7161397 He afegit el fitxer hola.txt

HEAD és un apuntador simbòlic a “on ets” dins de la història.

git guarda aquesta informació en el fitxer .git/HEAD:

cat .\.git\HEAD

Que com pots veure és només un identificador de commit:

71613970c7c8829e5ff71f3d8e8c01fd6984b4d5

I el contingut del fitxer …

cat hola.txt

És el que tu esperes:

Hola

Fes un checkout al commit 5a9a:

git checkout 5a9a
Previous HEAD position was 7161397 He afegit el fitxer hola.txt
HEAD is now at 5a9aa4d Ara és dilluns

Pots veure que no cal que escriguis tot l’identificador, amb els primers dígits és suficient.

I per tornar a la versió més actual pots fer servir l’identificador del commit o el de la branca (en parlem després):

git checkout main
Previous HEAD position was 5a9aa4d Ara és dilluns
Switched to branch 'main'

Tag

Això dels identificadors està molt bé pels ordinadors, però les persones fem servir noms perquè és més fàcil per nosaltres. Recordes de memòria d’algun número de telèfon?

Git permet etiquetar commits amb l’etiqueta que nosaltres vulguem.

Per exemple, pots etiquetar el commit actual amb l’etiqueta “dimarts”

git tag dimarts
main71613975a9aa4d1d30a16dimarts

I pots etiquetar el commit “Ara és dilluns” amb l’etiqueta “dilluns” (aquest cop haig d’indicar la id del commit):

git tag dilluns 5a9a
main71613975a9aa4ddilluns1d30a16dimarts

Pots veure que tenim dues etiquetes:

git tag
dilluns
dimarts

Pots veure la informació del commit etiquetat:

git show dilluns
commit 5a9aa4d9f636bf6813f97ea0b011c738decc6d63 (HEAD, tag: dilluns)
Author: David de Mingo <david@optersoft.com>
Date:   Sat Sep 20 11:42:51 2025 +0200

    Ara és dilluns

diff --git a/hola.txt b/hola.txt
index b35a5e3..8c77065 100644
Binary files a/hola.txt and b/hola.txt differ

Pots canviar de versió fent checkout del tag:

git checkout dilluns
Note: switching to 'dilluns'.
HEAD is now at 5a9aa4d Ara és dilluns

Torna al “main”.

git checkout main

També pots esborrar etiquetes:

git tag -d dilluns
git tag
dimarts

Tens més informació sobre les etiquetes en el document Basics - Tagging

Ignore

Potser et sorprendrà, però git només el fan servir els programadors

I els programadors escrivim codi que s’ha de compilar. I que vol dir compilar? Doncs que es creen nous fitxers i executables, que necessitem llibreries, etc. i que naturalment no s’han versionar!

I com pot saber git que s’ha de versionar i que no s’ha de versionar? Doncs no tè ni idea, és la teva feina!

Per això has de dir explícitament quins fitxers ha de controlar amb git add. Però també has de saber que un bon programador sempre troba la manera de fer menys per aconseguir més.

Crea dos fitxers i fes un git add –-all:

echo "Lluna blava" > lluna.txt
echo "Mar vermell" > mar.txt
git add --all

Però si ho afegim tot, potser també afegim el que no s’ha d’afegir.

Podem crear un fitxer .gitignore on indicarem tots els fitxers i carpetes que git sempre ha d’ignorar.

Crea una carpeta tmp on guardar fitxers temporals:

mkdir tmp

I a continuació crea un fitxer .gitignore on indicarem que no vols que git controli la carpeta tmp:

echo "tmp/" > .gitignore

Afegeix tots els fitxers a git i fes un commit:

git add .
git commit -m "Afegit lluna.txt i mar.txt, ignorem el directori tmp"
main71613975a9aa41d30a16dimarts5a7a09f

Fixa’t que git només controla fitxers, en cap cas directoris:

[main 5a7a09f] Afegit lluna.txt i mar.txt, ignorem el directori tmp
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 .gitignore
create mode 100644 lluna.txt
create mode 100644 mar.txt

NO FUNCIONA

echo "tmp" > .gitignore
echo "Terra groga" > tmp/terra.txt
echo "Llac blanc" > tmp/llac.txt

Si executes git status pots veure que el fitxer llac.txt no s’ha afegit a la llista de fitxers que git ha de controlar, perquè el fitxer .gitignore diu que ha d’ignorar tots els fitxers que acabin amb .txt.

Branques

I ara comencem una sessió de jardineria!

Quan fas un projecte de programació, quan fas un examen de programació, mai et surt res a la primera. Vas fent, t’equivoques, tornes enrere (has de desfer coses), intentes coses noves, etc., i tot és un galimaties.

La programació és així, i la majoria de les tasques de la teva vida diària són així.

Per poder treballar de manera segura sempre has de poder avançar des d’una posició segura a una altra posició segura.

I més important, poder tornar a una posició segura en què tot funciona.

Per això git permet crear branques de treball.

Branch

Crear una branca és molt fàcil:

git branch test

Anem a veure quantes branques tenim:

git branch
maintest71613975a9aa4d1d30a16dimarts5a7a09f

Tens dues branques, i estas en la branca main (està marcada amb *).

* main
  test

Ara mateix les dues branques (main és una branca com qualsevol altre) són iguals perquè totes dues estan apuntant al mateix commit.

git log -n 1

L’única diferència és que HEAD apunta a l’etiqueta main:

commit 5a7a09fa12cf72718870551fc0c22663e4774063 (HEAD -> main, test)
Author: David de Mingo <david@optersoft.com>
Date:   Sun Sep 21 12:09:57 2025 +0200

    Afegit lluna.txt i mar.txt, ignorem el directori tmp

El que anem a fer ara és canviar a la branca test:

git checkout test
git log -n 1
commit 5a7a09fa12cf72718870551fc0c22663e4774063 (HEAD -> test, main)
Author: David de Mingo <david@optersoft.com>
Date:   Sun Sep 21 12:09:57 2025 +0200

    Afegit lluna.txt i mar.txt, ignorem el directori tmp

Ara ja podem crear un fitxer i fer un commit:

echo "Una nit d'estiu" > nit.txt
git add nit.txt
git commit -m "Afegit nit.txt"
maintest71613975a9aa4d1d30a16dimarts5a7a09f3409713

Si tornem a la branca main pots veure que tot els commit nous de la branca test no apareixen.

git checkout main
git log -n 1
commit 5a7a09fa12cf72718870551fc0c22663e4774063 (HEAD -> main)
Author: David de Mingo <david@optersoft.com>
Date:   Sun Sep 21 12:09:57 2025 +0200

    Afegit lluna.txt i mar.txt, ignorem el directori tmp

Per tant, el fitxer nit.txt no existeix:

cat nit.txt
cat : Cannot find path 'C:\Users\david\Workspace\tmp\git\nit.txt' because it does not exist

Si volem esborrar la branca test, git ens avisa que tots els commits nous de la branca test es perdran.

git branch -d test
error: the branch 'test' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D test'
hint: Disable this message with "git config set advice.forceDeleteBranch false"

Merge

Si el que he fet en la branca test està bé i funcional puc fusionar els canvis a la branca principal:

 git merge test
maintest71613975a9aa4d1d30a16dimarts5a7a09f3409713
Updating 5a7a09f..3409713
Fast-forward
 nit.txt | Bin 0 -> 36 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 nit.txt

Ara ja tens el fitxer nit.txt a la branca principal:

cat nit.txt

I pots esborrar la branca test:

git branch -d test
main71613975a9aa4d1d30a16dimarts5a7a09f3409713
Deleted branch test (was 3409713)

De totes maneres molts alumnes no veuen la necessitat de crear una branca per una cosa tant simple.

Doncs anem a fer una activitat ben divertida (almenys pel profe 🙄).

Activitat

Els fitxers de la teva solució han de ser diferents 🤨

✅ Crea una carpeta nova (fora de la que has utilitzat fins ara), on estarà el teu petit projecte i versiona la carpeta

✅ Crea un fitxer de text amb algun contingut i fes un commit del nou fitxer.

✅ Crea una nova branca dev, canvia de branca, modifica el fitxer que has creat i fes un commit.

✅ Torna a la branca main i fes un merge de la branca dev.

✅ Fes un checkout del primer commit i verifica que és la primera versió del fitxer de text.

✅ Torna a l’últim commit.

✅ Acaba d’escriure el contingut del fitxer de text i fes un altre commit:

✅ Etiqueta el commit actual.

✅ Fes un git log per veure tot l’historial

main79d23202795960ed98c39vaca-cega
commit ed98c39581ba582f183a556487c6013071f5cfc6 (HEAD -> main, tag: vaca-cega)
Author: David de Mingo <david@optersoft.com>
Date:   Sun Sep 21 13:24:28 2025 +0200

    Estrofa completa

commit 27959606a1d0fdf0a8a208dbbd42ac9ca1075f0a
Author: David de Mingo <david@optersoft.com>
Date:   Sun Sep 21 13:13:49 2025 +0200

    Seguim amb l'estrofa

commit 79d23200d10572f857a50837accb8bffc194aee3
Author: David de Mingo <david@optersoft.com>
Date:   Sun Sep 21 13:11:32 2025 +0200

    Afegit la vaca cega