Commit 88fa3795 authored by jg5dev's avatar jg5dev 💬
Browse files

better

parent a8c5cd20
Loading
Loading
Loading
Loading
+1 −0
Changes for src/SUMMARY.md: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@
    - [Frameworks a la pràctica](./fonaments/frameworks_practica.md)
  - [Workflow Git](./fonaments/workflow_git.md)
    - [Git en equip](./fonaments/git_equip.md)
    - [Preguntes freqüents de Git](./fonaments/git_faq.md)
  - [Docker bàsic](./fonaments/basic_docker.md)
  - [DevOps](./fonaments/devops.md)
  - [Infrastructure as Code](./fonaments/iac.md)
+2 −1
Changes for src/fonaments.md: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -10,8 +10,9 @@
  - [Arquitectura dels frameworks](./fonaments/frameworks.md): quina arquitectura imposa un framework (peces comunes, model d'execució, eix d'opinió, capes, ORM).
  - [Frameworks un per un](./fonaments/frameworks_taules.md): taules de consulta amb el vocabulari i les decisions per defecte de dotze frameworks.
  - [Frameworks a la pràctica](./fonaments/frameworks_practica.md): llegir un projecte, triar framework, deixar peces substituïbles i posar ordre quan el framework no en posa.
- [Workflow Git](./fonaments/workflow_git.md): flux de treball amb Git, resolució de conflictes, operacions habituals i FAQ.
- [Workflow Git](./fonaments/workflow_git.md): flux de treball amb Git, resolució de conflictes i operacions habituals.
  - [Git en equip](./fonaments/git_equip.md): estratègies de branques, pull requests, fluxos de la indústria (GitHub flow, trunk-based, Git flow), CI/CD i bones pràctiques de commit.
  - [Preguntes freqüents de Git](./fonaments/git_faq.md): respostes breus als dubtes habituals (pull, upstream, desfer commits, reflog, .gitignore).
- [Docker bàsic](./fonaments/basic_docker.md): contenidors, Dockerfile, volums, Docker Compose i distribució d'imatges.
- [DevOps](./fonaments/devops.md): principis de la cultura DevOps i com aplicar-los al desenvolupament i l'operació.
- [Infrastructure as Code](./fonaments/iac.md): aprovisionament amb Terraform, configuració amb Ansible, gestió de secrets i integració amb CI/CD.
+1 −1
Changes for src/fonaments/git_equip.md: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -236,7 +236,7 @@ c72a3f8 "add product search index"

També fan la revisió més fàcil: el revisor pot seguir la PR commit a commit, com una història en capítols, en lloc d'enfrontar-se a un sol diff enorme.

Regla pràctica: fes commit de cada unitat lògica de treball per separat, ajudant-te de l'[staging area](./workflow_git.md#en-local) per triar què hi entra. Si el codi no està llest, utilitza [`git stash`](./workflow_git.md#descartar-tots-els-canvis-locals) per guardar-lo temporalment sense fer commit.
Regla pràctica: fes commit de cada unitat lògica de treball per separat, ajudant-te de l'[staging area](./workflow_git.md#en-local) per triar què hi entra. Si el codi no està llest, utilitza [`git stash`](./git_faq.md#descartar-tots-els-canvis-locals) per guardar-lo temporalment sense fer commit.

### Maneres de fusionar una PR

+276 −0
Changes for src/fonaments/git_faq.md: 276 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Preguntes freqüents de Git

<!-- toc -->

Respostes breus als dubtes més habituals quan treballes amb git. Els exemples fan referència als escenaris de [Workflow Git](./workflow_git.md).

## Crear un repositori des d'una carpeta existent

Si ja tens una carpeta amb codi i vols pujar-la a un repositori remot buit (creat prèviament a github o gitlab):

```shell
cd la-meva-carpeta
git init -b main
git remote add origin https://gitlab.com/usuari/repositori.git
# afegir .gitignore abans del primer commit
git add .
git commit -m "commit inicial"
git push -u origin main
```

Alternativament, pots clonar primer el repositori buit i copiar-hi el contingut:

```shell
git clone https://gitlab.com/usuari/repositori.git
cd repositori
git switch -c main
# copiar arxius i afegir .gitignore
git add .
git commit -m "commit inicial"
git push -u origin main
```

## `git pull` vs `git fetch` + `git merge`

`git pull` és equivalent a fer `git fetch` seguit de `git merge`. La diferència pràctica és que amb fetch + merge pots inspeccionar els canvis remots abans d'integrar-los (amb `git log` o `git diff`), mentre que pull ho fa tot de cop.

```shell
# Amb fetch + merge (més control)
git fetch
git log --oneline main..origin/main   # veure què ha canviat
git merge

# Amb pull (més ràpid)
git pull origin main
```

## `git pull`: merge o rebase?

Quan la teva branca local i la remota han divergit, `git pull` ha de combinar les dues històries, i pot fer-ho de dues maneres:

* **Merge** (comportament per defecte): crea un commit de merge que uneix les dues línies. Conserva l'historial exacte, però hi deixa "bombolles" de merge com les que hem vist a l'[escenari amb conflicte](./workflow_git.md#escenari-amb-conflicte).
* **Rebase**: reaplica els teus commits locals a sobre dels remots, deixant un historial lineal i més net. És la mateixa idea que [rebase per mantenir la branca al dia](./git_equip.md#rebase-per-mantenir-la-branca-al-dia), aplicada al `pull`.

Pensa en l'usuari 2 de l'[escenari amb conflicte](./workflow_git.md#escenari-amb-conflicte). Amb merge, obté el diamant que hem vist en aquell escenari. Amb rebase, el seu commit es reaplica a sobre de `segona 1`:

```mermaid
gitGraph
    commit id: "primer commit"
    commit id: "afegim pregunta"
    commit id: "segona 1"
    commit id: "segona 2'"
```

L'apòstrof de `segona 2'` indica que és un commit nou: el mateix canvi, però amb un altre hash. El conflicte s'hauria de resoldre igualment, durant el rebase.

Des de git 2.27, si no has triat estratègia, `git pull` mostra un avís demanant-te que en configuris una. Les opcions habituals:

```shell
git config --global pull.rebase true   # pull sempre amb rebase (historial lineal)
git config --global pull.ff only       # només permet pull si és fast-forward; si no, atura's
```

Amb `pull.ff only` (una opció prudent), si hi ha divergència git no fa res automàticament i decideixes tu si fer `git merge` o `git rebase`. Puntualment també pots forçar l'estratègia amb `git pull --rebase` o `git pull --no-rebase`.

Compte: no facis rebase de commits que ja hagis pujat i compartit, perquè en reescriu l'historial (com `--amend` o el push forçat).

## Vincular una branca local amb la remota (upstream)

Quan fas `git push` o `git pull` sense especificar el remot ni la branca, git necessita saber a quina branca remota correspon la teva branca local. Aquesta associació s'anomena _upstream_ o _tracking branch_.

Hi ha diverses maneres d'establir-la:

```shell
# Opció 1: al fer push per primera vegada, amb -u (o --set-upstream)
git push -u origin main

# Opció 2: explícitament, sense fer push
git branch --set-upstream-to=origin/main main
```

Un cop establerta l'associació, pots fer servir les comandes curtes:

```shell
git push    # equivalent a git push origin main
git pull    # equivalent a git pull origin main
```

Quan clones un repositori, git configura automàticament el tracking de la branca principal. Per això `git pull` funciona directament en un repositori clonat sense haver de fer `-u` primer.

Per veure quines branques locals tenen upstream configurat:

```shell
git branch -vv
```

La sortida mostra, entre claudàtors, la branca remota associada:

```text
  feature d4e5f6a [origin/feature] un altre missatge
* main    a1b2c3d [origin/main] últim missatge de commit
```

## El push m'ha estat rebutjat ("fetch first")

Si en fer `git push` reps un error com aquest:

```text
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to '...'
```

vol dir que **algú ha pujat canvis al remot abans que tu**, i git no et deixa sobreescriure'ls. No és cap error greu: només cal que integris primer els canvis remots i tornis a pujar.

```shell
git pull            # baixa i integra els canvis remots (fetch + merge)
# si hi ha conflictes, resol-los, fes git add i git commit
git push            # ara sí
```

És exactament la situació de l'[escenari amb conflicte](./workflow_git.md#escenari-amb-conflicte). Recorda la regla d'or: sincronitza (pull) sovint per reduir les vegades que et trobes en aquesta situació.

## Veure els canvis abans del commit

```shell
git diff                # canvis al working directory (no afegits al staging)
git diff --staged       # canvis ja afegits al staging area
git diff HEAD           # tots els canvis respecte l'últim commit
```

## Treure un arxiu afegit per error

Si encara no has fet push, pots treure l'arxiu de l'últim commit sense perdre els canvis locals:

```shell
git reset HEAD~1 --soft          # desfà el commit, manté els canvis al staging
git restore --staged arxiu-erroni.txt  # treu l'arxiu del staging
git commit -m "el commit correcte"
```

Si ja has fet push però vols treure l'arxiu del repositori sense esborrar-lo del disc:

```shell
git rm --cached arxiu-erroni.txt
# afegir-lo al .gitignore si cal
git commit -m "remove arxiu-erroni del repositori"
git push
```

## El .gitignore no ignora un arxiu

El `.gitignore` només afecta els arxius que git **encara no segueix** (untracked). Si un arxiu ja s'havia afegit al repositori abans d'incloure'l al `.gitignore`, git continuarà seguint-lo i els seus canvis. Per deixar de seguir-lo (sense esborrar-lo del disc), treu-lo de l'índex amb `--cached`:

```shell
git rm --cached arxiu.txt
git commit -m "deixa de seguir arxiu.txt"
```

A partir d'aquí, amb l'arxiu ja al `.gitignore`, git l'ignorarà. Per a una carpeta sencera, fes servir `git rm -r --cached carpeta`.

## Descartar tots els canvis locals

```shell
git reset --hard HEAD
```

Compte: això esborra tots els canvis no comesos. Si vols guardar-los temporalment per recuperar-los més tard:

```shell
git stash               # guarda els canvis temporalment
# ... fas altres coses ...
git stash pop           # recupera els canvis guardats
```

## Desfer o corregir l'últim commit

Mentre no hagis fet push, l'últim commit es pot desfer o modificar sense afectar ningú.

**Desfer el commit completament**, mantenint els canvis al working directory:

```shell
git reset --soft HEAD~1    # els canvis queden al staging, llestos per tornar a fer commit
git reset HEAD~1           # els canvis queden al working directory, fora del staging
```

**Desfer el commit i descartar els canvis** (irreversible):

```shell
git reset --hard HEAD~1
```

**Corregir l'últim commit** (afegir arxius oblidats o canviar el missatge):

```shell
# Canviar només el missatge
git commit --amend -m "nou missatge corregit"

# Afegir arxius que faltaven al commit
git add arxiu-oblidat.txt
git commit --amend --no-edit    # manté el missatge original
```

`--amend` reescriu l'últim commit. Si ja has fet push, no és recomanable fer-ho perquè reescriu l'historial i pot causar problemes als companys.

## Tornar a l'estat del remot

Si vols descartar tots els canvis locals (commits, staging i working directory) i sincronitzar-te exactament amb el repositori remot:

```shell
git fetch origin
git reset --hard origin/main
```

Això mou el HEAD local al mateix commit que `origin/main`, descartant qualsevol commit local que no s'hagi pujat i qualsevol canvi pendent. Si tens arxius nous que no estan al repositori (untracked), no s'esborren. Per eliminar-los també:

```shell
git clean -fd             # esborra arxius i carpetes untracked
```

Compte: ambdues operacions són irreversibles. Si no estàs segur de voler perdre els canvis, fes primer una còpia o un `git stash`.

## Recuperar commits perduts (reflog)

Si has perdut feina amb un `reset` o un rebase, sovint la pots recuperar. git guarda un registre de tots els llocs on ha estat el HEAD (cada commit, reset, merge, switch...) durant un temps. Es consulta amb `git reflog`:

```shell
git reflog
8f151d7 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
2be3461 HEAD@{1}: commit: feina que creia perduda
8f151d7 (HEAD -> main) HEAD@{2}: commit (initial): primer commit
```

Cada línia és un estat anterior del HEAD. Quan localitzis el commit que vols (per exemple `2be3461`, el que crèiem perdut), el pots recuperar tornant la branca a aquell punt:

```shell
git reset --hard 2be3461       # torna la branca a aquell commit
```

O, si només vols mirar-lo sense moure la branca, fes `git switch --detach 2be3461`.

Compte: el reflog és local i no és etern (git el va netejant; per defecte, les entrades caduquen al cap d'uns 90 dies). És una xarxa de seguretat, no un substitut de fer commits i push sovint.

## M'ha sortit un editor que no sé com tancar

Si fas un `git commit` sense `-m`, o git necessita que escriguis un missatge (per exemple, en completar un merge), obre un editor de text. Per defecte sol ser **vim** o **nano**, i és fàcil quedar-s'hi encallat:

* **vim**: prem `Esc`, escriu `:wq` i prem `Enter` per desar i sortir (o `:q!` per sortir sense desar).
* **nano**: prem `Ctrl+O` i `Enter` per desar, i després `Ctrl+X` per sortir.

Per evitar-ho, posa el missatge directament a la comanda amb `-m`:

```shell
git commit -m "el missatge"
```

O configura un editor que et resulti més còmode:

```shell
git config --global core.editor "nano"            # o "vim"
git config --global core.editor "code --wait"     # VS Code
```

## Referències

* [Pro Git book (gratuït)](https://git-scm.com/book/en/v2)
* [git-reflog: documentació oficial](https://git-scm.com/docs/git-reflog)
* [git-config: documentació oficial](https://git-scm.com/docs/git-config)
+3 −270

File changed.

Preview size limit exceeded, changes collapsed.

Loading