L'auditoria de seguretat de 08-03 va canviar dotze coses del toolkit, i la lliçó d'optimització n'havia canviat unes quantes més abans. Ara mateix, si vigilant.sh comença a fallar el dimarts de matinada, ningú no sap dir què es va tocar, quan ni per què, ni com tornar a la versió que funcionava. Aquesta lliçó posa ~/veloz-ops/ sota control de versions. No és un curs de Git: és Git vist des de la necessitat concreta d'un equip d'operacions que manté cinc scripts, una llibreria i un fitxer de configuració amb credencials que no s'ha de pujar mai.
Contingut
- Per què
copia.sh.bak.old.v2no és control de versions - Els cinc conceptes que calen
- Posar
~/veloz-ops/sota control - Veure què ha canviat:
git diffigit log - Què NO es versiona:
.gitignorei la configuració - Si ja has pujat un secret
- Missatges de commit útils en operacions
- Desfer amb criteri
- Branques per provar sense tocar producció
- Etiquetes i desplegament a la flota
- Remots i repositoris privats
- Un hook
pre-commitde debò - Flux de treball mínim per a un equip petit
- Per què
copia.sh.bak.old.v2 no és control de versions
copia.sh.bak.old.v2 no és control de versionsEl patró és universal: abans de tocar un script se'n fa una còpia amb un sufix. Al cap d'un any el directori té copia.sh.bak, copia.sh.old, copia.sh.v2, copia.sh.20260715 i copia.sh.BO. I cap d'aquestes còpies no respon a les preguntes que importen: què va canviar exactament entre dues d'elles, qui ho va canviar, quan, per què i quina és la que corre ara a srv-veloz-02. Tampoc no permeten saber si el canvi del dimarts i el del dijous són independents.
Git respon a les cinc preguntes i hi afegeix dues capacitats que les còpies no donen: provar un canvi en paral·lel sense tocar el que és en producció, i desfer un canvi concret sense desfer els posteriors.
- Els cinc conceptes que calen
| Concepte | Què és | Analogia |
|---|---|---|
| Repositori | El directori amb la seva història completa, a .git/ |
L'arxiu del projecte |
| Àrea de preparació (staging) | Zona intermèdia on tries què entra al pròxim commit | La safata del que lliuraràs |
| Commit | Una foto del projecte amb autor, data i missatge | Una entrada de bitàcola signada |
| Branca | Una línia de desenvolupament independent | Un esborrany paral·lel |
| Remot | Una còpia del repositori en un altre lloc | El servidor on l'equip comparteix |
L'àrea de preparació és el que més confon al principi i té una raó molt pràctica: permet haver tocat quatre fitxers i fer dos commits diferents, un amb la correcció de seguretat i un altre amb la millora de rendiment. En operacions això val or, perquè permet revertir-ne un sense l'altre.
- Posar
~/veloz-ops/ sota control
~/veloz-ops/ sota control$ cd ~/veloz-ops
$ git init
S'ha inicialitzat un repositori Git buit a /home/veloz/veloz-ops/.git/
$ git config user.name "Ana Lopez"
$ git config user.email "[email protected]"Abans del primer git add cal decidir què no hi entra, així que el correcte és escriure el .gitignore primer (apartat 5) i després afegir:
$ git add .gitignore bin/ lib/ etc/veloz-ops.conf.exemple
$ git status --short
A .gitignore
A bin/informe-diari.sh
A bin/vigilant.sh
A etc/veloz-ops.conf.exemple
A lib/comu.sh
$ git commit -m "Versio inicial del toolkit d'operacions de Veloz Envios"
[master (commit-arrel) 4f2a1b8] Versio inicial del toolkit d'operacions
8 files changed, 1247 insertions(+)git add mou canvis a l'àrea de preparació; git commit els grava a la història. A git status --short, A és added, M modificat, D esborrat i ?? sense seguiment. Un detall que estalvia sorpreses: Git desa el bit d'execució, així que els chmod +x de bin/ viatgen amb el repositori.
- Veure què ha canviat:
git diff i git log
git diff i git log$ git diff # canvis NO preparats (treball vs. staging)
$ git diff --staged # canvis preparats (staging vs. ultim commit)
$ git log --oneline --graph --decorate -4
* 9c14e7a (HEAD -> master, tag: v1.2) Fixar PATH i IFS a comu.sh (auditoria)
* 3b8d201 Substituir bucle per awk a informe-diari.sh: 3m12s -> 3,9s
* a71f0c4 Afegir --dry-run a copia.sh
* 4f2a1b8 Versio inicial del toolkitLa distinció entre els dos diff és la que més es pregunta en començar: el primer ensenya el que encara no has afegit amb git add; el segon, el que és a punt d'entrar al commit. Revisa sempre git diff --staged abans d'escriure el missatge: és el moment natural per descobrir que t'has deixat un set -x posat. Per investigar un fitxer concret, git log -p bin/vigilant.sh mostra la seva història línia a línia i git blame bin/vigilant.sh diu quin commit va introduir cada línia: l'eina que de debò faràs servir quan alguna cosa faci mesos que està trencada.
- Què NO es versiona:
.gitignore i la configuració
.gitignore i la configuracióAquesta és la part crítica. etc/veloz-ops.conf conté el token que acabem de protegir a 08-03; pujar-lo el fa visible per a tot l'equip, per sempre i a cada clon.
# ~/veloz-ops/.gitignore
etc/veloz-ops.conf # secrets i configuracio local: MAI
etc/secrets
*.key
*.pem
.netrc
logs/ # sortida regenerable
*.log
*.tmp
dades/ # dades de negoci: van a la copia, no al repositori
*.csvAl seu lloc es versiona una plantilla que documenta la configuració sense revelar res:
# etc/veloz-ops.conf.exemple <-- aquest SI es versiona
VELOZ_API_URL="http://localhost:8080"
VELOZ_API_TOKEN="posa-aqui-el-teu-token" # obtenir de Vault, no compartir
VELOZ_RETENCIO_DIES=30En instal·lar el toolkit en un servidor nou es copia la plantilla, s'omple i s'ajusten els permisos. Una advertència important: .gitignore només afecta els fitxers sense seguiment. Si ja vas fer git add etc/veloz-ops.conf, afegir-lo al .gitignore no el treu: cal git rm --cached etc/veloz-ops.conf, que el treu del repositori i el deixa al disc.
- Si ja has pujat un secret
Passa. L'ordre de les accions no és negociable:
- Rota el secret immediatament. Genera'n un de nou i invalida el vell. És l'únic pas que de debò mitiga; els altres són neteja.
- Treu-lo del repositori actual:
git rm --cached, afegeix-lo al.gitignore, commit. - Reescriu la història amb
git filter-repo(l'eina recomanada avui) o BFG Repo-Cleaner, que eliminen el fitxer de tots els commits. - Avisa l'equip: la reescriptura canvia tots els identificadors de commit i qui tingui un clon l'haurà de refer.
I l'advertència de fons: reescriure la història no n'hi ha prou si el repositori ja s'ha compartit. Qualsevol el va poder clonar, la plataforma el va poder indexar, hi ha còpies a la memòria cau i a les còpies de seguretat. Per això el pas 1 no és opcional ni posterior.
- Missatges de commit útils en operacions
Un missatge no descriu el diff —això ja ho fa el diff—, sinó què va canviar i per què. En operacions, el «per què» sol ser un incident:
| Missatge inútil | Missatge útil |
|---|---|
canvis |
Afegir timeout de 10s a veloz_api_get |
arreglo |
Corregir divisio per zero a veloz_percentatge sense enviaments |
update vigilant.sh |
Pujar el llindar de disc al 85% per evitar avisos falsos |
wip |
Fixar PATH i IFS a comu.sh (auditoria de seguretat) |
Convenció pràctica: primera línia imperativa de menys de 72 caràcters, línia en blanc i cos amb el context.
$ git commit -m "Reintentar la consulta a veloz-api fins a 3 cops" -m \
"Incident INC-482: el 2026-07-29 l'API va trigar 8s a respondre despres del
reinici nocturn i vigilant.sh va enviar una alerta falsa. S'afegeixen
reintents amb retroces exponencial (2s, 4s, 8s) abans d'alertar."D'aquí a sis mesos, aquest commit explica per què existeix un bucle de reintents que a primera vista sobra. Un commit per canvi lògic: no barregis la refactorització de rendiment amb la correcció de seguretat encara que les hagis fet la mateixa tarda.
- Desfer amb criteri
Quatre ordres per a quatre situacions. Confondre-les és la principal font de feina perduda:
| Situació | Ordre | Destructiu |
|---|---|---|
| Descartar les meves edicions d'un fitxer | git restore bin/vigilant.sh |
Sí (perd el que no s'ha desat) |
He fet git add de més |
git restore --staged etc/veloz-ops.conf |
No |
| Un commit ja publicat és incorrecte | git revert 3b8d201 |
No (crea un commit invers) |
| Llençar commits locals encara no publicats | git reset --hard 4f2a1b8 |
Sí, esborra història |
Regla d'or: git revert per al que ja han vist altres; git reset --hard només per al que és teu i no publicat. revert deixa constància que hi va haver un canvi i que es va retirar, cosa que en operacions és informació valuosa. I si el missatge de l'últim commit està malament, git commit --amend el corregeix mentre no l'hagis pujat.
- Branques per provar sense tocar producció
Vols reescriure la lògica de llindars de vigilant.sh, però aquest script corre cada cinc minuts a tres servidors. Una branca et dóna un espai paral·lel:
$ git switch -c llindars-dinamics # crea la branca i s'hi canvia
$ git commit -am "Calcular el llindar de disc amb la mitjana de 7 dies"
$ git switch master # master continua intacteQuan el canvi estigui provat s'integra amb git merge llindars-dinamics i s'esborra la branca amb git branch -d. Si en l'interval algú va tocar les mateixes línies a master, Git avisa d'un conflicte i marca el fitxer:
<<<<<<< HEAD
llindar_disc=85
=======
llindar_disc=$(( mitjana_7dies + 10 ))
>>>>>>> llindars-dinamicsResoldre'l és editar el fitxer deixant-hi la versió correcta —sovint una combinació de totes dues—, esborrar les tres línies de marques i fer git add i git commit. No hi ha màgia: decideix un humà. En scripts de Bash convé a més executar bash -n (05-03) sobre el fitxer resolt abans de confirmar, perquè un conflicte mal resolt hi deixa fàcilment un fi de més.
- Etiquetes i desplegament a la flota
Una etiqueta marca un punt de la història amb un nom estable, i en operacions serveix per saber quina versió corre a cada servidor:
El desplegament a srv-veloz-01/02/03 combina això amb el que vam veure a 07-06:
# A) Cada servidor te un clon i s'actualitza a l'etiqueta
for h in srv-veloz-01 srv-veloz-02 srv-veloz-03; do
ssh -n "$h" 'cd ~/veloz-ops && git fetch --tags && git checkout -q v1.2'
done
# B) Un clon de referencia i rsync a la flota (sense Git en produccio)
for h in srv-veloz-01 srv-veloz-02 srv-veloz-03; do
rsync -a --delete --exclude '.git' --exclude 'etc/veloz-ops.conf' \
~/veloz-ops/ "$h:~/veloz-ops/"
doneL'opció A permet consultar la versió desplegada amb git describe a cada màquina; la B evita instal·lar Git i credencials en producció. Fixa't en l'exclusió d'etc/veloz-ops.conf: la configuració és local de cada servidor i no s'ha de sobreescriure des del repositori.
- Remots i repositoris privats
Un repositori local no és una còpia de seguretat: si es perd el disc, es perd la història.
$ git remote add origin [email protected]:ops/veloz-ops.git
$ git push -u origin master # -u recorda el desti per als seguents
$ git pull # porta i integra el que hagin pujat altresgit pull és internament fetch més merge; si prefereixes veure què arriba abans d'integrar-ho, git fetch seguit de git log HEAD..origin/master és un hàbit excel·lent en operacions. I una advertència que no sobra: el codi d'operacions va en repositoris privats. Encara que no contingui secrets —i no n'ha de contenir—, revela noms de servidors, camins interns, llindars i estructura del sistema; és reconeixement gratuït per a un atacant. Autenticació per clau SSH (07-06), no per contrasenya.
- Un hook
pre-commit de debò
pre-commit de debòUn hook és un script que Git executa automàticament en un cert moment. pre-commit corre abans de crear el commit i, si acaba amb un codi diferent de 0, l'avorta:
#!/usr/bin/env bash
# .git/hooks/pre-commit - requereix chmod +x
set -uo pipefail
fallades=0
mapfile -t scripts < <(git diff --cached --name-only --diff-filter=ACM |
grep -E '\.(sh|bats)$|^bin/')
(( ${#scripts[@]} == 0 )) && exit 0
for s in "${scripts[@]}"; do
bash -n "$s" || { printf 'sintaxi: %s\n' "$s" >&2; fallades=1; }
shellcheck -x "$s" || fallades=1 # 08-05
done
[[ -d tests ]] && { bats tests/ >/dev/null || fallades=1; } # 08-06
if git diff --cached | grep -qE 'TOKEN=|PASSWORD=|BEGIN (RSA|OPENSSH) PRIVATE KEY'; then
printf 'possible secret al commit, revisa-ho\n' >&2
fallades=1
fi
exit "$fallades"Quatre barreres: sintaxi amb bash -n, anàlisi estàtica amb ShellCheck, proves amb Bats i una cerca simple de secrets. --diff-filter=ACM limita la comprovació als fitxers afegits, copiats o modificats —no té sentit analitzar-ne un que s'esborra— i només mira els preparats, no tot l'arbre. Dues limitacions que cal conèixer: els hooks viuen a .git/hooks/ i no es versionen, així que cal instal·lar-los a cada clon (per això molts equips guarden el hook a tools/ i l'enllacen amb un script d'instal·lació), i git commit --no-verify se'ls salta. El hook és una xarxa de seguretat per a despistes, no un control d'accés.
- Flux de treball mínim per a un equip petit
Per a dues o tres persones d'operacions n'hi ha prou amb això: git pull abans de començar; branca curta per al canvi (git switch -c corregir-timeout-api); commits petits amb missatges que citin l'incident; git push -u origin <branca> i petició de revisió a una altra persona; fusió a master, etiqueta si és desplegable i desplegament a la flota; esborrar la branca.
El penúltim pas és el més important de la llista, i no és una eina: és una persona. La revisió per part d'un altre company és el millor control de qualitat que existeix, millor que ShellCheck, que les proves i que la disciplina pròpia. Troba el que les eines no veuen: que el llindar està mal triat, que l'script assumeix un directori que només existeix a la teva màquina, que aquell rm -rf no està tan acotat com sembla. Deu minuts de revisió estalvien una guàrdia nocturna.
Errors Habituals i Consells
- Començar per
git add .sense.gitignore. És la manera més habitual de pujar un secret. El.gitignoreva abans del primer commit. - Creure que
.gitignoreretira fitxers ja versionats. No ho fa:git rm --cachedés el que els treu. - Esborrar el secret i no rotar-lo. Continua a la història, als clons i a les memòries cau.
git reset --hardsobre commits ja publicats. Trenca el repositori dels altres; per al que està publicat,git revert.- Consell:
git stashper a la interrupció. Desa la feina a mitges, atén la incidència i recupera-la ambgit stash pop. - Consell:
git log -S 'veloz_api_get'busca en quin commit va aparèixer o va desaparèixer una cadena; és la manera ràpida de datar un canvi de comportament.
Exercicis
Exercici 1. Descobreixes que etc/veloz-ops.conf, amb el token de l'API, fa tres commits que està versionat en un repositori compartit amb dos companys. Enumera en ordre les accions i les ordres concretes.
Exercici 2. Escriu el .gitignore del toolkit justificant cada exclusió, i explica què es versiona al seu lloc.
Exercici 3. Has fusionat a master un canvi a vigilant.sh (commit 3b8d201) que provoca alertes falses, i ja hi ha dos commits posteriors d'un altre company. Com el desfàs sense perdre la seva feina?
Solucions
Solució 1. Primer, rotar el token a l'API i invalidar l'antic: és en tres clons i al servidor de Git, i és l'única cosa que talla l'exposició real. Després:
$ printf 'etc/veloz-ops.conf\n' >> .gitignore
$ git rm --cached etc/veloz-ops.conf
$ git add .gitignore etc/veloz-ops.conf.exemple
$ git commit -m "Deixar de versionar la configuracio amb credencials"
$ git pushDesprés reescriure la història amb git filter-repo --path etc/veloz-ops.conf --invert-paths (o BFG), avisant abans els dos companys que hauran de tornar a clonar perquè tots els identificadors de commit canvien. I documentar l'incident, recordant que la reescriptura no substitueix la rotació: si el repositori s'ha compartit, cal assumir que el token és públic.
Solució 2. El de l'apartat 5. etc/veloz-ops.conf, *.key, *.pem i .netrc contenen credencials; logs/ i *.log són sortida regenerable que a més faria créixer el repositori sense límit; *.tmp són temporals de mktemp; dades/ i *.csv són dades de negoci amb informació personal (08-03), que pertanyen a la còpia de seguretat i no al control de versions. Es versiona etc/veloz-ops.conf.exemple perquè documenta quines variables cal definir sense revelar-ne els valors.
Solució 3. Amb git revert, que crea un commit nou desfent exactament els canvis de 3b8d201 i deixa intactes els dos posteriors:
git reset --hard seria un error greu: llençaria també els commits del company i, com que ja estan publicats, obligaria a un push --force que trencaria el seu repositori. Si el revert produeix conflicte perquè els commits posteriors van tocar les mateixes línies, es resol a mà com a l'apartat 9 i s'acaba amb git revert --continue.
Conclusió
Git resol per a un toolkit d'operacions el que les còpies .bak no resolen: què va canviar, qui, quan i per què, i com tornar enrere sense arrossegar la resta. Amb cinc conceptes —repositori, àrea de preparació, commit, branca i remot— n'hi ha prou per treballar: git init, git add, git commit -m, git status --short, git diff i git diff --staged per revisar abans de confirmar, git log --oneline --graph per llegir la història i git blame per saber qui va introduir aquella línia. El primer que s'escriu no és un commit sinó el .gitignore, que deixa fora logs/, temporals, dades i sobretot etc/veloz-ops.conf amb les seves credencials, versionant al seu lloc etc/veloz-ops.conf.exemple; i si un secret ja és a dins, l'ordre és rotar primer, després git rm --cached i després git filter-repo o BFG, sabent que reescriure la història no repara res si el repositori ja s'ha compartit. Els missatges descriuen el canvi i el seu motiu —l'incident que el va provocar—, amb un commit per canvi lògic. Per desfer cal triar bé: git restore descarta edicions, git restore --staged retira de l'àrea de preparació, git revert desfà el que està publicat deixant-ne constància i git reset --hard només es fa servir sobre commits propis no publicats. Les branques (git switch -c) permeten reescriure vigilant.sh sense tocar el que corre cada cinc minuts, amb fusió i resolució manual de conflictes; les etiquetes (git tag -a v1.2) fixen quina versió està desplegada i es combinen amb el desplegament a la flota de 07-06, per git checkout a cada servidor o per rsync excloent .git i la configuració local. El remot —privat i amb clau SSH— és alhora còpia de seguretat i punt de trobada. I el pre-commit automatitza les barreres: bash -n, ShellCheck, Bats i una cerca de secrets, amb la doble advertència que els hooks no es versionen i que --no-verify se'ls salta. Per damunt de tot això queda el control de qualitat més eficaç, que no és una eina: que una altra persona llegeixi el teu canvi abans que arribi a producció.
El hook pre-commit que acabem d'escriure invoca dues ordres que encara no coneixem. La lliçó 08-05 s'ocupa de la primera: ShellCheck, l'analitzador estàtic que troba els errors que aquest curs t'ha ensenyat a evitar —i uns quants més—, juntament amb shfmt per al format uniforme que 08-01 va deixar promès. Recorrerem els avisos més freqüents connectant-los amb la lliçó on es va explicar el problema, aprendrem a silenciar un avís amb criteri i no per comoditat, i passarem ShellCheck als cinc scripts i a lib/comu.sh per classificar i corregir tot el que aparegui.
Curs de Programació en Bash
Mòdul 1: Introducció a Bash
- Què és Bash?
- Configurar el teu Entorn
- Navegació Bàsica per la Línia d'Ordres
- Entendre el Shell
- Trobar Ajuda: man, help i --help
Mòdul 2: Ordres Bàsiques de Bash
- Operacions amb Fitxers i Directoris
- Ordres de Processament de Text
- Permisos i Propietat dels Fitxers
- Redirecció i Canonades
- Comodins i Expansió de Rutes
- Historial i Dreceres de Teclat
Mòdul 3: Fonaments de Scripting
- Crear i Executar un Script
- Variables i Constants
- Operadors Bàsics
- Sentències Condicionals
- Arguments i Entrada de l'Usuari
- Cometes, Expansió i Substitució
Mòdul 4: Scripting Intermedi
- Bucles en Bash
- Funcions en Bash
- Arrays i Arrays Associatius
- Manipulació de Cadenes
- La Sentència case i els Menús Interactius
- Aritmètica i Càlculs Numèrics
Mòdul 5: Tècniques Avançades de Scripting
- Operacions Avançades amb Fitxers
- Gestió de Processos
- Gestió d'Errors i Depuració
- Expressions Regulars
- Entrada/Sortida Avançada: Descriptors i Here-Documents
- Scripts Modulars i Llibreries Reutilitzables
Mòdul 6: Treballar amb Eines Externes
Mòdul 7: Automatització i Programació
- Tasques Cron
- Automatitzar Tasques
- Scripts de Còpia i Restauració
- Monitoratge i Registre
- Serveis i Temporitzadors amb systemd
- Automatització Remota amb SSH
Mòdul 8: Bones Pràctiques i Optimització
- Escriure Codi Llegible
- Optimitzar Scripts en Bash
- Consideracions de Seguretat
- Control de Versions amb Git
- Anàlisi Estàtica amb ShellCheck i shfmt
- Proves Automatitzades amb Bats
- Portabilitat: POSIX sh enfront de Bashismes
