administració de servidors i git

Fins que no proves les coses no te n’adones de lo difícil, o fàcil, que és fer-les…

Avui havia de fer uns canvis a un dels servidors de la feina i com que eren temes de configuració … cd /etc

Però abans de prémer cap més tecla m’ho he pensat dues vegades i he teclejat unes quantes ordres ben senzilles i  molt útils de cara al futur:

Control de versions de la configuració d’un servidor

Sembla que pugui ser una cosa difícil, que requereixi molt de temps i que sigui complex de mantenir oi? Doncs res més senzill que fer:

cd /etc
git init
(opcionalment vim .gitignore per excloure els fitxers que no volem versionar)
git add -A
git commit -m"Configuració inicial que funciona del servidor"

Només amb aquestes senzilles ordres ja tenim tot el directori /etc versionat amb git. A partir d’ara qualsevol canvi a qualsevol fitxer que estigui dintre de /etc ens sortirà amb un git status i quan haguem fet les proves necessàries per assegurar que els canvis són correctes ja podrem fer un git commit FITXER1 FITXER2 -m”Missatge” per tenir controlada una nova revisió dels fitxers.

Ara ja no hi ha excusa per dir que s’ha perdut alguna configuració o que s’ha espatllat algun servei del servidor, sempre tindràs un git checkout o un git reset –hard HEAD per tornar a una versió dels fitxers de configuració correcta :)

git stash

Una de les primeres coses que descobreixes quan utilitzes git és que de la mateixa manera que un mediawiki, per posar un exemple, hi ha mil i una maneres de treballar-hi:

Tot amb branques, arbres remots a github, via pedaços (com se solia anar amb subversion i cvs) …

De manera que igual com amb un mediawiki el més important és definir una bona guia d’estil, les plantilles i el sistema de categorització, treballant amb el git, el més important és definir dintre de l’equip de treball un bon cicle de treball per tal que no hi hagi diverges

I és aquí on entra l’ordre git stash.

Un exemple ben fàcil: tens canvis a 5 fitxers diferents, fas un commit per a tres d’ells perquè els altres dos encara no estan llestos per enviar.  Si en aquell moment vols fer un git pull –rebase perquè el servidor de git és un servidor central i vols agafar els últims canvis i aplicar-hi els teus commits locals a sobre de les últimes actualitzacions, el git no et deixarà fer-ho, ja que hi ha canvis sense estar en un commit.

No pots fer-ne un commit perquè no estan acabats, de manera que el que pots fer és un git stash, que senzillament desa els canvis que no estan a cap commit i et deixa l’arbre sense cap fitxer que no estigui en un commit, de manera que ja pots fer un git pull –rebase i si tot va bé un git push per enviar els teus commits locals.

Ja només et queda fer un git stash pop per recuperar els canvis que tens que no estan a cap commit i continuar treballant tranquilament :)

Evidentment, com tota eina de git, el git stash et permet fer moltíssimes coses més, de fet per tal com es recupera la sessió desada (git stash pop) ja podeu veure que el git stash funciona com una pila, de manera que pots tenir tants stash com necessiteu ((No exempt de perill que després no funcionin sobre el commit en el que esteu treballant)) i aplicar-los a altres branques, o crear branques a partir dels stash, etc etc …

Permisos per compartir un repositori de git

Un dels problemes de tenir un repositori en un servidor central és com de costum el tema dels permisos, per una banda has de tenir els usuaris creats en local, afegir-los en el mateix grup perquè cadascú pugui accedir als repositoris i finalment un cop està tot apunt tens el problema (amb solució!) de que quan algú fa un commit la resta no en poden fer ja que s’han canviat els permisos.

A primer cop d’ull penses que això amb un hook de git i un script que faci un chown ja n’hi pot haver prou, després ho rumies una mica més i penses que no hauria de ser tant complicat i arribes a la idea que l’umask serà el teu amic … però al final cerques una mica per Internet i et trobes amb una solució molt més elegant:

$ git repo-config core.sharedRepository true

Amb aquesta senzilla ordre executada per a tots i cadascun dels repositoris que vulguis compartir entre més d’un desenvolupador i llestos, a programar que és el que ens agrada.

submòduls a git

Sempre hi ha aquells casos en que tot i tenir un sol codi font s’utilitzen diversos altres codis font que tenen la seva existència per separat però que són necessaris dintre del projecte.

A subversion existeixen els externals i a git hi ha els submòduls. Treballen de forma diferent i per tant no es poden comparar exactament (tot i que el concepte és el mateix), ja que per exemple a subversion assumeixen que sempre vols actualitzar el codi de tots els submòduls i en canvi a git ho has de forçar tu manualment, si això és un avantatge o un inconvenient ja depèn de cada projecte en concret.

Per si hi heu de treballar des de git el capítol sobre submòduls del llibre del Git és perfecte (de fet l’he seguit punt per punt per fer-ho al projecte que tinc ara entre mans).

etiquetes a git

Això del git està molt bé, però com tot té la seva corba d’aprenentatge :)

Avui ha tocat indagar en les etiquetes (tags). N’hi ha de tres tipus:

  • Senzilles
  • Anotades
  • Signades

Primer la versió ràpida i fàcil:

$ git tag NOM_ETIQUETA

$ git tag NOM_ETIQUETA SHA1

Creem una etiqueta amb el nom NOM_ETIQUETA i si es dóna el cas que no la volem fer en el commit en que està ara mateix el repositori local on estem treballant hi afegim el SHA1 del commit (amb un git log, o interfície web el trobem de seguida).

Per saber les etiquetes hi ha:

$ git tag -l -n1

Amb això mostrem totes les etiquetes, l’opció -l, i de pas també mostra el missatge del commit (en el cas de les etiquetes anotades també mostra l’anotació), l’opció -n1.

Un cop hem etiquetat tots els commits que ens sembli ja podem enviar els canvis (en cas que s’hagin d’enviar a algun lloc, estil git.gnome.org):

$ git push –tags

Fàcil eh :)

Si us equivoqueu també les podeu suprimir:

$ git tag -d NOM_ETIQUETA

I si ja l’havíeu enviat l’heu de suprimir en remot:

$ git push origin :refs/tags/NOM_ETIQUETA

Les etiquetes anotades tenen la particularitat que a més del nom que li donem a l’etiqueta també li afegim un comentari (l’anotació vaja).

Per crear-la:

$ git tag -a -m”ANOTACIÓ DE L’ETIQUETA” NOM_ETIQUETA

La resta funciona igual (enviar, llistar, suprimir, etc).

L’última opció de crear una etiqueta és la que en certs projectes té molt sentit. Les etiquetes signades permeten no només etiquetar un commit en concret de l’historial del repositori sinó que a més a més les pots signar amb una clau OpenPG, d’aquesta manera, si t’has de baixar el codi font del nucli de Linux i en vols estar 100% segur que ningú l’ha tocat ho pots saber comprovant que la signatura del commit de l’etiqueta signada correspon a en Linus Tolvards :)

migrar de subversion a git a-la-GNOME

Avui al final m’he decidit a fer la migració d’algunes coses que tenim encara a la feina que estan amb subversion i passar-les a git.

Ja feia uns dies havia trobat una petita guia per fer la migració ((De fet ja ho havia comentat per identi.ca :D)), però avui quan m’hi he posat m’he trobat que no em funcionava tal com jo volia.

No és que el repositori de git no el deixés funcionant correctament, sinó que com que tot i que sigui un scm descentralitzat tenim un servidor on hi ha el codi, etc etc no deixava el repositori en el mateix format.

Després de donar-hi unes quantes voltes m’he adonat que el que estava intentant fer era migrar de subversion a git amb els mateixos propòsits i casos d’ús que el GNOME, així que després de buscar una mica he arribat a la guia de migració del GNOME que m’ha portat a una pàgina personal en el wiki del GNOME on s’explica com fer el canvi de format dels repositoris.

I ara sí, ja puc clonar els repositoris del servidor amb total llibertat :)

Pels curiosos, aquest és l’script que he utilitzat (un mix de les dues solucions apuntades abans):

mkdir NOM-REPOSITORI.git
cd NOM-REPOSITORI.git
git –bare init
git –bare svn init https://servidor.codi.org/subversion/REPOSITORI –no-metadata
git config svn.authorsfile /git/users.txt*
git –bare svn fetch

* S’ha de crear un fitxer amb una línia per autor a l’estil: nom.usuari = Nom Real <correu@electronic.org>

P.D. Tot buscant informació sobre la migració i tot plegat he arribat a una entrada d’un bloc on hi havia la frase “You don’t branch because you don’t use git” ((No crees branques perquè no utilitzes git)) i la veritat és que té molta raó la frase, el canvi de subversion a git, entre moltes d’altres millores és que hi ha gestió de branques i no una simple recreació d’arbres de directoris sense cap mena de control per part del sistema de control de versions, a veure com em va!

crear un dipòsit de git remot

git-logoAra que el git s’utilitza a molts projectes importants va bé saber com muntar-se el teu propi servidor de git.

A grans trets són 3 pasos diferenciats: crear el dipòsit en el servidor, iniciar el dipòsit en el servidor local i finalment com s’utilitza en un ordinador qualsevol.

Crear el dipòsit en el servidor

Creem un directori ((a on ens sembli del sistema de fitxers, l’únic en que afecta és en l’URL que ens quedarà pera  poder-hi accedir)) i hi entrem:

mkdir /home/git/DIPOSIT.git
cd /home/git/DIPOSIT.git

Iniciem el dipòsit de git:

git --bare init

Amb això ja tenim creat un dipòsit de git apunt per a que s’hi enviïn els primers canvis

Crear un dipòsit local per a iniciar el dipòsit del servidor

Creem un directori on  ens sembli i hi entrem:

mkdir ~/Escriptori/DIRECTORI
cd ~/Escriptori/DIRECTORI

Iniciem el dipòsit:

git init

Afegim els fitxers que volem que estiguin en el dipòsit i un cop ja hi són tots:

git add -A ((fins ara no m'havia adonat que era en majúscula))
git commit -a -m"Primer commit"

Un cop ja tenim els fitxers li diem quin és el dipòsit remot on s’hauran d’enviar:

git remote add origin ssh://USUARI@servidor/home/git/DIPOSIT.git

Enviem els canvis que ja hem fet:

git push origin master

I amb això ja tenim un dipòsit de git iniciat en el servidor i amb els continguts que hi acabem d’enviar. Aquest directori que hem creat en aquest segon pas es pot esborrar.

Clonar el dipòsit en remot

El pas més curt i més coneguts per tothom:

git clone ssh://USUARI@servidor/home/git/DIPOSIT.git

I ja podem fer públic l’URL per a accedir als dipòsits a qualsevol que tingui accés ((em falta mirar com s’ha de fer per permetre també l’accés a través d’HTTP sense necessitar un usuari en el servidor, alguna idea/web on s’expliqui?)).

git tip: git reset –hard

git-logoSi mai us trobeu treballant amb un codi que utilitza git com a control de versions i quan canvieu de branques, feu cherry-pick o altres operacions i deixeu l’arbre en un estat que no teniu manera de deixar-lo net, utilitzeu el títol d’aquest missatge!

Amb això el que fareu és fer que l’índex de l’última revisió sigui l’índex dels canvis actuals (o sigui cap canvi) i s’esborrin tots els canvis que hi hagi fets en tot l’arbre.

Tirar enrere commits locals en git

git-logoQuan esteu treballant en una traducció i potser esteu a mig fer-la potser us ha passat que us comenten o us adoneu de la manera que sigui que hi ha noves cadenes o se n’han canviat algunes, de manera que us cal actualitzar el codi per a poder després actualitzar la traducció.

Si esteu amb Git com a control de versions el que aniríeu a fer és fer un git pull per a actualitzar el codi, però ràpidament us adonareu que no podeu, ja que us dirà que hi ha fitxers els canvis dels quals no estan registrats (no s’ha fet el commit) en el git.

Al tractar-se d’una traducció, la qual no té massa sentit fer-ne diferents commits per fer-ne la traducció sembla que perdem flexibilitat …

Doncs per sort no! (i perdó per la llarga introducció :D

El truc està en que es fa un commit local (sense enviar-lo al servidor central), després actualitzem normalment amb git pull i finalment fem:

git reset –mixed HEAD^

Amb el git reset podem canviar l’estat del cap actual, d’aquesta manera amb l’ordre de sobre aquesta línia el que li estem dient és que desfaci el commit però que deixi aplicats els canvis de manera que només haguem de fer el commit de nou i pujar-ho.

git-clean (1)

git-logoA vegades després de compilar un programa que t’has baixat per exemple de git.gnome.org vols tornar a deixar-ho tot tal com estava (o sigui una còpia igual del que hi ha publicat a git.gnome.org).

En aquestes ocacions, si el sistema de control de versions és el git només heu de fer:

# per veure què es netejarà
git clean -n
# per eliminar aquests fitxers
git clean -f
# si també voleu eliminar els directoris que s'hagin pogut crear
git clean -fd

I amb això ja estarà tot net com una patena :)