La Carla fa tres dies que és a funcionalitat/esborrat-multiple. És una branca llarga: toca app.js, estils.css i el nou diàleg de components-ui. Té el codi a mitges, amb funcions sense acabar i l'aplicació en un estat que ni tan sols arrenca.
I aleshores arriba l'avís: hi ha una fallada en producció i cal publicar una correcció ara.
La seva rutina actual és aquesta:
git stash -u
git switch main
git switch -c correccio/urgent
# ... arreglar, provar, confirmar, publicar ...
git switch funcionalitat/esborrat-multiple
git stash pop
# ... reconstruir mentalment on era ...Deu vegades al dia. I cada volta té el seu peatge: el stash amb fitxers sense seguiment de vegades dona conflictes en recuperar-lo, cal reconstruir el context mental, el servidor de desenvolupament es reinicia, i des que hi ha submòdul (lliçó 06-05) cada canvi de branca arrossega a més la seva actualització.
La seva idea següent és clonar el repositori dues vegades. Funcionaria, però com veurem té un cost real. Git ofereix una cosa millor i força desconeguda: diversos directoris de treball compartint una única base de dades d'objectes. Es diu git worktree, i amb aquesta lliçó tanquem el mòdul.
Contingut
- Què és un worktree
worktree add: el primer directori addicional- Comparació amb clonar dues vegades
- El joc complet d'ordres
- La regla clau: una branca, un worktree
- Com es veu per dins
- Casos d'ús reals
- Interacció amb
stash, submòduls i hooks - Tancament del mòdul 6
- Què és un worktree
Recordem l'estructura de la lliçó 01-03. Un repositori Git té dues parts ben diferenciades:
- El directori
.git/: els objectes, les referències, la configuració, el reflog. El repositori de debò. - L'arbre de treball (working tree): els fitxers que veus i edites, que són el reflex d'un commit concret.
Fins ara hem donat per fet que n'hi ha un de cada. Però no és obligatori:
Un worktree és un directori de treball addicional, amb el seu propi
HEAD, el seu propi índex i els seus propis fitxers, que comparteix la base de dades d'objectes i les referències amb el repositori original.
flowchart TD
subgraph BD[".git/ — una sola base de dades"]
O["Objectes: blobs, trees, commits"]
R["Referències: branques, etiquetes, remots"]
C["Configuració i reflog"]
end
subgraph W1["~/projectes/gestor-tasques"]
H1["HEAD → funcionalitat/esborrat-multiple"]
I1["Índex propi"]
F1["app.js, estils.css... (a mitges)"]
end
subgraph W2["~/projectes/gestor-tasques-urgent"]
H2["HEAD → correccio/urgent"]
I2["Índex propi"]
F2["app.js, estils.css... (net)"]
end
W1 --> BD
W2 --> BD
El que es comparteix: objectes, branques, etiquetes, remots, git fetch, configuració del repositori, reflog de les referències.
El que és propi de cada worktree: HEAD, l'índex, els fitxers del disc, l'estat d'operacions en curs (una fusió a mitges, un rebase aturat) i la pila de stash.
El directori original s'anomena worktree principal; els afegits, worktrees enllaçats. Funcionalment són gairebé idèntics.
worktree add: el primer directori addicional
worktree add: el primer directori addicionalLa Carla resol el seu problema amb una ordre:
Preparing worktree (new branch 'correccio/urgent') HEAD is now at c8f2a1e Fusiona funcionalitat/filtre-estat
El que acaba de passar:
- S'ha creat el directori
~/projectes/gestor-tasques-urgent/. - Conté una còpia de treball completa del projecte en l'estat de
main. - S'ha creat la branca
correccio/urgenta partir demaini és activa allà. - El directori original no s'ha tocat en absolut: continua a
funcionalitat/esborrat-multiple, amb tota la seva feina a mitges intacta.
/home/carla/projectes/gestor-tasques c8f2a1e [funcionalitat/esborrat-multiple] /home/carla/projectes/gestor-tasques-urgent c8f2a1e [correccio/urgent]
Ara la Carla treballa al segon directori amb tota normalitat:
cd ../gestor-tasques-urgent
# ... corregir app.js ...
git commit -am "Corregeix l'esborrat quan la tasca te subtasques"
git push -u origin correccio/urgentI quan acaba, torna:
On branch funcionalitat/esborrat-multiple Changes not staged for commit: modified: app.js modified: estils.css Untracked files: nou-dialeg.js
Exactament com ho va deixar. Ni stash, ni pop, ni reconstruir el context: l'editor, el servidor de desenvolupament i la finestra del navegador continuen oberts on eren.
Les formes d'invocar add:
| Ordre | Què fa |
|---|---|
git worktree add <ruta> <branca-existent> |
Obre aquella branca al directori nou |
git worktree add <ruta> |
Crea una branca amb el nom del directori |
git worktree add -b <branca-nova> <ruta> [<punt>] |
Crea la branca i l'obre |
git worktree add -B <branca> <ruta> [<punt>] |
Com -b, però la restableix si ja existeix |
git worktree add --detach <ruta> <commit> |
Detached HEAD en aquell commit, sense branca |
git worktree add --track -b <branca> <ruta> origin/<branca> |
Crea la branca amb seguiment del remot |
I una d'útil quan la branca ve del remot:
Git detecta que funcionalitat/exportar existeix a origin i crea automàticament una branca local amb seguiment (el comportament de --guess-remote, que es pot fixar amb git config worktree.guessRemote true).
- Comparació amb clonar dues vegades
L'alternativa evident era git clone una altra vegada. La comparació explica per què worktree és millor gairebé sempre:
git worktree add |
Segon git clone |
|
|---|---|---|
| Espai al disc | Només els fitxers de l'arbre de treball | Fitxers + tota la base d'objectes duplicada |
| Objectes compartits | Sí: una sola còpia | No: dues còpies independents |
| Branques visibles | Les mateixes a tots els worktrees | Cada clon té les seves |
| Etiquetes | Compartides | Duplicades i dessincronitzables |
git fetch |
Un de sol actualitza tots | Un per clon |
| Remots i credencials | Compartits | Cal configurar-los a cadascun |
| Configuració local | Compartida (amb matisos) | Independent per clon |
| Un commit a A, es veu a B? | Immediatament | Només després de push + fetch |
| Stash | Independent per worktree | Independent |
| Hooks | Compartits (un sol .git/hooks) |
Un per clon |
| Temps de creació | Segons (no hi ha transferència) | El que trigui el clon complet |
| Risc de dessincronització | Cap: és un sol repositori | Real |
El punt que més se subestima és "un commit a A, es veu a B?". Amb dos clons, per portar un commit d'un a l'altre cal passar pel servidor. Amb worktrees, tan bon punt la Carla confirma en un directori, aquell commit ja existeix per a l'altre: hi pot fer git cherry-pick, git rebase o git log immediatament, sense xarxa pel mig.
L'estalvi d'espai, amb xifres: si .git/ ocupa 400 MB (historial llarg, algun binari) i l'arbre de treball 15 MB, un clon extra costa 415 MB i un worktree 15 MB. En repositoris grans la diferència deixa de ser anecdòtica.
Abans existia
git clone --shared/--referenceper compartir objectes entre clons. Funciona, però és fràgil: si el repositori de referència es mou o es neteja, el clon dependent pot quedar corrupte.git worktreeés la solució moderna i segura al mateix problema, i la que s'ha de fer servir.
- El joc complet d'ordres
list
/home/carla/projectes/gestor-tasques c8f2a1e [funcionalitat/esborrat-multiple] /home/carla/projectes/gestor-tasques-urgent 3d8f1a6 [correccio/urgent] /home/carla/projectes/gestor-tasques-v1 b7e2c4a (detached HEAD) /home/carla/projectes/gestor-tasques-antic a1b2c3d [experiment] prunable
La marca prunable indica que el directori ja no existeix al disc i el seu registre es pot netejar.
remove
La manera correcta d'eliminar un worktree:
Esborra el directori i el seu registre. Si hi ha canvis sense confirmar, s'hi nega —cosa que és una protecció, no una molèstia:
I compte: remove no esborra la branca. Això va a part:
prune
Si vas esborrar el directori a mà amb rm -rf (que funciona, però deixa el registre), prune neteja les restes:
Git també l'executa sol de tant en tant, i el termini de gràcia es controla amb gc.worktreePruneExpire (per defecte, tres mesos).
move
Mou el directori i actualitza les rutes internes. Moure'l amb mv a seques trenca els enllaços, així que fes servir sempre aquesta ordre.
lock i unlock
git worktree lock ../gestor-tasques-usb --reason "És al disc extern de còpies"
git worktree unlock ../gestor-tasques-usbUn worktree bloquejat no es pot fer servir amb prune ni move. És exactament per al cas d'un worktree en una unitat extraïble o un recurs de xarxa: quan la unitat no és muntada, el directori "no existeix" i prune l'esborraria del registre sense més. lock ho impedeix, i el motiu apareix a git worktree list --porcelain perquè se sàpiga per què.
repair
Reconstrueix els enllaços interns quan alguna cosa els ha trencat: has mogut directoris a mà, has restaurat una còpia de seguretat, o has reanomenat el repositori principal.
Taula resum:
| Ordre | Què fa |
|---|---|
git worktree add <ruta> [<branca>] |
Crea un worktree nou |
git worktree list |
Els llista tots, amb la seva branca i el seu commit |
git worktree remove <ruta> |
N'elimina un (amb --force si hi ha canvis) |
git worktree prune |
Neteja registres de worktrees ja esborrats |
git worktree move <origen> <destinacio> |
En mou un actualitzant les rutes |
git worktree lock/unlock <ruta> |
En protegeix un de prune i move |
git worktree repair [<rutes>] |
Repara els enllaços interns trencats |
- La regla clau: una branca, un worktree
Aquesta és la restricció fonamental, i cal entendre-la perquè explica la meitat dels missatges d'error que veuràs:
Una mateixa branca no pot estar activa en dos worktrees alhora.
fatal: 'funcionalitat/esborrat-multiple' is already used by worktree at '/home/carla/projectes/gestor-tasques'
I el mateix en crear:
fatal: 'funcionalitat/esborrat-multiple' is already used by worktree at '/home/carla/projectes/gestor-tasques'
Per què existeix la restricció. Una branca és un punter que avança en confirmar (lliçó 03-01). Si dos worktrees tinguessin la mateixa branca activa, un commit en un mouria la branca sota els peus de l'altre: el segon es trobaria que el seu HEAD apunta a un commit que ell no ha creat, i el seu arbre de treball deixaria de correspondre a res coherent. Git prohibeix la situació en lloc de deixar que passi.
No és una limitació, és una protecció. I té tres sortides quan de debò necessites el mateix codi dues vegades:
# A) En detached HEAD: sense branca per moure, no hi ha conflicte
git worktree add --detach ../revisio-nomes-lectura funcionalitat/esborrat-multiple
# B) En un commit concret, que és el mateix
git worktree add --detach ../versio-1.0 v1.0.0
# C) Una branca nova des del mateix punt
git worktree add -b experiment/altra-via ../experiment funcionalitat/esborrat-multipleL'opció A és la que més es fa servir: per llegir o compilar una branca no cal tenir-la activa com a branca.
I una conseqüència pràctica que convé saber: git branch -d es nega a esborrar una branca que sigui activa en un altre worktree, i git rebase o git merge tampoc no hi poden operar des de fora. Per localitzar on és:
- Com es veu per dins
Reprenem la lliçó 01-04 i el model de dades, perquè el mecanisme és elegant i explica tot l'anterior.
Al worktree principal, .git és un directori:
En un worktree enllaçat, .git és un fitxer de text:
Una sola línia que diu: "el meu repositori és allà". És exactament el mateix mecanisme que fan servir els submòduls de la lliçó 06-05, on el .git del submòdul és un fitxer que apunta a .git/modules/<nom> del pare.
I al repositori principal:
| Fitxer | Contingut |
|---|---|
HEAD |
El HEAD propi d'aquell worktree |
index |
El seu índex propi (l'àrea de preparació) |
gitdir |
La ruta absoluta del directori de treball al qual serveix |
commondir |
Ruta al .git comú, on hi ha els objectes i les refs |
logs/HEAD |
El reflog d'aquell worktree |
I aquí hi ha l'explicació completa del model:
HEADiindexsón per worktree → cadascun pot ser en una branca diferent i tenir els seus propis canvis preparats.objects/irefs/són alcommondir→ les branques, les etiquetes i els objectes són els mateixos per a tots, i per això un commit en un es veu a l'instant a l'altre.
Amb això s'entén també per què la restricció de l'apartat 5 és inevitable: hi ha un sol fitxer refs/heads/funcionalitat/esborrat-multiple, i no pot ser el HEAD de dos directoris que confirmen per separat.
Hi ha fins i tot una notació per consultar el HEAD d'un altre worktree:
git rev-parse main@{worktree-principal} # sintaxi avançada, rarament necessària
git worktree list --porcelain # l'habitualI una nota sobre configuració: per defecte, .git/config és compartit per tots els worktrees. Si necessites que un tingui configuració pròpia, existeix extensions.worktreeConfig:
És un cas avançat i poc freqüent, però convé saber que existeix si et trobes un config.worktree dins de .git/worktrees/<nom>/.
- Casos d'ús reals
Cas 1: el hotfix sense tocar el que tens a mitges
El de la Carla, i el més comú. Un worktree permanent per a urgències:
Quan arriba l'avís, cd ../gestor-tasques-hotfix, git pull, es crea la branca, s'arregla i es publica. Sense stash, sense canviar de branca, sense perdre el context.
Cas 2: comparar dues versions en execució
En Bruno ha de comprovar si un problema de rendiment existia a la versió 1.0:
# Terminal 1
cd ~/projectes/gestor-tasques && python3 -m http.server 8000
# Terminal 2
cd ~/projectes/gestor-tasques-v1 && python3 -m http.server 8001Dos servidors, dues pestanyes del navegador, les dues versions funcionant alhora. Comparar així és incomparablement més fiable que anar alternant branques i recordar com era.
Cas 3: compilar una branca mentre treballes en una altra
Una compilació completa de gestor-tasques triga quatre minuts. Amb un sol directori, aquests quatre minuts són d'espera, perquè qualsevol edició embruta el resultat. Amb worktrees:
git worktree add ../gestor-tasques-build funcionalitat/esborrat-multiple-rc
cd ../gestor-tasques-build && npm run build &
cd ~/projectes/gestor-tasques # continuar treballant mentre compilaCas 4: revisar la branca d'un company
L'Ana ha de revisar la pull request d'en Bruno, però és a mitja feina pròpia:
git fetch
git worktree add --detach ../revisio origin/funcionalitat/exportar
cd ../revisio
# ... executar, llegir, provar ...
cd .. && git worktree remove revisioSense --detach també funcionaria, però per revisar no cal branca local, i així s'evita acumular branques de revisió.
Cas 5: un rebase llarg sense bloquejar la feina
Un git rebase -i amb conflictes (lliçó 05-02) deixa el repositori en un estat intermedi. Si apareix alguna cosa urgent, quedes atrapat: rebase --abort i a començar de nou. Amb un worktree dedicat, el rebase es queda aturat al seu directori i tu treballes en un altre. Com que l'estat de les operacions en curs és propi de cada worktree, no interfereixen.
Cas 6: bisect sense aturar-se
git bisect (lliçó 06-02) fa desenes de checkout al teu directori. Si és una bisecció llarga amb compilacions, la pots llançar en un worktree a part:
git worktree add --detach ../gestor-tasques-bisect main
cd ../gestor-tasques-bisect
git bisect start main v1.0.0
git bisect run /tmp/provar-esborrat.shMentrestant, el teu directori principal continua a la teva branca, intacte. En acabar, git bisect reset i git worktree remove.
Cas 7: documentació en una branca òrfena
Alguns projectes publiquen la documentació en una branca independent (gh-pages i similars). Amb worktrees:
S'edita la documentació al seu directori i el codi al seu, amb historials separats i sense canviar de branca mai.
- Interacció amb
stash, submòduls i hooks
stash, submòduls i hooksAmb git stash
La pila de stash és pròpia de cada worktree. Un git stash list al directori principal no mostra el que s'ha desat en un altre:
Tècnicament, refs/stash es desa per worktree. És coherent amb el model —el stash és feina a mitges d'un arbre concret— però sorprèn la primera vegada.
I la conclusió pràctica de tot això: els worktrees no substitueixen stash, sinó que redueixen molt la necessitat de fer-lo servir. stash continua sent l'eina correcta per apartar una cosa durant dos minuts dins de la mateixa branca; el worktree ho és per treballar en dues branques durant dies.
| Situació | Eina |
|---|---|
Apartar canvis dos minuts per fer un pull |
git stash |
| Provar una cosa ràpida a la mateixa branca | git stash |
| Treballar en dues branques durant hores o dies | git worktree |
| Atendre urgències sense perdre el context | git worktree |
| Comparar dues versions en execució | git worktree |
| Desar feina abans de canviar de màquina | git stash o una branca WIP |
Amb submòduls
Els worktrees i els submòduls (lliçó 06-05) conviuen, però cal saber dues coses:
- Els submòduls no s'inicialitzen sols en un worktree nou. Després de l'
add, toca:
git worktree add ../gestor-tasques-urgent -b correccio/urgent main
cd ../gestor-tasques-urgent
git submodule update --init --recursive- Els repositoris interns dels submòduls viuen al
.git/modules/comú, així que els objectes es comparteixen igual que els del pare: la inicialització no torna a baixar res de la xarxa, només facheckout. És ràpida.
El suport de worktrees dins de submòduls ha millorat molt en les versions recents de Git, però continua sent el terreny on apareixen més rareses. Si alguna cosa es descol·loca, git worktree repair sol arreglar-ho.
Amb hooks
Els hooks són compartits: hi ha un sol .git/hooks/ (o un sol core.hooksPath, lliçó 06-01) per a tots els worktrees. Un pre-commit instal·lat funciona a tots automàticament, cosa que és un avantatge.
El matís: un hook que assumeixi rutes absolutes o que doni per fet un directori concret es pot confondre. Els hooks s'executen amb el directori de treball posat a l'arrel del worktree actiu, així que fer servir rutes relatives és el correcte. I si un hook necessita distingir on és:
git rev-parse --show-toplevel # arrel del worktree actual
git rev-parse --git-common-dir # el .git compartit
git rev-parse --git-dir # el .git/worktrees/<nom> d'aquest worktreeAmb el rendiment i el manteniment
Un apunt breu, perquè el tema complet és d'una altra lliçó: els worktrees comparteixen la base d'objectes, així que un git gc afecta tots i Git té cura de no eliminar objectes referenciats des de qualsevol d'ells. Un worktree registrat però el directori del qual ja no existeix pot, en canvi, mantenir vius objectes innecessàriament: per això convé executar git worktree prune de tant en tant.
Tot el relatiu a
git gc,git maintenancei el rendiment en repositoris grans és el tema de la lliçó 08-06: Consells de Rendiment; els clons parcials,sparse-checkouti les tècniques d'escalat, el de la 10-04.
- Tancament del mòdul 6
Amb aquesta lliçó tanques el bloc d'eines. Repassant el que ha canviat en la manera de treballar de l'equip de gestor-tasques:
- Hooks (06-01): comprovacions automàtiques a
pre-commit,commit-msgipre-push, versionades ambcore.hooksPath. Ajuden contra el descuit, però el que és obligatori es comprova al servidor. git bisect(06-02): cerca binària que converteix 214 commits en 8 proves, automatitzable ambbisect runi els seus codis de sortida.git blame(06-03): la història de cada línia, amb-w,-Ci--ignore-revper travessar el soroll, igit log -Lper veure l'evolució completa.git logavançat i àlies (06-04):--graph,--first-parent,--simplify-by-decoration,--left-right, formats amb colors,shortlog, i els àlies que converteixen tot això en una paraula.- Submòduls (06-05): un punter a un commit d'un altre repositori, amb reproductibilitat exacta a canvi de fricció, i comparats amb subtree, paquets i monorepo.
git worktree(06-06): diversos directoris de treball sobre una única base d'objectes.
I una idea que travessa tot el mòdul: l'historial de Git no és només un registre del que va passar, és una base de dades consultable. Qui va escriure cada línia, en quin commit va canviar un comportament, què s'ha integrat a main aquest mes, quina versió exacta de la biblioteca feia servir la versió 1.0. Totes aquestes preguntes tenen resposta exacta, i ara saps com demanar-la.
El que ve
L'equip domina l'eina. L'Ana, en Bruno i la Carla saben construir l'historial, manipular-lo amb criteri, consultar-lo a fons i automatitzar comprovacions sobre ell.
El que no han acordat encara és com treballar junts. I aquestes preguntes ja no són tècniques:
- Quan en Bruno acaba una funcionalitat, com la proposa? Empeny directament a
main? Obre una pull request? I si no té permís d'escriptura al repositori? - Quan l'Ana revisa la feina de la Carla, què mira, com comenta i quan aprova? Què fa un revisor que no sigui repetir el que ja diu el linter?
- Quines branques existeixen i per a què serveix cadascuna? Hi ha una branca
develop? Branques de versió? O tothom integra amaindiverses vegades al dia? - Quan es publica una versió? Què cal haver passat abans que un canvi arribi a producció?
No hi ha una resposta única: hi ha fluxos de treball diferents, cadascun amb la seva lògica, els seus avantatges i el seu tipus d'equip. Un projecte de codi obert amb centenars de col·laboradors externs no pot funcionar com un equip de tres persones que desplega cinc vegades al dia.
Al mòdul 7: Estratègies de Col·laboració i Flux de Treball veurem els forks i les pull requests com a mecanisme per proposar canvis, les revisions de codi i com es fan bé, i els tres grans models de ramificació —Git Flow, GitHub Flow i Trunk Based Development— comparats amb criteri per saber quin encaixa en cada situació. I tancarem amb la integració contínua: les comprovacions automàtiques que, aquesta vegada sí, ningú no es pot saltar amb un --no-verify.
Comencem per com es proposa un canvi, a la lliçó 07-01: Forks i Pull Requests.
Errors Habituals i Consells
Error 1: intentar obrir la mateixa branca en dos worktrees. Git ho impedeix i et diu on és activa. Fes servir --detach si només vols llegir o compilar.
Error 2: esborrar el directori amb rm -rf. Funciona, però deixa el registre brut. Fes servir git worktree remove, o git worktree prune després.
Error 3: moure el directori amb mv. Trenca els enllaços interns. Fes servir git worktree move, o git worktree repair si ja ho has fet.
Error 4: oblidar que remove no esborra la branca. Treure el worktree deixa la branca viva; esborra-la a part amb git branch -d.
Error 5: esperar que els submòduls s'inicialitzin sols. Cal executar git submodule update --init --recursive a cada worktree nou.
Error 6: buscar un stash al worktree equivocat. La pila és pròpia de cadascun. Si no apareix, mira a l'altre directori.
Error 7: crear worktrees dins del mateix repositori. git worktree add ./temporal funciona, però el directori apareix com a contingut sense seguiment del repositori principal. Crea'ls fora, com a germans del directori original.
Error 8: acumular worktrees oblidats. Ocupen disc i mantenen branques ocupades. git worktree list de tant en tant, i remove dels que sobren.
Consell 1: adopta una convenció de noms. gestor-tasques, gestor-tasques-hotfix, gestor-tasques-v1. Amb ../<projecte>-<proposit> mai no et perds.
Consell 2: tingues un worktree permanent per a urgències. Sempre a main, sempre net. És el que més vegades et salvarà el dia.
Consell 3: crea un àlies. Amb el que hem après a la lliçó 06-04:
git config --global alias.wt "worktree list"
git config --global alias.nou '!f() { git worktree add "../$(basename "$PWD")-$1" -b "$1"; }; f'git nou correccio-urgent crea ../gestor-tasques-correccio-urgent amb aquella branca.
Consell 4: --detach per a tot el que sigui només lectura. Revisar, compilar, comparar o bisecar no necessita branca local, i així no xoques amb la regla d'una branca per worktree.
Consell 5: un git fetch n'hi ha prou per a tots. És un sol repositori: no repeteixis el fetch a cada directori.
Consell 6: comprova la teva versió de Git. worktree existeix des de la 2.5, però move, remove i repair van arribar després (2.17 i 2.30). En versions antigues, algunes operacions són manuals.
Exercicis
Exercici 1: el flux del hotfix
- Crea un repositori amb
maini una brancafuncionalitat/llargaamb canvis sense confirmar (modificats i sense seguiment). - Sense fer
stash, crea un worktree a../projecte-hotfixamb una branca novacorreccio/urgentdes demain. - Confirma una correcció al worktree nou.
- Torna al directori original i comprova que els teus canvis sense confirmar continuen exactament igual.
- Comprova des del directori original que el commit del hotfix ja existeix (
git log correccio/urgent), sense haver fet cappushnifetch. - Elimina el worktree i la branca.
Exercici 2: la restricció d'una branca per worktree
- Amb el repositori anterior, intenta crear un worktree amb una branca que ja sigui activa en un altre. Anota el missatge d'error.
- Aconsegueix el mateix codi en un segon directori fent servir
--detach. - Comprova amb
git worktree listque un apareix amb branca i l'altre com a(detached HEAD). - Intenta esborrar amb
git branch -duna branca activa en un altre worktree i observa què passa.
Exercici 3: l'anatomia per dins
- En un worktree enllaçat, comprova que
.gités un fitxer i mostra'n el contingut. - Localitza el directori corresponent a
.git/worktrees/del principal i llista'n el contingut. - Compara el
HEADde tots dos worktrees. - Fes un
git stashen un i comprova quegit stash lista l'altre és buit. - Esborra un worktree amb
rm -rf, comprova que continua apareixent agit worktree list(marcat com aprunable) i neteja'l ambprune.
Solucions
Solució 1:
mkdir /tmp/practica-worktree && cd /tmp/practica-worktree
git init -q -b main
echo "<html><body></body></html>" > index.html
echo "console.info('arrencada');" > app.js
git add . && git commit -q -m "Afegeix l'esquelet de l'aplicacio"
git switch -qc funcionalitat/llarga
echo "// feina a mitges, no compila" >> app.js
echo "esborrany sense acabar" > notes.txt
git status --shortPreparing worktree (new branch 'correccio/urgent') HEAD is now at 4f8a2e6 Afegeix l'esquelet de l'aplicacio
cd ../projecte-hotfix
git status --short # net
echo "console.info('correccio aplicada');" >> app.js
git commit -qam "Corregeix l'arrencada quan falta el contenidor"
git log --onelineIntactes. Ni stash ni pop.
El commit fet a l'altre directori es veu immediatament: és la mateixa base d'objectes. Amb dos clons hauria calgut push + fetch.
La branca continua viva: remove no l'esborra.
Solució 2:
Mateix commit, mateix contingut, sense conflicte: a ../altre no hi ha cap branca que es pugui moure.
Git protegeix la branca activa en qualsevol worktree, no només en l'actual.
Solució 3:
cat /tmp/practica-worktree/.git/worktrees/altre/HEAD
cat /tmp/practica-worktree/.git/HEAD
cat /tmp/practica-worktree/.git/worktrees/altre/commondirEl worktree enllaçat té un hash directe (detached), el principal una referència simbòlica a la seva branca, i commondir apunta al .git compartit on hi ha els objectes i les refs.
El registre continua allà, marcat com a prunable.
Net. Amb git worktree remove en lloc de rm -rf, aquest últim pas no hauria calgut.
Conclusió
git worktree resol un problema quotidià amb una idea simple i ben construïda. L'essencial:
- Un worktree és un directori de treball addicional amb el seu propi
HEADi índex, que comparteix objectes i referències amb el repositori original. - Davant de clonar dues vegades: no duplica la base d'objectes, comparteix branques, etiquetes, remots i hooks, un sol
fetchserveix per a tots, i un commit fet en un es veu a l'instant a l'altre, sense passar pel servidor. git worktree add <ruta> [<branca>]el crea en segons;-bcrea branca nova i--detachobre un commit sense branca.- El joc complet és
add,list,remove,prune,move,lock/unlockirepair. Fes servirremoveen lloc derm -rfimoveen lloc demv;lockprotegeix els worktrees en unitats extraïbles. - Una branca no pot estar activa en dos worktrees alhora. No és una limitació capriciosa: evita que un commit mogui la branca sota els peus d'un altre directori. La sortida per a lectura i compilació és
--detach. - Per dins, el
.gitdel worktree enllaçat és un fitxer amb una líniagitdir:que apunta a.git/worktrees/<nom>, on viuen el seuHEAD, el seuindexi el seu reflog; els objectes i les refs són alcommondircompartit. És el mateix mecanisme que fan servir els submòduls. - Casos d'ús que es guanyen el lloc: hotfix sense perdre el context, comparar dues versions en execució, compilar una branca mentre treballes en una altra, revisar la branca d'un company, i aïllar un rebase llarg o una bisecció.
- El stash és propi de cada worktree; els hooks són compartits; els submòduls cal inicialitzar-los a cada worktree nou.
- I la relació amb
stash: no el substitueix, però en redueix molt l'ús.stashper a minuts dins d'una branca;worktreeper a dies entre diverses.
Amb això es tanca el mòdul 6 i el bloc tècnic del curs. L'equip de gestor-tasques ja sap construir, manipular, consultar i automatitzar el seu historial. El que necessita ara és posar-se d'acord: com es proposa un canvi, com es revisa i quin flux de branques seguir. Això és el mòdul 7, i comença a la lliçó 07-01: Forks i Pull Requests.
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ó
