Vam tancar el mòdul 1 amb el portàtil de l'Ana a punt: Git instal·lat, la identitat configurada, init.defaultBranch valent main i l'editor llest. Tota la bastida estava muntada, però gestor-tasques continuava sent el que era el primer dia: una carpeta normal i corrent amb quatre fitxers a dins. Ni historial, ni versions, ni cap manera de tornar enrere.
En aquesta lliçó fem el pas que ho canvia tot. Amb una sola ordre, git init, aquella carpeta passa a ser un repositori: Git comença a observar-la, apareix el directori .git/ amb la base de dades d'objectes que vam estudiar a El Model de Dades de Git, i a partir d'aquí cada canvi pot quedar registrat per sempre.
Veurem què crea exactament git init, què diu git status en un repositori acabat de néixer (i per què parla de "no commits yet"), com es crea la primera confirmació del projecte, en què es diferencia arrencar de zero de convertir un projecte que ja existeix, i com desfer un git init llançat per error al lloc equivocat —una cosa que li passa a gairebé tothom alguna vegada.
Contingut
- El punt de partida: la carpeta de l'Ana
git init: l'ordre que crea el repositori- Què crea exactament dins de
.git/ git statusen un repositori acabat de crear- Què significa "No commits yet"
- La primera confirmació del projecte
- Convertir un projecte existent enfront de començar de zero
- Repositoris bare: què són i per a què serveixen
- Com desfer un
git initaccidental - Comprovacions útils abans de continuar
- El punt de partida: la carpeta de l'Ana
L'Ana treballa en Ubuntu i té el seu projecte a ~/projectes/gestor-tasques. L'ha escrit durant un parell de tardes i conté quatre fitxers:
total 16 -rw-rw-r-- 1 ana ana 486 jul 20 18:12 app.js -rw-rw-r-- 1 ana ana 312 jul 20 17:55 estils.css -rw-rw-r-- 1 ana ana 602 jul 20 18:04 index.html -rw-rw-r-- 1 ana ana 198 jul 20 18:20 README.md
El contingut és senzill. index.html munta la pàgina:
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="utf-8">
<title>Gestor de Tasques</title>
<link rel="stylesheet" href="estils.css">
</head>
<body>
<h1>Gestor de Tasques</h1>
<form id="nova-tasca">
<input type="text" id="text" placeholder="Què cal fer?">
<button type="submit">Afegeix</button>
</form>
<ul id="llista"></ul>
<script src="app.js"></script>
</body>
</html>I app.js conté la lògica mínima per afegir tasques:
// gestor-tasques — lògica principal
const tasques = [];
function afegeixTasca(text) {
tasques.push({ id: Date.now(), text: text, feta: false });
pintaLlista();
}
function pintaLlista() {
const llista = document.querySelector('#llista');
llista.innerHTML = '';
for (const tasca of tasques) {
const li = document.createElement('li');
li.textContent = tasca.text;
llista.appendChild(li);
}
}
document.querySelector('#nova-tasca').addEventListener('submit', function (esdeveniment) {
esdeveniment.preventDefault();
const camp = document.querySelector('#text');
if (camp.value.trim() !== '') {
afegeixTasca(camp.value.trim());
camp.value = '';
}
});Aquests fitxers ens acompanyaran durant tot el curs. Fixa't en un detall que importarà més endavant: no hi ha cap carpeta oculta. Comprovem-ho:
Només hi ha . (el directori actual) i .. (el pare). Ni rastre de .git. Això és el que Git anomena, amb precisió, un directori que no està sota control de versions. Si l'Ana esborrés app.js ara mateix, no hi hauria res a fer.
git init: l'ordre que crea el repositori
git init: l'ordre que crea el repositoriL'Ana se situa dins de la carpeta del projecte i executa:
Ja està. Això és tot. Analitzem el missatge amb calma, perquè cada paraula diu alguna cosa:
Initialized: s'ha creat l'estructura des de zero.empty: el repositori està buit en el sentit que no conté cap confirmació. Compte: els quatre fitxers de l'Ana continuen allà intactes. "Buit" es refereix a l'historial, no a la carpeta.- La ruta
/home/ana/projectes/gestor-tasques/.git/: t'indica exactament on ha quedat el repositori. Val la pena llegir-la sempre, perquè és la manera més ràpida de detectar que l'has executat al lloc equivocat.
Les dues maneres d'invocar-lo
| Forma | Què fa | Quan fer-la servir |
|---|---|---|
git init |
Converteix el directori actual en repositori | Ja tens una carpeta amb fitxers (el cas de l'Ana) |
git init <nom> |
Crea el directori <nom> si no existeix i l'inicialitza |
Comences un projecte de zero |
La segona forma estalvia un pas. Si l'Ana comencés un projecte nou anomenat notes-equip:
Git ha creat la carpeta i l'ha inicialitzada, però no hi ha posat res a dins: el projecte està per escriure.
Opcions que convé conèixer
# Forçar el nom de la branca inicial en aquest repositori concret
git init --initial-branch=main
git init -b main # forma abreujada
# Inicialitzar amb sortida mínima
git init --quietL'Ana no necessita -b main perquè ja va fixar init.defaultBranch=main a la seva configuració global a Configuració Inicial. Però si treballes en un equip on no tothom ho té configurat, git init -b main garanteix el mateix punt de partida per a tothom.
Nota sobre versions antigues. L'opció
-b/--initial-branchexisteix des de Git 2.28. En versions anteriors la branca inicial sempre s'anomenavamasteri no hi havia manera de canviar-la en el moment de crear el repositori. Si el teugit --versionés inferior a 2.28, aquest és un bon motiu per actualitzar.
- Què crea exactament dins de
.git/
.git/Ara sí, vegem què ha aparegut:
L'únic canvi visible és la carpeta .git. Mirem-hi dins:
Això connecta directament amb el que vam veure a El Model de Dades de Git. Repassem què és cada peça en un repositori acabat d'inicialitzar:
| Element | Què és | Estat acabat de crear |
|---|---|---|
HEAD |
Referència a la branca actual | Apunta a refs/heads/main, que encara no existeix |
config |
Configuració de nivell --local |
Només uns quants valors per defecte |
description |
Nom del repositori per a GitWeb | Text de farciment; irrellevant avui |
objects/ |
La base de dades d'objectes | Buida: sense blobs, sense trees, sense commits |
refs/ |
Branques (heads/) i etiquetes (tags/) |
Tots dos subdirectoris buits |
hooks/ |
Scripts que es disparen en certs esdeveniments | Només exemples desactivats (.sample) |
info/ |
Informació auxiliar, com ara exclude |
Pràcticament buit |
branches/ |
Directori heretat, en desús | Buit; el pots ignorar |
Fixa't en el que no hi ha: no hi ha fitxer index. L'àrea de preparació és un fitxer binari (.git/index) que Git crea la primera vegada que prepares alguna cosa. Abans d'això, senzillament no existeix.
Mirant els fitxers clau
HEAD és un fitxer de text d'una sola línia:
Diu: "la branca actual és main". Però ara mateix aquesta branca és una promesa, no un fet:
El directori és buit. main no existeix com a fitxer de referència perquè una branca és, literalment, un fitxer que conté el hash d'una confirmació, i encara no hi ha cap confirmació a la qual apuntar. Aquesta situació —HEAD apuntant a una branca inexistent— s'anomena branca òrfena o unborn branch, i es resol tota sola tan bon punt es crea el primer commit.
El config local també és curt:
Quatre valors tècnics i res més. Recorda de Configurant Git que aquest fitxer és el nivell --local, el de més precedència: la identitat de l'Ana no és aquí perquè la va posar a --global, i des d'allà s'aplica igualment.
I la base de dades d'objectes està estrictament buida:
Dos subdirectoris buits esperant el primer blob. Això il·lustra bé la idea de fons: git init no desa cap dels teus fitxers. Només prepara el magatzem. Desar és cosa de git add i git commit.
git status en un repositori acabat de crear
git status en un repositori acabat de creargit status és l'ordre que més vegades escriuràs a la teva vida. Vegem què diu ara:
On branch main No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) README.md app.js estils.css index.html nothing added to commit but untracked files present (use "git add" to track)
Quatre blocs d'informació, i tots importen:
On branch main— en quina branca ets. Coincideix amb el que vam llegir a.git/HEAD.No commits yet— l'historial és buit. Ho desenvolupem a l'apartat següent.Untracked files— els fitxers sense seguiment. Git els veu al directori de treball, però no els ha registrat mai, així que encara no formen part del projecte. És l'estat que vam presentar a Terminologia Bàsica de Git.- L'última línia — un resum: no hi ha res preparat, però sí fitxers sense seguiment.
Observa el detall que Git suggereix l'ordre següent entre parèntesis: use "git add <file>...". Git és insistentment pedagògic a la seva sortida. Llegir aquests suggeriments en lloc de saltar-se'ls escurça moltíssim la corba d'aprenentatge.
Consell. Si aquests suggeriments et resulten sorollosos quan ja dominis el flux, els pots reduir amb
git config --global advice.statusHints false. Al principi, deixa'ls.
- Què significa "No commits yet"
És una frase que confon el principiant perquè sembla dir "no has fet res", quan en realitat té un significat tècnic molt concret:
HEAD apunta a la branca main, però main no apunta a cap confirmació.
És un estat transitori i perfectament vàlid, però té conseqüències pràctiques. Moltes ordres necessiten una confirmació de referència i fallen fins que n'existeixi la primera:
No és un error teu: és que HEAD no resol a res. Tan bon punt hi hagi un commit, totes aquestes ordres funcionaran amb normalitat.
Ho podem veure amb la lampisteria que vam aprendre al mòdul 1:
Aquest diagrama resumeix l'estat del repositori de l'Ana en aquest moment:
graph LR
HEAD["HEAD"] -->|ref: refs/heads/main| MAIN["main<br/>(encara no existeix)"]
MAIN -.->|apuntarà a| C["primer commit<br/>(encara sense crear)"]
OBJ["objects/<br/>buit"]
WT["Directori de treball<br/>4 fitxers sense seguiment"]
style MAIN stroke-dasharray: 5 5
style C stroke-dasharray: 5 5
- La primera confirmació del projecte
Tanquem el cercle. A Flux de Treball Bàsic de Git i sobretot a Preparant i Confirmant Canvis veurem aquestes ordres amb tot detall; aquí les fem servir en la seva forma més simple perquè el repositori deixi d'estar buit.
Pas 1: preparar els quatre fitxers.
L'ordre no imprimeix res. En Git, el silenci significa èxit. Comprovem-ne l'efecte:
On branch main No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: README.md new file: app.js new file: estils.css new file: index.html
Els quatre fitxers han passat d'Untracked files a Changes to be committed: són a l'àrea de preparació. Cadascun apareix marcat com a new file perquè no existien en cap confirmació anterior (no n'hi ha cap).
I ara sí que existeix l'índex:
I la base de dades ja té contingut:
Quatre objectes: un blob per cada fitxer. Encara no hi ha ni arbre ni commit; això ho crea git commit.
Pas 2: confirmar.
[main (root-commit) 1a4c8d6] Estructura inicial del gestor de tasques 4 files changed, 68 insertions(+) create mode 100644 README.md create mode 100644 app.js create mode 100644 estils.css create mode 100644 index.html
Llegim la primera línia, que és la més informativa:
[main— la branca sobre la qual s'ha confirmat.(root-commit)— aquesta marca només apareix a la primera confirmació d'un historial: és un commit sense pare. Recorda del model de dades que un commit normal desa el hash del seu pare; aquest no en té cap.1a4c8d6— el hash abreujat del nou commit.- El missatge que hem escrit.
Les línies següents resumeixen què hi ha entrat: 4 fitxers, 68 línies afegides, i el mode 100644 (fitxer normal) de cadascun, exactament la notació que vam veure en estudiar els trees.
Pas 3: comprovar el resultat.
Han desaparegut tant No commits yet com la llista de fitxers. working tree clean significa que el directori de treball coincideix exactament amb l'última confirmació: no hi ha res pendent. És el missatge més tranquil·litzador de Git.
I la branca ja existeix de debò:
Un fitxer amb un hash a dins. Això és una branca en Git: ni més ni menys.
HEAD -> main indica que estem situats a la branca main i que aquesta branca apunta a aquest commit. El projecte de l'Ana ja té història.
- Convertir un projecte existent enfront de començar de zero
Els dos escenaris fan servir la mateixa ordre, però les precaucions són diferents.
| Començar de zero | Convertir projecte existent | |
|---|---|---|
| Ordre típica | git init <nom> |
cd projecte && git init |
| Estat inicial | Carpeta buida | Fitxers ja presents, sense seguiment |
| Risc principal | Cap | Confirmar brossa: dependències, secrets, binaris |
| Pas previ recomanat | Crear un README.md |
Escriure un .gitignore abans del primer git add |
| Primer commit | Gairebé buit | Tot el projecte de cop |
El risc del segon cas és real i molt freqüent. Imagina que l'Ana hagués instal·lat dependències abans d'inicialitzar el repositori:
Si fes git add . sense pensar, ficaria a l'historial milers de fitxers de node_modules/ (que es reinstal·len amb una ordre i no aporten res) i, molt pitjor, .env amb les seves claus. I com vam aprendre a El Model de Dades de Git, l'historial és immutable: treure'n un fitxer amb secrets no és "esborrar-lo", és reescriure l'historial i rotar les claus.
La regla és senzilla: en un projecte existent, escriu el .gitignore abans del primer git add. Un .gitignore mínim per al cas de l'Ana:
Amb això, git status torna a mostrar només el que interessa. Veurem els patrons, les excepcions i els casos difícils a Ignorant Fitxers amb .gitignore; de moment queda't amb la idea que aquest fitxer existeix i que el seu lloc és abans del primer commit.
Un detall important: els fitxers existents no es perden
Convé dir-ho explícitament perquè genera ansietat: git init no toca els teus fitxers. No els mou, no els modifica, no els esborra. Només crea .git/. Si executes git init en una carpeta amb feina de mesos, aquesta feina continua exactament igual un segon després. L'única cosa que canvia és que ara pots començar a versionar-la.
- Repositoris bare: què són i per a què serveixen
Existeix una variant que veuràs esmentada constantment:
Un repositori bare (nu) és un repositori sense directori de treball. No conté index.html ni app.js com a fitxers amb els quals puguis treballar: conté únicament la base de dades d'objectes i les referències, és a dir, el contingut del que en un repositori normal seria .git/, però directament a l'arrel.
Et sona? És exactament el mateix contingut que vam veure dins de .git/, però sense carpeta contenidora i sense fitxers del projecte al costat.
| Repositori normal | Repositori bare | |
|---|---|---|
| Directori de treball | Sí | No |
| Pots editar fitxers | Sí | No |
| Hi pots confirmar | Sí | No directament |
| Convenció de nom | gestor-tasques |
gestor-tasques.git |
| Ús típic | La teva còpia de treball | Servidor central compartit |
Per a què serveix: és la manera correcta de muntar el repositori "central" al qual tot l'equip envia i del qual tot l'equip descarrega. Quan clones de GitHub o GitLab, el que hi ha a l'altra banda és un repositori bare. Es fa així perquè, si el repositori central tingués directori de treball, rebre canvis el podria deixar en un estat incoherent respecte del que hi hagués als seus fitxers.
No ho desenvolupem més aquí: els repositoris bare cobren sentit quan parlem de remots al mòdul 4. Queda't amb la definició —repositori sense còpia de treball, pensat per compartir— i amb el fet que a la lliçó següent en Bruno clonarà precisament d'un.
- Com desfer un
git init accidental
git init accidentalLi passa a tothom: executes git init, mires el missatge i descobreixes una ruta que no esperaves. El cas clàssic:
Acabes de convertir tota la teva carpeta personal en un repositori. git status intentarà llistar desenes de milers de fitxers sense seguiment i, encara pitjor, qualsevol projecte que tinguis a dins començarà a comportar-se de manera estranya, perquè Git busca el .git més proper cap amunt i ara troba aquest.
La solució és tranquil·litzadora per la seva simplicitat: esborrar la carpeta .git.
En Windows, des de PowerShell:
Això és tot. Com que git init no havia fet res més que crear aquesta carpeta, esborrar-la retorna el sistema exactament a com estava. Els teus fitxers no en resulten afectats en absolut.
Precaucions abans d'esborrar
Aquí convé anar amb compte, perquè rm -rf .git és inofensiu en un repositori acabat d'inicialitzar i catastròfic en un amb historial: esborraries tots els commits, branques i etiquetes, i no hi hauria manera de recuperar-los (llevat que existeixi una còpia en un altre lloc). Abans d'executar-lo, fes-te tres preguntes:
1. Sóc on em penso que sóc?
2. Quin és el repositori que vaig a esborrar?
Aquesta ordre retorna l'arrel del repositori actual, que és justament el que eliminaràs. Si la ruta no és la que esperaves, no esborris res encara.
3. Té historial?
Si respon does not have any commits yet, esborrar és segur. Si llista confirmacions, atura't i esbrina quin repositori és abans de tocar res.
Com evitar-ho la propera vegada
- Llegeix sempre la ruta del missatge d'
Initialized.... Un segon d'atenció evita el problema sencer. - Prefereix
git init <nom>quan comencis de zero: crea la carpeta ell mateix, així que no et pots equivocar de lloc. - Comprova abans d'inicialitzar si ja ets dins d'un repositori:
Aquest fatal és, en aquest cas, la resposta que vols: significa que no ets dins de cap repositori i que git init en crearà un de nou de debò.
Un avís sobre repositoris imbricats. Si executes
git initdins d'una carpeta que ja està sota control de versions, Git no protesta: crees un repositori dins d'un altre. El repositori interior queda invisible per a l'exterior i sol acabar en confusió i feina perduda. Si de debò necessites imbricar projectes, l'eina correcta són els submòduls, no ungit inita mà.
- Comprovacions útils abans de continuar
Un grapat d'ordres de diagnòstic que convé tenir a mà:
# Sóc dins d'un repositori?
git rev-parse --is-inside-work-tree # → true
# Quina és l'arrel del repositori?
git rev-parse --show-toplevel # → /home/ana/projectes/gestor-tasques
# On és el directori .git?
git rev-parse --git-dir # → .git
# És un repositori bare?
git rev-parse --is-bare-repository # → false
# En quina branca sóc?
git branch --show-current # → main
# Amb quina identitat confirmaré aquí?
git config user.name && git config user.emailAquesta última és especialment valuosa quan fas servir perfils condicionals amb includeIf, com vam veure al final de Configurant Git: et confirma quina identitat s'aplicarà en aquest repositori concret abans de crear una confirmació amb el correu equivocat.
Errors Habituals i Consells
- Executar
git initsense mirar on ets. És l'error número u. Llegeix la ruta del missatge de confirmació; si no és l'esperada, esborra.gitimmediatament abans d'afegir-hi res. - Creure que
git initja desa els fitxers. No desa res. Un repositori acabat d'inicialitzar té la base de dades buida i tots els teus fitxers en estat untracked. Fins al primergit commitno hi ha cap còpia de seguretat de res. - Fer
git add .com a primera ordre en un projecte existent. Sense.gitignore, arrossegaràs dependències, fitxers temporals, binaris de compilació i, en el pitjor dels casos, secrets. Escriu primer el.gitignorei revisagit statusabans de preparar. - Confondre "repositori buit" amb "carpeta buida". El missatge
Initialized empty Git repositoryalarma molta gent que tem haver perdut la seva feina. "Buit" es refereix a l'historial, no als fitxers. - Inicialitzar un repositori dins d'un altre. Git ho permet en silenci i el resultat és desconcertant. Comprova-ho abans amb
git rev-parse --show-toplevel. - No confirmar res durant dies. Un repositori sense commits no et protegeix de res. La primera confirmació, encara que sigui imperfecta, ja és una xarxa de seguretat.
- Consell: acostuma't que el primer commit d'un projecte s'anomeni alguna cosa com ara "Estructura inicial del projecte". És la convenció més estesa i ajuda a localitzar l'origen de l'historial d'un cop d'ull.
- Consell: si tens dubtes sobre si una carpeta és un repositori,
ls -aen Linux/macOS odir /aen Windows t'ho diu en un segon: si hi apareix.git, ho és.
Exercicis
Exercici 1: Crear un repositori de zero i observar-lo
Crea un repositori nou anomenat notes-equip sense fer servir mkdir, i respon amb ordres —no de memòria— a aquestes quatre preguntes:
- A quina branca apunta
HEAD? - Existeix ja aquesta branca com a fitxer a
refs/heads? - Quants objectes hi ha a la base de dades?
- Existeix el fitxer
.git/index?
Després crea un README.md amb una línia de text, fes la primera confirmació i torna a respondre les quatre preguntes. Explica què ha canviat i per què.
Exercici 2: Convertir un projecte existent sense ficar-hi brossa
Prepara aquesta situació de partida:
mkdir -p ~/practica/botiga-online/node_modules/llibreria
cd ~/practica/botiga-online
echo "<h1>Botiga</h1>" > index.html
echo "body { margin: 0; }" > estils.css
echo "API_KEY=abc123secret" > .env
echo "soroll" > node_modules/llibreria/index.js
echo "error de dijous" > depuracio.logConverteix la carpeta en repositori i fes un primer commit que contingui exclusivament index.html, estils.css i el .gitignore. Demostra amb la sortida de git status que .env, node_modules/ i depuracio.log no apareixen ni tan sols com a fitxers sense seguiment.
Exercici 3: Diagnosticar i reparar un git init accidental
Un company t'escriu: "he executat git init no sé on i ara git status triga moltíssim i em llista milers de fitxers que no són del meu projecte. A més, quan entro a la meva carpeta ~/projectes/api-clients i faig git log, em diu que no hi ha confirmacions, quan jo sé que en porto vint."
- Què ha passat, exactament?
- Quines ordres ha d'executar per confirmar el diagnòstic abans de tocar res?
- Com ho arregla sense perdre l'historial d'
api-clients? - Per què
git logaapi-clientsdeia que no hi havia confirmacions si el.gitd'aquest projecte continuava intacte?
Solucions
Solució a l'Exercici 1
Estat inicial:
cat .git/HEAD
# → ref: refs/heads/main
ls .git/refs/heads
# → (buit)
find .git/objects -type f | wc -l
# → 0
ls .git/index
# → ls: cannot access '.git/index': No such file or directoryRespostes: (1) HEAD apunta a refs/heads/main; (2) no, la branca encara no existeix; (3) zero objectes; (4) no existeix l'índex.
Després de la primera confirmació:
echo "# Notes de l'equip" > README.md
git add README.md
git commit -m "Estructura inicial del projecte"[main (root-commit) 3f7b2e9] Estructura inicial del projecte 1 file changed, 1 insertion(+) create mode 100644 README.md
cat .git/HEAD
# → ref: refs/heads/main (sense canvis)
cat .git/refs/heads/main
# → 3f7b2e9c1a5d8b4f2e6a9c3d7b1f5e8a4c2d9b6f (ara sí que existeix)
find .git/objects -type f | wc -l
# → 3
ls .git/index
# → .git/index (ara sí que existeix)Què ha canviat i per què:
HEADcontinua igual. Sempre apuntava amain; el que faltava era la branca, no la referència.mainja existeix com a fitxer amb un hash a dins: el commit ha donat a la branca alguna cosa a la qual apuntar. Aquí es veu literalment que una branca és un fitxer de text amb un hash.- Hi ha 3 objectes, no 1. Són els tres objectes que exigeix el model de dades de 01-04: un blob amb el contingut de
README.md, un tree amb el directori arrel (una entrada: el nomREADME.mdi el hash del blob) i un commit que apunta a aquest tree i no té pare. .git/indexexisteix perquègit addel va crear en preparar el fitxer.
Solució a l'Exercici 2
L'ordre dels passos és el que resol l'exercici: primer el .gitignore, després git add.
Abans de preparar res, escrivim les exclusions:
Comprovació:
.env, node_modules/ i depuracio.log han desaparegut de la llista: Git els veu al disc però els ignora, així que ni tan sols els compta com a untracked. Aquesta és la demostració que demanava l'enunciat.
Ara ja és segur preparar-ho tot:
[main (root-commit) 8c2f5a1] Estructura inicial de la botiga 3 files changed, 5 insertions(+) create mode 100644 .gitignore create mode 100644 estils.css create mode 100644 index.html
Tres fitxers, els tres correctes.
Si algú hagués fet git add . abans de crear el .gitignore, el fitxer .env ja seria a l'àrea de preparació i afegir el .gitignore després no l'en trauria: .gitignore només afecta els fitxers sense seguiment. Caldria treure'l explícitament de l'índex, una cosa que veurem a Preparant i Confirmant Canvis. I si ja s'hagués confirmat, el secret quedaria a l'historial de manera permanent i caldria rotar la clau.
Solució a l'Exercici 3
1. Què ha passat. Ha executat git init al seu directori personal (~) o a ~/projectes, és a dir, en una carpeta per sobre dels seus projectes. Ara existeix un .git en aquest nivell superior.
Els dos símptomes s'expliquen sols:
git statusllista milers de fitxers perquè el repositori abasta tota la carpeta personal i tot està sense seguiment.- Dins d'
api-clientsveu un historial buit perquè... en realitat no el veu. Vegeu el punt 4.
2. Confirmar el diagnòstic sense modificar res:
cd ~/projectes/api-clients
git rev-parse --show-toplevel
# → /home/company ← l'arrel NO és api-clients: aquí hi ha el problema
git rev-parse --git-dir
# → /home/company/.git
ls -d ~/.git
# → /home/company/.git ← existeix, no hauria de ser-hiI comprovar que el repositori accidental està realment buit abans d'esborrar-lo:
Aquest fatal és el llum verd: no hi ha historial a perdre.
3. La reparació:
I verificar que tot ha tornat al seu lloc:
cd ~/projectes/api-clients
git rev-parse --show-toplevel
# → /home/company/projectes/api-clients
git log --oneline | head -3
# → les seves vint confirmacions, intactes4. Per què git log fallava. Perquè Git busca el directori .git pujant per l'arbre de directoris des d'on ets, i fa servir el primer que troba. L'esperable és que el primer sigui el d'api-clients... i així era. Aquí hi ha la clau de l'enunciat: el company no era dins d'api-clients quan va llançar git log, o bé el .git del seu projecte no existia perquè no el va crear mai a dins i havia estat treballant, sense saber-ho, contra el repositori de nivell superior.
Aquest matís és el que fa perillós el git init accidental: el .git de dalt no oculta el de baix, però sí que captura qualsevol ordre que executis en carpetes que no tinguin el seu propi repositori. Si el company portava dies fent commits des de ~ creient que anaven a api-clients, tot el seu historial era a ~/.git i esborrar-lo amb rm -rf el destruiria. D'aquí la insistència de l'apartat 9: comprova sempre git log --oneline abans d'esborrar. Si hagués llistat confirmacions, la solució no seria esborrar, sinó moure aquest .git a un lloc segur i recuperar-ne la feina.
Conclusió
El projecte de l'Ana ja no és una carpeta: és un repositori. En aquesta lliçó hem vist que:
git initconverteix el directori actual en repositori, igit init <nom>crea a més la carpeta. El seu únic efecte és crear.git/; no toca ni desa els teus fitxers.- El que crea és la bastida buida que ja coneixíem del model de dades:
HEADapuntant amain,objects/sense cap objecte,refs/heads/sense cap branca i ni tan sols un fitxerindex. git statusés la brúixola des del primer segon: ens diu la branca, que encara no hi ha confirmacions i quins fitxers estan sense seguiment, suggerint sempre l'ordre següent.- "No commits yet" té un significat tècnic:
HEADapunta a una branca que encara no existeix. Per aixògit logigit diff HEADfallen fins a la primera confirmació. - La primera confirmació és un
root-commit: l'únic commit de l'historial sense pare. En crear-la apareixen els blobs, el tree i el commit, irefs/heads/mainneix com a fitxer amb un hash a dins. - Convertir un projecte existent exigeix una precaució extra: escriure el
.gitignoreabans del primergit add, perquè l'historial és immutable i treure'n un secret és molt més car que no ficar-l'hi. - Els repositoris bare són repositoris sense còpia de treball, pensats per servir de punt central compartit.
- Un
git initaccidental es desfà esborrant.git, però només després de comprovar ambgit rev-parse --show-topleveligit log --onelineque aquest repositori no conté res valuós.
L'Ana té el seu repositori i el seu primer commit. Però un projecte d'equip no viu en un sol portàtil: en Bruno s'incorpora la setmana que ve i necessita la seva pròpia còpia, amb tot l'historial, al seu MacBook. Per a això no serveix git init —això crearia un repositori nou i buit, sense relació amb el de l'Ana— sinó una ordre diferent.
A la lliçó següent, Clonant un Repositori, veurem què fa realment git clone: com copia tota la base de dades d'objectes, crea el directori de treball, registra el remot origin i deixa en Bruno amb un historial idèntic al de l'Ana. Compararem els protocols disponibles (HTTPS, SSH i ruta local), les opcions més útils com --branch i --depth, i deixarem clara d'una vegada la diferència conceptual entre init i clone.
Dominant Git: De Principiant a Avançat
Mòdul 1: Introducció a Git
- Què és Git?
- Instal·lant Git
- Terminologia Bàsica de Git
- El Model de Dades de Git
- Configurant Git
- Configuració Inicial
Mòdul 2: Operacions Bàsiques de Git
- Creant un Repositori
- Clonant un Repositori
- Flux de Treball Bàsic de Git
- Preparant i Confirmant Canvis
- Inspeccionant Canvis amb git diff
- Visualitzant l'Historial de Confirmacions
Mòdul 3: Branques i Fusió
- Entenent les Branques
- Creant i Canviant Branques
- Fusionant Branques
- Estratègies de Fusió
- Resolent Conflictes de Fusió
- Gestió de Branques
Mòdul 4: Treballant amb Repositoris Remots
- Entenent els Repositoris Remots
- Afegint un Repositori Remot
- Autenticació amb Repositoris Remots
- Obtenint i Baixant Canvis
- Enviant Canvis
- Rastrejant Branques
Mòdul 5: Operacions Avançades de Git
- Rebase
- Rebase Interactiu
- Cherry-Picking de Confirmacions
- Desant Canvis Temporals
- Etiquetant Confirmacions
- Revertint Confirmacions
Mòdul 6: Eines i Tècniques de Git
- Usant Git Hooks
- Git Bisect
- Git Blame
- Git Log i Àlies
- Submòduls de Git
- Múltiples Còpies de Treball amb git worktree
Mòdul 7: Estratègies de Col·laboració i Flux de Treball
- Forks i Pull Requests
- Revisions de Codi amb Git
- Flux de Treball Git Flow
- GitHub Flow
- Trunk Based Development
- Integració Contínua amb Git
Mòdul 8: Bones Pràctiques i Consells de Git
- Escrivint Bons Missatges de Confirmació
- Mantenint un Historial Net
- Ignorant Fitxers amb .gitignore
- Atributs de Fitxer amb .gitattributes
- Bones Pràctiques de Seguretat
- Consells de Rendiment
Mòdul 9: Resolució de Problemes i Depuració
- Problemes Habituals de Git
- Desfent Canvis
- Resolent Divergències amb el Remot
- Recuperant Confirmacions Perdudes
- Tractant amb Repositoris Corruptes
- Tècniques Avançades de Depuració
