Algunes d’aquestes configuracions també es poden especificar per a una ruta, de manera que Git apliqui aquestes configuracions només per a un subdirectori o un subconjunt de fitxers.
Aquestes configuracions específiques de ruta s’anomenen atributs de Git i es configuren en un fitxer .gitattributes en un dels vostres directoris (normalment l’arrel del vostre projecte) o en el fitxer .git/info/attributes si no voleu que el fitxer d’atributs es commitegi amb el vostre projecte.
Utilitzant atributs, podeu fer coses com especificar estratègies de fusió separades per a fitxers o directoris individuals en el vostre projecte, dir a Git com fer diff de fitxers no text, o fer que Git filtri el contingut abans de revisar-lo o treure’l de Git. En aquesta secció, aprendreu sobre alguns dels atributs que podeu configurar en les vostres rutes en el vostre projecte Git i veureu alguns exemples d’ús d’aquesta característica en la pràctica.
Un truc interessant per al qual podeu utilitzar els atributs de Git és dir a Git quins fitxers són binaris (en casos en què no pugui determinar-ho) i donar a Git instruccions especials sobre com gestionar aquests fitxers. Per exemple, alguns fitxers de text poden ser generats per màquina i no ser difusibles, mentre que alguns fitxers binaris es poden difusar. Veureu com dir a Git quins són quins.
Alguns fitxers semblen fitxers de text però, per a tots els efectes, s’han de tractar com a dades binàries.
Per exemple, els projectes Xcode a macOS contenen un fitxer que acaba en .pbxproj, que bàsicament és un conjunt de dades JSON (format de dades de text pla de JavaScript) escrit al disc per l’IDE, que registra les vostres configuracions de compilació, etc.
Tot i que tècnicament és un fitxer de text (perquè tot és UTF-8), no voleu tractar-lo com a tal perquè realment és una base de dades lleugera: no podeu fusionar el contingut si dues persones el canvien, i els diffs generalment no són útils.
El fitxer està destinat a ser consumit per una màquina.
En essència, voleu tractar-lo com un fitxer binari.
Per dir a Git que tracti tots els fitxers pbxproj com a dades binàries, afegiu la següent línia al vostre fitxer .gitattributes:
*.pbxproj binaryAra, Git no intentarà convertir o corregir problemes de CRLF; ni intentarà calcular o imprimir un diff per als canvis en aquest fitxer quan executeu git show o git diff en el vostre projecte.
També podeu utilitzar la funcionalitat d’atributs de Git per difusar efectivament fitxers binaris. Ho feu dient a Git com convertir les vostres dades binàries a un format de text que es pugui comparar mitjançant el diff normal.
Primer, utilitzareu aquesta tècnica per resoldre un dels problemes més molests coneguts per la humanitat: el control de versions de documents de Microsoft Word.
Si voleu controlar les versions de documents de Word, podeu posar-los en un repositori Git i commitejar de tant en tant; però de què serveix això?
Si executeu git diff normalment, només veieu alguna cosa com això:
$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 88839c4..4afcb7c 100644
Binary files a/chapter1.docx and b/chapter1.docx differNo podeu comparar directament dues versions a menys que les treieu i les escaneu manualment, oi?
Resulta que podeu fer això força bé utilitzant atributs de Git.
Poseu la següent línia al vostre fitxer .gitattributes:
*.docx diff=wordAixò diu a Git que qualsevol fitxer que coincideixi amb aquest patró (.docx) ha d’utilitzar el filtre “word” quan intenteu veure un diff que contingui canvis.
Què és el filtre “word”?
Heu de configurar-lo.
Aquí configureu Git per utilitzar el programa docx2txt per convertir documents de Word en fitxers de text llegibles, que després difusarà correctament.
Primer, heu d’instal·lar docx2txt; podeu descarregar-lo des de https://sourceforge.net/projects/docx2txt.
Seguiu les instruccions del fitxer INSTALL per posar-lo en un lloc on la vostra shell el pugui trobar.
A continuació, escriureu un script d’envoltori per convertir la sortida al format que Git espera.
Creeu un fitxer que estigui en alguna part del vostre camí anomenat docx2txt, i afegiu aquest contingut:
#!/bin/bash
docx2txt.pl "$1" -No us oblideu de fer chmod a+x en aquest fitxer.
Finalment, podeu configurar Git per utilitzar aquest script:
$ git config diff.word.textconv docx2txtAra Git sap que si intenta fer un diff entre dues instantànies, i alguns dels fitxers acaben en .docx, ha d’executar aquests fitxers a través del filtre “word”, que està definit com el programa docx2txt.
Això efectivament crea versions basades en text dels vostres fitxers Word abans d’intentar difusar-los.
Aquí teniu un exemple: el Capítol 1 d’aquest llibre es va convertir al format Word i es va commitejar en un repositori Git.
Llavors es va afegir un nou paràgraf.
Aquí teniu el que mostra git diff:
$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 0b013ca..ba25db5 100644
--- a/chapter1.docx
+++ b/chapter1.docx
@@ -2,6 +2,7 @@
Aquest capítol tractarà sobre com començar amb Git. Començarem des del principi explicant alguns antecedents sobre les eines de control de versions, després passarem a com posar en marxa Git al vostre sistema i finalment com configurar-lo per començar a treballar. Al final d'aquest capítol hauríeu d'entendre per què Git està al voltant, per què l'heu d'utilitzar i hauríeu d'estar tots configurats per fer-ho.
1.1. Sobre el Control de Versions
Què és el "control de versions" i per què us hauria d'importar? El control de versions és un sistema que registra els canvis en un fitxer o un conjunt de fitxers al llarg del temps per poder recordar versions específiques més endavant. Per als exemples d'aquest llibre utilitzareu codi font de programari com els fitxers que es controlen de versions, tot i que en realitat podeu fer això amb gairebé qualsevol tipus de fitxer en un ordinador.
+Prova: 1, 2, 3.
Si sou un dissenyador gràfic o web i voleu mantenir cada versió d'una imatge o disseny (el que sens dubte voldríeu fer), un Sistema de Control de Versions (VCS) és una cosa molt savia d'utilitzar. Us permet revertir fitxers a un estat anterior, revertir tot el projecte a un estat anterior, comparar canvis al llarg del temps, veure qui va modificar alguna cosa que podria estar causant un problema, qui va introduir un problema i quan, i més. Utilitzar un VCS també generalment significa que si ho feu malbé o perdeu fitxers, podeu recuperar-los fàcilment. A més, obteniu tot això amb molt poca sobrecàrrega.
1.1.1. Sistemes de Control de Versions Locals
El mètode de control de versions triat per moltes persones és copiar fitxers en un altre directori (potser un directori amb marca de temps, si són llestos). Aquest enfocament és molt comú perquè és tan simple, però també és increïblement propens a errors. És fàcil oblidar en quin directori esteu i escriure accidentalment en el fitxer equivocat o copiar fitxers que no voleu.Git ens diu amb èxit i succintament que hem afegit la cadena “Prova: 1, 2, 3.”, el que és correcte. No és perfecte: els canvis de format no es mostrarien aquí, però sens dubte funciona.
Un altre problema interessant que podeu resoldre d’aquesta manera implica la difusió de fitxers d’imatge.
Una manera de fer això és executar fitxers d’imatge a través d’un filtre que extreu la seva informació EXIF: metadades que es registren amb la majoria de formats d’imatge.
Si descarregueu i instaleu el programa exiftool, podeu utilitzar-lo per convertir les vostres imatges en text sobre les metadades, de manera que almenys el diff us mostri una representació textual de qualsevol canvi que hagi ocorregut.
Poseu la següent línia al vostre fitxer .gitattributes:
*.png diff=exifConfigureu Git per utilitzar aquesta eina:
$ git config diff.exif.textconv exiftoolSi replaceu una imatge al vostre projecte i executeu git diff, veieu alguna cosa com això:
diff --git a/image.png b/image.png
index 88839c4..4afcb7c 100644
--- a/image.png
+++ b/image.png
@@ -1,12 +1,12 @@
ExifTool Version Number: 7.74
-File Size: 70 kB
-File Modification Date/Time: 2009:04:21 07:02:45-07:00
+File Size: 94 kB
+File Modification Date/Time: 2009:04:21 07:02:43-07:00
File Type: PNG
MIME Type: image/png
-Image Width: 1058
-Image Height: 889
+Image Width: 1056
+Image Height: 827
Bit Depth: 8
Color Type: RGB with AlphaPodeu veure fàcilment que tant la mida del fitxer com les dimensions de la imatge han canviat.
L’expansió de paraules clau a l’estil SVN o CVS sovint és sol·licitada per desenvolupadors acostumats a aquests sistemes. El principal problema amb això a Git és que no podeu modificar un fitxer amb informació sobre el commit després d’haver commitejat, perquè Git calcula la suma de comprovació del fitxer primer. No obstant això, podeu injectar text en un fitxer quan es treu i eliminar-lo abans que s’afegeixi a un commit. Els atributs de Git us ofereixen dues maneres de fer això.
Primer, podeu injectar la suma de comprovació SHA-1 d’un blob en un camp $Id$ al fitxer automàticament.
Si configureu aquest atribut en un fitxer o un conjunt de fitxers, llavors la propera vegada que treieu aquesta branca, Git reemplaçarà aquest camp amb el SHA-1 del blob.
És important notar que no és el SHA-1 del commit, sinó del blob en si.
Poseu la següent línia al vostre fitxer .gitattributes:
*.txt identAfegiu una referència $Id$ a un fitxer de prova:
$ echo '$Id$' > test.txtLa propera vegada que treieu aquest fitxer, Git injectarà el SHA-1 del blob:
$ rm test.txt
$ git checkout -- test.txt
$ cat test.txt
$Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $No obstant això, aquest resultat és d’utilitat limitada. Si heu utilitzat substitució de paraules clau a CVS o Subversion, podeu incloure una marca de temps: el SHA-1 no és gaire útil, perquè és bastant aleatori i no podeu dir si un SHA-1 és més antic o més nou que un altre només mirant-los.
Resulta que podeu escriure els vostres propis filtres per fer substitucions en fitxers en commit/checkout.
Aquests s’anomenen filtres “clean” i “smudge”.
Al fitxer .gitattributes, podeu configurar un filtre per a rutes particulars i després configurar scripts que processaran fitxers just abans que es treuin (“smudge”, vegeu El filtre “smudge” s’executa en checkout) i just abans que es posin en escena (“clean”, vegeu El filtre “clean” s’executa quan els fitxers es posen en escena).
Aquests filtres es poden configurar per fer tot tipus de coses divertides.
El missatge de commit original per a aquesta característica dona un exemple simple d’execució de tot el vostre codi font C a través del programa indent abans de commitejar.
Podeu configurar-ho configurant l’atribut de filtre al vostre fitxer .gitattributes per filtrar fitxers \*.c amb el filtre “indent”:
*.c filter=indentLlavors, digueu a Git què fa el filtre “indent” en smudge i clean:
$ git config --global filter.indent.clean indent
$ git config --global filter.indent.smudge catEn aquest cas, quan commiteu fitxers que coincideixen amb *.c, Git els executarà a través del programa indent abans de posar-los en escena i després els executarà a través del programa cat abans de tornar-los a treure al disc.
El programa cat no fa res essencialment: escup les mateixes dades que entren.
Aquesta combinació efectivament filtra tots els fitxers de codi font C a través d'`indent` abans de commitejar.
Un altre exemple interessant obté l’expansió de paraules clau $Date$, a l’estil RCS.
Per fer això correctament, necessiteu un petit script que prengui un nom de fitxer, descobreixi l’última data de commit per a aquest projecte i inserisca la data al fitxer.
Aquí teniu un petit script Ruby que fa això:
#! /usr/bin/env ruby
data = STDIN.read
last_date = `git log --pretty=format:"%ad" -1`
puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')Tot el que fa l’script és obtenir l’última data de commit del comandament git log, posar aquesta data en qualsevol cadena $Date$ que vegi a stdin, i imprimir els resultats: hauria de ser simple fer-ho en qualsevol llenguatge amb el qual us sentiu més còmode.
Podeu anomenar aquest fitxer expand_date i posar-lo al vostre camí.
Ara, heu de configurar un filtre a Git (anomeneu-lo dater) i digueu-li que utilitzi el vostre filtre expand_date per difuminar els fitxers en checkout.
Utilitzareu una expressió Perl per netejar això en commit:
$ git config filter.dater.smudge expand_date
$ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'Aquest tros de Perl elimina qualsevol cosa que vegi en una cadena $Date$, per tornar al punt de partida.
Ara que el vostre filtre està llest, podeu provar-lo configurant un atribut Git per a aquest fitxer que engageu el nou filtre i creant un fitxer amb la vostra paraula clau $Date$:
date*.txt filter=dater$ echo '# $Date$' > date_test.txtSi commiteu aquests canvis i torneu a treure el fitxer, veieu la paraula clau substituïda correctament:
$ git add date_test.txt .gitattributes
$ git commit -m "Prova d'expansió de data a Git"
$ rm date_test.txt
$ git checkout date_test.txt
$ cat date_test.txt
# $Date: Tue Apr 21 07:26:52 2009 -0700$Podeu veure com aquesta tècnica pot ser poderosa per a aplicacions personalitzades.
No obstant això, heu de tenir cura, perquè el fitxer .gitattributes es commiteix i es passa amb el projecte, però el controlador (en aquest cas, dater) no ho és, així que no funcionarà a tot arreu.
Quan dissenyeu aquests filtres, han de poder fallar elegantment i el projecte encara ha de funcionar correctament.
Les dades d’atributs de Git també us permeten fer algunes coses interessants quan exporteu un arxiu del vostre projecte.
Podeu dir a Git que no exporti certs fitxers o directoris quan generi un arxiu.
Si hi ha un subdirectori o fitxer que no voleu incloure al vostre fitxer d’arxiu però que voleu que es commitegi al vostre projecte, podeu determinar aquests fitxers mitjançant l’atribut export-ignore.
Per exemple, suposem que teniu alguns fitxers de prova en un subdirectori test/, i no té sentit incloure’ls a l’exportació tarball del vostre projecte.
Podeu afegir la següent línia al vostre fitxer d’atributs Git:
test/ export-ignoreAra, quan executeu git archive per crear un tarball del vostre projecte, aquest directori no s’inclourà a l’arxiu.
En exportar fitxers per a desplegament, podeu aplicar el format i el processament d’expansió de paraules clau de git log a porcions seleccionades de fitxers marcats amb l’atribut export-subst.
Per exemple, si voleu incloure un fitxer anomenat LAST_COMMIT al vostre projecte, i voleu que les metadades sobre l’últim commit s’injectin automàticament quan s’executa git archive, podeu, per exemple, configurar els vostres fitxers .gitattributes i LAST_COMMIT d’aquesta manera:
LAST_COMMIT export-subst$ echo 'Data de l'últim commit: $Format:%cd per %aN$' > LAST_COMMIT
$ git add LAST_COMMIT .gitattributes
$ git commit -am 'afegint fitxer LAST_COMMIT per a arxius'Quan executeu git archive, el contingut del fitxer arxivat es veurà així:
$ git archive HEAD | tar xCf ../deployment-testing -
$ cat ../deployment-testing/LAST_COMMIT
Data de l'últim commit: Tue Apr 21 08:38:48 2009 -0700 per Scott ChaconLes substitucions poden incloure, per exemple, el missatge de commit i qualsevol git notes, i git log pot fer un ajust de línia simple:
$ echo '$Format:Últim commit: %h per %aN a %cd%n%+w(76,6,9)%B$' > LAST_COMMIT
$ git commit -am 'export-subst utilitza el formatador personalitzat de git log'
git archive utilitza el processador `pretty=format:` de git log
directament, i elimina el marcador `$Format:` i `$` circumdant de la sortida.
'
$ git archive @ | tar xfO - LAST_COMMIT
Últim commit: 312ccc8 per Jim Hill a Fri May 8 09:14:04 2015 -0700
export-subst utilitza el formatador personalitzat de git log
git archive utilitza el processador `pretty=format:` de git log directament, i
elimina el marcador `$Format:` i `$` circumdant de la sortida.L’arxiu resultant és adequat per a treballs de desplegament, però com qualsevol arxiu exportat, no és adequat per a treballs de desenvolupament addicionals.
També podeu utilitzar els atributs de Git per dir a Git que utilitzi diferents estratègies de fusió per a fitxers específics al vostre projecte. Una opció molt útil és dir a Git que no intenti fusionar fitxers específics quan tenen conflictes, sinó que utilitzi el vostre costat de la fusió sobre el d’algú altre.
Això és útil si una branca del vostre projecte ha divergit o està especialitzada, però voleu poder fusionar canvis des d’ella, i voleu ignorar certs fitxers.
Suposem que teniu un fitxer de configuració de base de dades anomenat database.xml que és diferent en dues branques, i voleu fusionar l’altra branca sense fer malbé el fitxer de base de dades.
Podeu configurar un atribut com aquest:
database.xml merge=oursI llavors definir una estratègia de fusió ours fictícia amb:
$ git config --global merge.ours.driver trueSi fusionau l’altra branca, en lloc de tenir conflictes de fusió amb el fitxer database.xml, veieu alguna cosa com això:
$ git merge topic
Auto-merging database.xml
Merge made by recursive.En aquest cas, database.xml es queda a la versió que originalment teníeu.

