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:

Terminal window
scoop install git

Primers passos

Configura git:

Terminal window
> git config --global init.defaultBranch main

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

Terminal window
mkdir test
cd test

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

Terminal window
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:

Terminal window
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:

Terminal window
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.

Terminal window
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:

Terminal window
git add hola.txt
git status

Perfecte!

Terminal window
Changes to be committed:
new file: hola.txt

Ara esborrem el fitxer i llestos

Terminal window
$ rm hola.txt
$ ls

Doncs el fitxer s’ha esborrat 😐

I que ha fet git al respecte?

Terminal window
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:

Terminal window
$ 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

Terminal window
$ 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:

Terminal window
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:

Terminal window
git restore hola.txt

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

Terminal window
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:

Terminal window
$ 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:

Terminal window
git config --global user.email "ddemingo@xtec.cat""
git config --global user.name "David de Mingo"
Ajuda pel professor

Per verificar que l’alumne ha fet el que havia de fer executa aquesta comanda:

Terminal window
$ git config --list
init.defaultbranch=main
user.email=ddemingo@xtec.cat
user.name=David de Mingo
...

I ja pots fer un commit:

Terminal window
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

Terminal window
git log

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

Terminal window
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:

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

I ara un altre commit:

Terminal window
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:

Terminal window
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:

Terminal window
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 …

Terminal window
cat hola.txt

És el que tu esperes:

Hola

Fes un checkout al commit 5a9a:

Terminal window
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):

Terminal window
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”

Terminal window
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):

Terminal window
git tag dilluns 5a9a
main71613975a9aa4ddilluns1d30a16dimarts

Pots veure que tenim dues etiquetes:

Terminal window
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:

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

Torna al “main”.

Terminal window
git checkout main

També pots esborrar etiquetes:

Terminal window
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:

Terminal window
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.

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

Crea una carpeta tmp on guardar fitxers temporals:

Terminal window
mkdir tmp

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

Terminal window
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

Terminal window
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 estigui a la carpeta tmp:

Terminal window

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:

Terminal window
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.

Terminal window
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:

Terminal window
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:

Terminal window
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.

Terminal window
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:

Terminal window
cat nit.txt
Terminal window
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.

Terminal window
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:

Terminal window
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:

Terminal window
cat nit.txt

I pots esborrar la branca test:

Terminal window
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