A la lliçó anterior vam desmuntar el misteri: una branca és un fitxer de 41 bytes amb un hash a dins, i HEAD és un altre fitxer que diu en quina branca ets. Ara farem servir aquesta maquinària. L'Ana obrirà per fi funcionalitat/comptador-tasques, en Bruno farà el mateix amb funcionalitat/filtre-pendents, i el repositori deixarà de tenir una sola línia de treball.
Crear branques en Git és trivial —ho veuràs en un segon—, però moure's entre elles té matisos que convé dominar des del principi: què passa amb la feina que tens a mitges, per què de vegades Git et deixa canviar de branca i d'altres s'hi nega, i què és aquell estat de HEAD desacoblat que apareix quan menys t'ho esperes i que espanta tothom la primera vegada.
També aclarirem un dubte que arrossega qualsevol que aprengués Git abans del 2019: la diferència entre git checkout i git switch, i per què Git va decidir partir una ordre en dues.
Contingut
git branch: crear sense moure'sgit switch: moure'sgit switch -c: crear i moure's en un pasgit switchdavant degit checkout- Crear una branca des d'un punt concret de l'historial
git switch -: alternar entre dues branques- Canvis sense confirmar en canviar de branca
- HEAD desacoblat (detached HEAD)
- El repositori de l'equip, ja amb branques
git branch: crear sense moure's
git branch: crear sense moure'sL'Ana és a main, amb el repositori tal com el vam deixar:
c5d9b1e (HEAD -> main) 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
Vol una branca per al comptador de tasques:
Silenci absolut. En Git, el silenci sol voler dir èxit. Vegem què ha passat exactament:
Un fitxer nou, amb el hash del commit on era l'Ana. (Nota lateral interessant: com que el nom de la branca porta una barra, Git ha creat un directori funcionalitat/ dins de refs/heads/. Els noms de branca amb barres són simplement rutes de fitxer; tornarem sobre les convencions de noms a la lliçó 03-06.)
Ara la part important:
HEAD no s'ha mogut. L'Ana continua a main. Ha creat un punter nou, però no s'hi ha situat:
L'asterisc marca la branca actual. Hi ha dues branques i totes dues apunten al mateix commit.
gitGraph commit id: "1a4c8d6" commit id: "8b6d3c2" commit id: "4e7f2a9" commit id: "c5d9b1e" branch comptador-tasques
Regla:
git branch <nom>crea el punter i no toca res més. NiHEAD, ni el directori de treball, ni l'àrea de preparació.
Si l'Ana confirmés ara, el commit aniria a main, perquè és on continua apuntant HEAD. És un error clàssic: crear la branca i oblidar-se de canviar-s'hi. Per això, a la pràctica, gairebé mai no es fa servir git branch a seques per començar a treballar; es fa servir la variant de l'apartat 3.
git switch: moure's
git switch: moure'sPer situar-se a la branca acabada de crear:
I ara sí:
Això és tot el que ha fet Git en aquest cas: reescriure el fitxer .git/HEAD. Com que les dues branques apuntaven al mateix commit, el directori de treball no ha canviat ni un byte.
Quan les branques apunten a commits diferents, git switch fa alguna cosa més: a banda de reescriure HEAD, actualitza el directori de treball i l'àrea de preparació perquè reflecteixin l'arbre del commit de destinació. És a dir, canvia els fitxers del teu disc. Això és el que passa en les tres operacions internes d'un canvi de branca:
| Pas | Què fa Git |
|---|---|
| 1 | Comprova que el canvi és segur (vegeu l'apartat 7) |
| 2 | Actualitza el directori de treball i l'índex a l'arbre del commit de destinació |
| 3 | Reescriu .git/HEAD amb la branca nova |
L'Ana escriu el comptador de tasques a app.js i confirma:
[funcionalitat/comptador-tasques 6f2b9d4] Afegeix el comptador de tasques pendents 1 file changed, 12 insertions(+)
Fixa't en el nom entre claudàtors: [funcionalitat/comptador-tasques 6f2b9d4]. Git t'està dient en quina branca ha caigut el commit. És una comprovació gratuïta que convé llegir sempre.
L'Ana afegeix després el marcatge de completades:
[funcionalitat/comptador-tasques 9d1e4b7] Marca les tasques com a completades en fer clic 2 files changed, 18 insertions(+), 2 deletions(-)
Estat actual:
* 9d1e4b7 (HEAD -> funcionalitat/comptador-tasques) Marca les tasques com a completades en fer clic * 6f2b9d4 Afegeix el comptador de tasques pendents * c5d9b1e (main) 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
main s'ha quedat quieta a c5d9b1e, exactament com era. La feina de l'Ana està aïllada: pot confirmar tant com vulgui sense tocar la línia principal del projecte.
git switch -c: crear i moure's en un pas
git switch -c: crear i moure's en un pasCrear una branca i no canviar-s'hi és estrany. Per això existeix la drecera:
La -c ve de create. És exactament equivalent a:
Aquesta és la forma que faràs servir el 95 % de les vegades. git branch <nom> a seques queda reservat per als casos en què vols marcar un punt de l'historial sense abandonar el que estàs fent (per exemple, deixar un marcador abans d'una operació arriscada).
Un detall important que sovint es passa per alt: la branca nova es crea des d'on ets ara. Si l'Ana executés aquella ordre estant a funcionalitat/comptador-tasques, la branca nova partiria de 9d1e4b7 i arrossegaria el comptador de tasques, que no és el que vol. Per a la feina d'en Bruno, el punt de partida correcte és main:
O, encara millor, indicant-ho explícitament en una sola ordre —la forma que veurem a l'apartat 5.
Hi ha una variant majúscula, -C, que crea la branca o la reinicia si ja existeix:
Fes-la servir amb cura: si la branca ja existia apuntant a un altre lloc, -C mou el punter sense preguntar i pots deixar commits orfes. -c, en canvi, falla amb fatal: a branch named '…' already exists, que gairebé sempre és el que vols.
git switch davant de git checkout
git switch davant de git checkoutSi has vist Git en qualsevol tutorial anterior al 2019, o en la majoria dels que hi ha per internet avui, hauràs vist això:
git checkout funcionalitat/comptador-tasques # equival a git switch
git checkout -b funcionalitat/filtre-pendents # equival a git switch -cFunciona. git checkout no està obsolet ni desapareixerà. Però des de Git 2.23 (agost del 2019) existeixen git switch i git restore, i per a feina nova són l'opció recomanada. La raó és senzilla: git checkout feia massa coses diferents.
| Necessitat | Ordre antiga | Ordre moderna |
|---|---|---|
| Canviar de branca | git checkout <branca> |
git switch <branca> |
| Crear branca i canviar-s'hi | git checkout -b <branca> |
git switch -c <branca> |
| Crear branca des d'un commit | git checkout -b <branca> <commit> |
git switch -c <branca> <commit> |
| Anar a un commit solt | git checkout <commit> |
git switch --detach <commit> |
| Tornar a la branca anterior | git checkout - |
git switch - |
| Descartar canvis d'un fitxer | git checkout -- <fitxer> |
git restore <fitxer> |
| Treure de l'àrea de preparació | git reset HEAD <fitxer> |
git restore --staged <fitxer> |
| Recuperar un fitxer d'un altre commit | git checkout <commit> -- <fitxer> |
git restore --source=<commit> <fitxer> |
Mira les tres últimes files, que són les importants. git checkout servia tant per navegar entre branques (una operació innòcua i reversible) com per destruir canvis del directori de treball (una operació irreversible). El mateix verb per a dues coses de risc oposat.
I el desastre potencial era a l'ambigüitat. Imagina que existeix un fitxer anomenat informe i també una branca anomenada informe:
Canvia de branca o descarta els canvis del fitxer? Git resolia a favor de la branca i calia escriure git checkout -- informe (amb el doble guionet separador) per forçar la interpretació de fitxer. Si t'oblidaves del --, podies perdre feina sense avís.
La separació a Git 2.23 elimina l'ambigüitat d'arrel:
git switchnomés treballa amb branques. No pot tocar fitxers.git restorenomés treballa amb fitxers. No pot canviar de branca.
Ja vas fer servir git restore a la lliçó 02-04, així que ja coneixes la meitat de la reforma. Aquesta lliçó et dona l'altra meitat.
Què fer a la pràctica:
- Escriu
git switchigit restoreen la teva feina diària. - Aprèn a llegir
git checkout, perquè el veuràs a tot arreu: documentació antiga, respostes de Stack Overflow, scripts d'integració contínua i companys amb costums arrelats. - No converteixis els scripts existents que funcionen només per moda;
checkoutcontinua sent perfectament vàlid.
- Crear una branca des d'un punt concret de l'historial
Per defecte, una branca nova parteix de HEAD. Però li pots indicar un altre punt de partida com a segon argument, i això val per a les dues formes de l'ordre:
El punt de partida pot ser qualsevol cosa que Git sàpiga resoldre a un commit, amb tota la sintaxi que vas aprendre a la lliçó 02-06:
# Des d'una altra branca, sense haver de canviar-t'hi primer
git switch -c funcionalitat/filtre-pendents main
# Des d'un commit concret pel seu hash
git switch -c experiment/redisseny 8b6d3c2
# Des d'una posició relativa
git switch -c correccio/regressio HEAD~2
# Des del pare d'un commit concret
git switch -c prova 4e7f2a9^El primer és el cas d'en Bruno i és la manera correcta de fer-ho: crea la branca a partir de main sense necessitat de canviar-se a main abans. Una ordre en lloc de dues, i sense risc d'oblidar-se'n.
Un cas real on això salva la tarda: has estat programant durant mitja hora a main per despistament, has fet tres commits, i t'adones que haurien d'haver anat en una branca. Solució:
# 1. Crear la branca aquí mateix, amb els tres commits a dins
git branch funcionalitat/el-que-sigui
# 2. Tornar main on havia de ser
git switch main
git reset --hard HEAD~3
# 3. Anar a la branca, on hi ha tota la feina intacta
git switch funcionalitat/el-que-siguiFixa't que el pas 1 fa servir git branch sense canviar-se: crea el marcador abans de moure res. (git reset --hard és potent i perillós; l'estudiarem a fons a la lliçó 09-02. Aquí és segur perquè els commits continuen assolibles des de la branca nova.)
git switch -: alternar entre dues branques
git switch -: alternar entre dues branquesQuan estàs revisant la feina d'un company i saltes contínuament entre dues branques, escriure el nom sencer cansa. El guionet sol significa «la branca anterior»:
És el mateix concepte que cd - a la shell. Funciona amb noms de branca tan llargs com funcionalitat/exportar-llistat-a-csv i estalvia moltíssimes pulsacions.
Per sota, el guionet és un àlies d'@{-1}, que significa «la branca on era fa un canvi». I n'hi ha més:
Aquesta informació surt del reflog, el registre que Git manté de tots els moviments de HEAD. És la mateixa eina que permet recuperar feina aparentment perduda, i l'estudiarem a la lliçó 09-04.
- Canvis sense confirmar en canviar de branca
Aquí hi ha el matís que més confusió genera. Què passa amb el que tens a mitges quan canvies de branca?
La resposta curta: Git intenta emportar-s'ho amb tu, i si no pot fer-ho sense perdre res, s'hi nega.
La resposta llarga depèn de si els canvis afecten fitxers que difereixen entre les dues branques.
Cas A: Git et deixa passar i s'emporta els canvis
L'Ana és a funcionalitat/comptador-tasques i ha començat a retocar README.md, un fitxer que és idèntic a les dues branques:
Ha funcionat, i aquella línia M README.md és Git avisant-te: «aquell fitxer venia modificat i continua modificat». El canvi ha viatjat amb l'Ana a l'altra branca. Continua sense confirmar, al seu directori de treball:
Això és útil a propòsit: et permet començar a escriure alguna cosa, adonar-te que ets a la branca equivocada i corregir-ho sense perdre res.
Cas B: Git s'hi nega
Ara l'Ana és a main i modifica app.js, que sí que difereix entre main i la branca del comptador (el comptador el va canviar allà):
error: Your local changes to the following files would be overwritten by checkout: app.js Please commit your changes or stash them before you switch branches. Aborting
Git s'hi ha negat, i ha fet bé. Per situar-se a l'altra branca hauria de sobreescriure app.js amb la versió d'allà, i això destruiria els canvis de l'Ana sense possibilitat de recuperar-los, perquè mai no han estat a la base de dades d'objectes.
L'important és que l'operació s'ha avortat del tot. Continues on eres i els teus canvis són intactes.
La regla, resumida
| Situació | Comportament |
|---|---|
| El fitxer modificat és igual a les dues branques | Canvia de branca i s'emporta les modificacions |
| El fitxer modificat difereix entre les dues branques | Rebutja el canvi de branca i avorta |
| Hi ha canvis a l'àrea de preparació sobre fitxers que no difereixen | Canvia de branca i conserva l'àrea de preparació |
| Hi ha fitxers nous sense seguiment que no existeixen a la destinació | Canvia de branca i els deixa on són |
| Hi ha fitxers sense seguiment que sí existeixen a la destinació | Rebutja, per no sobreescriure'ls |
Les tres sortides quan Git s'hi nega
-
Confirmar. Si la feina té sentit a la branca actual, confirma-la. Si està a mitges, pots fer un commit provisional i arreglar-ho després amb
git commit --amend(lliçó 02-04) o amb el rebase interactiu (lliçó 05-02). -
Descartar. Si el canvi no val res,
git restore app.jsl'elimina i el canvi de branca passa a estar permès. -
Desar-ho temporalment. Per al cas real —feina a mitges que vols conservar però que encara no mereix un commit— Git té una eina específica:
git stash, que aparta els canvis a un magatzem temporal, deixa el directori net i permet recuperar-los després ambgit stash pop:
git stash # aparta els canvis
git switch funcionalitat/comptador-tasques # ara sí que pot
# … el que fos a fer …
git switch main
git stash pop # recupera els canvisÉs una ordre amb bastanta més profunditat de la que suggereix aquest exemple (diverses entrades apilades, incloure fitxers sense seguiment, aplicar en una altra branca…). L'estudiarem sencera a la lliçó 05-04; de moment queda't amb que existeix i amb que és la resposta estàndard a aquest problema.
Forçar el canvi de branca (amb compte)
Existeix l'opció de descartar els canvis i canviar de branca igualment:
(L'equivalent antic era git checkout -f.) És destructiu i irreversible: els canvis no confirmats no són a cap objecte de Git, així que no hi ha cap reflog ni cap recuperació possible. Fes-ho servir només quan estiguis absolutament segur que vols llençar aquella feina.
- HEAD desacoblat (detached HEAD)
Recorda la lliçó anterior: HEAD normalment conté ref: refs/heads/<branca>. Però pot contenir directament un hash. Aquest estat s'anomena HEAD desacoblat.
Com s'hi arriba
La forma deliberada és demanar-ho:
Note: switching to '4e7f2a9'. 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> HEAD is now at 4e7f2a9 Afegeix l'esborrat de tasques al llistat
Git et deixa anar un discurs perquè l'estat és inusual, no perquè sigui perillós. De fet aquell text ja explica gairebé tot el que necessites saber.
Les formes accidentals d'arribar-hi, que són les que espanten:
git checkout <hash>(sense-b), la més freqüent amb l'ordre antiga.git checkout v1.2.0, en situar-se en una etiqueta —les etiquetes apunten a commits, no són branques.- Durant un
git rebaseo ungit bisect, que treballen internament en aquest estat (mòduls 5 i 6). - En situar-se a
origin/mainen lloc de amain, un error molt comú que veurem al mòdul 4.
Què es veu
Un hash directament, sense ref:. HEAD apunta al commit, no a una branca.
El directori de treball conté els fitxers tal com eren en aquell commit. És un estat perfectament legítim: pots compilar, executar les proves, mirar el codi antic o fins i tot confirmar.
Per a què serveix de debò
No és un accident que calgui evitar; és una eina:
- Revisar com era el projecte en un moment donat. L'Ana vol veure l'aplicació tal com era el dia de la primera confirmació:
git switch --detach 1a4c8d6, obreindex.htmlal navegador i llestos. - Provar si una fallada existia en una versió antiga, situant-se en diferents punts de l'historial.
- Experimentar sense comprometre's. Pots confirmar en aquest estat, i si el resultat no val, tornes a una branca i els commits queden orfes.
El perill real
El perill no és ser en aquest estat. És confirmar-hi i després marxar sense deixar rastre:
# En detached HEAD
echo "// prova de rendiment" >> app.js
git commit -am "Prova una optimització del pintat"Aquell commit 7d2f9a1 és real i és a la base de dades d'objectes, però cap branca no l'assoleix. Si l'Ana ara fa git switch main:
Warning: you are leaving 1 commit behind, not connected to any of your branches: 7d2f9a1 Prova una optimització del pintat If you want to keep it by creating a new branch, this may be a good time to do so with: git branch <new-branch-name> 7d2f9a1 Switched to branch 'main'
Git avisa, i fins i tot et dona l'ordre exacta. Però si no llegeixes aquell avís i tanques el terminal, el hash desapareix de la teva vista i el commit queda orfe. Continua sent recuperable durant un temps mitjançant el reflog (mòdul 9), però és una situació que no vols.
Com sortir-ne sense perdre res
Si no has confirmat res (només miraves):
O git switch main, o qualsevol branca. No hi ha res a salvar.
Si has confirmat i ho vols conservar, crea una branca abans de marxar:
Ara HEAD torna a apuntar a una branca, aquella branca apunta a 7d2f9a1, i el commit ja és assolible. Ja no hi ha res orfe.
Si ja has marxat i el commit va quedar enrere, encara pots crear la branca a posteriori, sempre que tinguis el hash (apareix a l'avís, i si el vas perdre, a git reflog):
graph TD
A["En una branca<br/>HEAD → ref: refs/heads/main"] -->|"git switch --detach abc123"| B["HEAD desacoblat<br/>HEAD → abc123"]
B -->|"git switch -<br/>(sense confirmar res)"| A
B -->|"confirmar aquí"| C["Commits orfes<br/>cap branca no els assoleix"]
C -->|"git switch -c la-meva-branca"| D["Feina salvada<br/>en una branca nova"]
C -->|"marxar sense crear branca"| E["Només recuperable<br/>via reflog (mòdul 9)"]
- El repositori de l'equip, ja amb branques
Recapitulem on som. L'Ana té la seva branca amb dos commits. En Bruno ha estat treballant a la seva, amb els tres commits que ja vam veure al final del mòdul 2 —el filtre de pendents, l'estil de les completades i la correcció del focus—, ara a funcionalitat/filtre-pendents en lloc de directament sobre main.
Per a la resta del mòdul raonarem com si les tres branques fossin en un mateix repositori local, el de l'Ana. Com aconsegueix l'equip que la feina viatgi entre el portàtil de l'Ana i el MacBook d'en Bruno és precisament el tema del mòdul 4; aquí ens concentrem en la mecànica de les branques, que és idèntica vingui la feina d'on vingui.
funcionalitat/comptador-tasques 9d1e4b7 Marca les tasques com a completades en fer clic funcionalitat/filtre-pendents b2e6d3f Corregeix el focus del camp després d'afegir una tasca * main c5d9b1e Documenta la instal·lació al README
* b2e6d3f (funcionalitat/filtre-pendents) 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 | * 9d1e4b7 (funcionalitat/comptador-tasques) Marca les tasques com a completades en fer clic | * 6f2b9d4 Afegeix el comptador de tasques pendents |/ * c5d9b1e (HEAD -> main) 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
gitGraph commit id: "1a4c8d6" commit id: "8b6d3c2" commit id: "4e7f2a9" commit id: "c5d9b1e" branch comptador-tasques checkout comptador-tasques commit id: "6f2b9d4" commit id: "9d1e4b7" checkout main branch filtre-pendents checkout filtre-pendents commit id: "3d5b8e1" commit id: "7c1f4a9" commit id: "b2e6d3f"
Tres línies de treball, tres punters, 123 bytes de cost total. Els quatre commits de base són una sola vegada a la base de dades d'objectes i els comparteixen les tres branques.
I aquí hi ha el problema que resoldrem a la lliçó següent: les dues funcionalitats estan acabades i provades, però el projecte real —main— continua exactament on era fa una setmana. Res del que han fet l'Ana i en Bruno no és a la línia principal.
Errors Habituals i Consells
Error 1: git branch <nom> i posar-se a treballar. Crees la branca, se t'oblida el git switch, fas cinc commits i tots cauen a main. Prevenció doble: fes servir git switch -c en lloc de git branch, i llegeix la línia entre claudàtors que imprimeix git commit, que et diu la branca de destinació.
Error 2: crear la branca des del lloc equivocat. git switch -c correccio/urgent estant en una branca de funcionalitat a mitges arrossega tota aquella feina sense acabar dins de la correcció urgent. Abans de crear una branca, comprova on ets amb git branch --show-current, o indica el punt de partida explícitament: git switch -c correccio/urgent main.
Error 3: entrar en pànic amb detached HEAD. No és un error ni una corrupció: és un estat normal. El missatge és llarg perquè explica, no perquè avisi d'un desastre. Si només miraves, git switch - i llestos. Si vas confirmar, git switch -c <nom> abans de marxar.
Error 4: fer servir git checkout -f o --discard-changes per «desencallar». Aquella ordre destrueix els canvis no confirmats de manera irreversible: no són a cap objecte de Git i no hi ha reflog que valgui. Quan Git es negui a canviar de branca, la resposta correcta és confirmar, descartar conscientment amb git restore o desar amb git stash.
Error 5: git switch -C en lloc de -c. La majúscula reinicia una branca existent sense preguntar. Si la branca ja tenia feina, mou el punter i aquella feina queda òrfena. -c falla amb un error clar, que en el 99 % dels casos és el que vols que passi.
Consell 1: una branca per tasca, i de vida curta. Les branques són gratis, així que no hi acumulis feina. Una branca que viu tres setmanes acumula divergència i garanteix conflictes; una que viu dos dies gairebé mai no en té.
Consell 2: activa l'autocompletat de Git. Amb noms com funcionalitat/filtre-pendents, escriure git switch fun<TAB> és la diferència entre treballar còmode i equivocar-se de branca. L'script git-completion.bash ve amb la instal·lació de Git i moltes distribucions l'activen per defecte.
Consell 3: comprova on ets abans de confirmar. El cost és un segon:
Consell 4: no reutilitzis branques velles per a tasques noves. És temptador (ja tinc la branca proves, la reaprofito), però acaba amb historials que no s'entenen i amb fusions que arrosseguen canvis que ningú no ha demanat. Crea una branca nova i esborra la vella quan ja no serveixi; la neteja és el tema de la lliçó 03-06.
Exercicis
Exercici 1: crear branques sense moure's
En un repositori de proves amb almenys tres commits, crea dues branques —experiment/un i experiment/dos— sense canviar-te a cap d'elles, de manera que:
experiment/unparteixi del commit actual.experiment/dosparteixi de dos commits enrere.
Després, demostra amb ordres que HEAD no s'ha mogut i que les dues branques apunten on correspon.
Exercici 2: provocar i resoldre un rebuig de canvi de branca
Dissenya la seqüència mínima d'ordres que provoqui l'error Your local changes to the following files would be overwritten by checkout, i després resol-lo de tres maneres diferents, explicant quan faries servir cadascuna.
Exercici 3: sortir d'un HEAD desacoblat sense perdre feina
Situa't deliberadament en un HEAD desacoblat, fes-hi un commit i conserva'l en una branca nova. Després repeteix el procés però abandonant l'estat sense crear la branca, i observa què et diu Git. Quina dada del missatge és imprescindible anotar?
Solucions
Solució 1:
# Les dues branques, amb git branch (que NO mou HEAD)
git branch experiment/un
git branch experiment/dos HEAD~2Comprovació:
experiment/dos 8b6d3c2 Afegeix els estils base del llistat experiment/un c5d9b1e Documenta la instal·lació al README * main c5d9b1e Documenta la instal·lació al README
L'asterisc continua a main: HEAD no s'ha mogut. experiment/un coincideix amb main i experiment/dos és dos commits enrere, com demanava l'enunciat.
Verificació byte a byte:
Solució 2:
Per provocar l'error calen dues condicions: un fitxer que difereixi entre les dues branques i una modificació sense confirmar en aquell mateix fitxer.
# 1. Branca amb un canvi confirmat a app.js
git switch -c branca-x
echo "// canvi de la branca X" >> app.js
git commit -am "Canvia app.js a la branca X"
# 2. Tornem a main i toquem el MATEIX fitxer, sense confirmar
git switch main
echo "// canvi sense confirmar a main" >> app.js
# 3. Intentem tornar
git switch branca-xerror: Your local changes to the following files would be overwritten by checkout: app.js Please commit your changes or stash them before you switch branches. Aborting
Les tres resolucions:
# A) Confirmar: la feina pertany a main i està llesta
git commit -am "Afegeix una nota a app.js"
git switch branca-xQuan: quan el canvi és vàlid i té sentit a la branca actual.
Quan: proves, traces de depuració o qualsevol cosa que no vulguis conservar. És irreversible.
# C) Desar temporalment: feina a mitges que vull conservar
git stash
git switch branca-x
# … feina a branca-x …
git switch main
git stash popQuan: el cas més habitual del dia a dia, i el motiu que git stash existeixi (lliçó 05-04).
Solució 3:
# Confirmem alguna cosa aquí
echo "/* prova des de HEAD desacoblat */" >> estils.css
git commit -am "Prova un ajust d'estils"El commit ja és assolible des d'una branca: no hi ha res orfe.
Segona part, abandonant sense crear branca:
git switch --detach HEAD~2
echo "/* una altra prova */" >> estils.css
git commit -am "Una altra prova que abandonaré"
git switch mainWarning: you are leaving 1 commit behind, not connected to any of your branches: 3c9d4a2 Una altra prova que abandonaré If you want to keep it by creating a new branch, this may be a good time to do so with: git branch <new-branch-name> 3c9d4a2 Switched to branch 'main'
La dada imprescindible és el hash: 3c9d4a2. Mentre el tinguis, recuperar la feina és una sola ordre:
Si a més perds el hash, la situació no és desesperada: git reflog guarda tots els moviments de HEAD durant 90 dies per defecte i permet trobar-lo. És el tema de la lliçó 09-04.
Conclusió
Ja saps crear branques i moure't entre elles amb criteri:
git branch <nom>crea el punter i no toca res més: niHEAD, ni el directori de treball, ni l'índex. Útil per marcar un punt sense abandonar el que estàs fent.git switch <branca>et situa en una branca: reescriu.git/HEADi actualitza el directori de treball a l'arbre de destinació.git switch -c <nom> [punt-de-partida]és la manera habitual de començar una tasca: crea i es canvia en un pas, i admet qualsevol referència com a origen (una altra branca, un hash,HEAD~2…).git switchigit restoresubstitueixengit checkoutdes de Git 2.23, separant el que abans era una única ordre ambigua: navegar entre branques i destruir canvis ja no comparteixen verb.checkoutcontinua funcionant i el continuaràs veient en documentació i scripts.git switch -alterna amb la branca anterior, igual quecd -.- En canviar de branca, Git s'emporta els canvis sense confirmar si pot fer-ho sense perdre res, i avorta netament si el fitxer difereix entre les dues branques. Les sortides són confirmar, descartar amb
git restoreo apartar ambgit stash(lliçó 05-04). - El HEAD desacoblat és
HEADcontenint un hash en lloc deref: refs/heads/…. No és un error: serveix per inspeccionar i experimentar. L'única precaució és crear una branca ambgit switch -cabans d'abandonar-lo si hi has confirmat alguna cosa.
El que ve
L'equip té ara tres branques: main aturada on era, funcionalitat/comptador-tasques amb dos commits de l'Ana i funcionalitat/filtre-pendents amb tres d'en Bruno. Dues funcionalitats acabades que no són al projecte.
Aïllar la feina era la meitat del problema; l'altra meitat és tornar-la a ajuntar. A la lliçó següent, Fusionant Branques, l'Ana integrarà per fi les dues funcionalitats a main. Veurem els dos escenaris que Git distingeix —el fast-forward, en què el punter simplement avança, i la fusió a tres bandes, que crea un commit especial amb dos pares—, com troba Git l'ancestre comú que vam estudiar a la lliçó anterior, i per què de vegades convé forçar un commit de fusió encara que no calgui.
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ó
