summaryrefslogtreecommitdiff
path: root/eu/2.md
diff options
context:
space:
mode:
Diffstat (limited to 'eu/2.md')
-rw-r--r--eu/2.md1026
1 files changed, 1026 insertions, 0 deletions
diff --git a/eu/2.md b/eu/2.md
new file mode 100644
index 0000000..a4e64d1
--- /dev/null
+++ b/eu/2.md
@@ -0,0 +1,1026 @@
+---
+title: GIT — EITB 2022
+subtitle: Erabilera aurreratua
+license: CC-BY-SA 4.0
+author: Ekaitz Zarraga - ElenQ Technology
+links-as-notes: true
+lang: basque
+polyglossia-lang:
+ name: basque
+how-to: pandoc -f markdown+smart -t beamer % -o pdf/2.pdf --pdf-engine=xelatex --template=./template.tex
+...
+
+## Lizentzia
+
+- CC-BY-SA 4.0
+- Dokumentu honen edukiak eta irudiak [**Pro Git (Scott Chacon, Ben
+ Straub)**](https://git-scm.com/book/en/v2) liburutik atera dira.
+
+# Git zerbitzarian
+
+## Git zerbitzarian: sarrera
+
+Lankideen artean kodea partekatzeko zerbitzari bat izatea ideia ona da: beti
+dago eskuragarri, kudeaketa sinplifikatzen du, etab.
+
+Zerbitzarietan *bare repository*-ak erabiltzen dira. Hauek ez dute *working
+directory*-rik. `.git` direktorioan dagoena bakarrik dute.
+
+- `git init --bare` *bare repository* bat eratzeko.
+
+## Protokoloak
+
+Protokolo ezberdinak erabili daitezke repositorioen arteko komunikazioa
+egiteko:
+
+- **Local**: beste fitxategi batean dagoen repositorioa. `git clone
+ /path/to/file`-en bitartez klonatu daiteke.
+- **HTTP**: *smart* edo *dumb* moduak ditu. *Smart*-ek baimenak kudeatu ditzake.
+ *Dumb*-ek fitxategiak eman baino ez du egiten.
+- **SSH**: Askotan erabiltzen da. Erabiltzaile bat behar du.
+ `git clone ssh://[<user>@]<host>/<project>.git` erabiliz. SCP-ren modu
+ laburra erabili daiteke: `[<user>@]<host>:<project>.git`.
+- **Git**: SSH-ren antzekoa da baina autentikazio barik.
+
+## Protokoloak — Adibide bat
+
+Nire [zerbitzaria](https://git.elenq.tech/):
+
+- Web bitartez proiektuak aztertu daitezke. `cgit` erabiltzen du. Beste aukera
+ batzuk daude: `gitweb` adibidez, Git-ekin datorrena.
+- Proiektu publikoak Git-en bitartez zerbitzatzen dira edonork kopiatu ahal
+ izateko.
+- Idazteko baimena SSH-ren bitartez zerbitzatzen da, baimena kontrolatu ahal
+ izateko.
+
+*Liburuan azaltzen da gauza hauek nola muntatu.*
+
+
+# Git workflowak
+
+## Workflow zentralizatua
+
+Git-en izaera banatuak *workflow* ezberdin asko ahalbidetzen ditu baina gaur
+egun *workflow zentralizatua* erabiltzen da gehien, Web zerbitzu integratuen
+arrakastagatik (Github, Gitlab, Gitea...) non tiketak eta kodea kudeatzeko
+aukera dagoen.
+
+![Bezero guztiak zerbitzariarekin sinkronizatzen dira](img/centralized_workflow.png){ height=140px }
+
+## Email-en bitartez
+
+Software libre proiektu asko oraindik emailean oinarritzen dira aldaketak
+proposatzeko.
+
+- `git format-patch <commit-selektorea>` aukeratutako commitak patch
+ fitxategietan idazteko
+- `git send-email <patch-fitxategiak>` patch-ak emailez bidaltzeko
+ (konfigurazioa behar du)
+- `git am <patch-fitxategiak>` jasotako patch-ak proiektuan commiteatzeko
+- `git apply <patch-fitxategiak>` jasotako patch-ak aldaketa moduan aplikatzeko
+
+
+# Git tresna aurreratuak
+
+## Commit selektoreak
+
+Giten komando asko commit askotan aplikatu daitezke. Gitek commit selektore
+ezberdinak aplikatzea ahalbidetzen du commitak aukeratzeko.
+
+- `git show <commit-selektorea>` aukeratutako objektuak erakusteko
+
+*Ikusi `git show`-n laguntza. Objetu ezberdinak erakutsi ditzake*
+
+*Ikusi `git rev-parse`-n laguntza, selektoreen sintaxia azaltzen baitu.*
+
+
+## Commit selektoreak — I
+
+- **SHA-1 hasha**: commit identifikadorea bera erabili daiteke selektore moduan.
+ Oso luzeak direnez, hasierako karaktereak bakarrik erabili daitezke anbiguoak
+ ez badira. `git log --abbrev-commit` commit id-aren laburpena egiten du.
+
+- **Adarren burua**: adarraren izena erabiltzean, adarraren buruaren commita
+ aukeratzen da: `git show <adarra>`. Adarraren buruaren commit id-a
+ ateratzeko: `git rev-parse <adarra>`.
+
+- **Reflog-a**: Reflog-a repositorioaren egoera gordetzen du historiko baten
+ modura. Reflog-aren sarreren izenak erabili daitezke commit selektore moduan.
+ Gainera denbora erabili daiteke: `HEAD@{yesterday}`.
+
+ - `git reflog` reflog-aren sarrerak erakusteko
+
+## Commit selektoreak — II
+
+- **Gurasoak**: aukeratutako commiten gurasoak eta aitzindariak lortu daitezke:
+
+ - Txapela (`^`) erabiliz aukeratutako commitaren gurasoak lortu daitezke.
+ Adibidez: `git show HEAD^`. Merge commitetan (guraso asko dituztenak)
+ gurasoen artean aukeratzeko `^` eta gero gurasoaren zenbakia jarri
+ daiteke guraso konkretua lortzeko.
+ - Tildea (`~`) erabiliz aitzindariak lortu daitezke. Zenbaki bat gehituta
+ aurreko aitzindaria lortu daiteke. Adibidez `git show HEAD~2`: aurreko
+ commitaren aurrekoa lortu.
+
+## Commit selektoreak — III
+
+- **Commit tartea**: bi commiten arteko tartea lortzeko: `..`
+ Adarrekin ere egin daiteke, adar batetik besteraren burura ailegatzeko behar
+ diren commitak lortzeko:
+ ![](img/double-dot.png){width=350px}
+ - `git log master..experiment` => D C
+ - `git log experiment..master` => F E
+
+## Commit selektoreak — IV
+
+- **Puntu tripleak**: bi adarretatik ailegatu ahal diren commitak, baina
+ amankomunean ez daudenak:
+ ![](img/double-dot.png){width=350px}
+ - `git log master...experiment` => F E D C
+ - Zein adarretik datozen ikusteko `--left-right`:
+ ```
+ git log master...experiment --left-right
+ < F
+ < E
+ > D
+ > C
+ ```
+
+## Commit selektoreak — V
+
+- **Puntu multipleak**: eskaera konplexuagoak egiteko `^` (aurretik) edo
+ `--not` erabili daiteke, adar horren commitak baztertzeko:
+ - Hurrengo komandoak baliokideak dira:
+ ```
+ git log refA..refB
+ git log ^refA refB
+ git log refB --not refA
+ ```
+ - Hurrengo komandoek `refA`tik eta `refB`tik lortu daitezkeen commitak
+ hartzen dituzte, `refC`tik lortu daitezkeenak baztertuz:
+ ```
+ git log refA refB ^refC
+ git log refA refB --not refC
+ ```
+
+## Staging interaktiboa
+
+- `git add --interactive|-i` stage-a modu interaktiboan kudeatzeko
+- `git add --patch|-p` gehituko diren aldaketak modu interaktiboan
+ aukeratzeko. Blokez bloke
+
+*Komando askotan erabili daitezken aukerak dira hauek.
+Oso erabilgarriak dira.*
+
+## Stash-a
+
+Aldaketak gordetzeko zaku bat da *stash*a. Trakeatu gabeko aldaketak bertan
+sartu daitezke repositoria aldatu/berriztu/mergeatu eta gero aldaketak berriro
+adar berdinean edo beste batean ateratzeko.
+
+- `git stash [push]` direktorioa garbitu eta aldaketak *stash*era sartzeko
+- `git stash list` *stash*aren sarrerak ikusteko
+- `git stash apply [<stash-sarrera>]`-k aukeratutako sarrera (defektuz
+ azkena) aplikatzen dio *working directory*ari.
+- `git stash drop [<stash-sarrera>]` aukeratutako *stash* sarrera ezabatzeko
+- `git stash pop` = `git stash apply` + `git stash drop`
+
+*Push* eta *pop* izenak erabiltzen dira *stash*a LIFO ilara edo stack baten
+moduan kudeatzen delako. *Gainetik gehitu eta gainetik atera*
+
+## Stash-a — Aukera interesgarriak
+
+- `git stash apply --index` egitean *staging area*ra bidaltzen dira *stash*ean
+ *staging area*an zeuden fitxategiak. Defektuz ez dira *stage*era bidaltzen.
+- `git stash --keep-index` indexatutako (*stage*a) fitxategiak ez dira
+ *stash*era gehitzen, eta *stage*ean mantentzen dira.
+- `git stash --include-untracked|-u` trackeatuta ez dauden fitxategiak ere
+ *stash*eatzeratzeko.
+- `git stash --all|-a` baztertutako fitxategiak (`.gitignore`) ere *stash*era
+ gehitzeko
+- `git stash --patch|-p` *stash*eratzeratzeko aldaketak modu interaktiboan
+ aukeratzeko
+- `git stash branch <adar-izena> [<stash-sarrera>]` adar berri bat sortu eta
+ bertan aukeratutako *stash*a aplikatu. Dena ondo badoa *stash*a garbitzen du
+ bukatzerakoan.
+
+## Direktorioa garbitzeko
+
+- `git stash --all` egitea direktorio osoa garbitzen du, hau da, trackeatuta ez
+ dauden fitxategiak eta aldaketak *stash*earatzen ditu.
+- `git clean` egiten antzeko efektu bat lortu daiteke *stash*a erabili gabe,
+ zuzenean aldaketak eta fitxategiak ezabatuz.
+ - `-f` (*force*) beharrezkoa da (defektuz, aukera bat dago desaktibatzeko)
+ nahi gabe ez egiteko
+
+> KONTUZ: `git clean --dry-run|-n` erabili badaezpada, zer egingo duen ikusteko
+> benetan exekutatu baino lehen.
+
+## Sinadurak
+
+Commit faltsuak ekiditeko, commitak sinatu daitezke GPG-ren bitartez.
+
+> GPG (Gnu Privacy Guard), PGP-ren (Pretty Good Privacy) inplementazio bat da.
+
+`user.signkey` konfiguratu behar da.
+
+- `git commit -S` commitak sinatzeko
+- `git tag -s` tagak sinatzeko
+- `git merge --verify-signatures` sinadurak baieztatzeko mergetan
+- `git tag -v` tag-en sinadurak baieztatzeko
+
+Sinadurak erabiltzen badira, proiektu kide guztiek commitak sinatu behar
+dituzte.
+
+## Bilaketak
+
+- `git grep` espresio erregularren bitartez bilaketak egiteko. `grep`
+ komandoarekin alderatuta azkarragoa da eta historikoan eta indexean bilatzen
+ du.
+- `git log` logetan bilatzeko funtzio oso interesgarriak daude:
+ - `-S` *pickaxe* funtzioa
+ - `-L` lerroen eboluzioa edo funtzioaren eboluzioa erakusten du
+
+## Historia berridazten
+
+- `git commit --amend` mini-rebase baten eragina dauka
+- `git rebase -i|--interactive <commit>` aukeratutako commitera ailegatzeko
+ behar diren commitak aldatu.
+ Editorearen bitartez commit bakoitzarekin zer egin behar duen adierazi ahal
+ zaio: commitak batu, aukeratu, mezua berridatzi, editatu... Aukera batzuek
+ prozesua gelditzen dute. `git rebase --continue` egiten aurrera jarraitzen
+ da, edo `--abort` egiten prozesua ezeztatzen da. Komandoak berak oso ondo
+ azaltzen du nola egin.
+
+> KONTUZ: N+1 commit aldatu emaitza gutxienez commit bat behar duelako
+
+- `git filter-branch` eta antzeko tresnek aldaketa sakonak egin ditzakete.
+ Adibidez, fitxategi bat commit *guztietatik* kendu.
+
+## Reset eta checkout sakonki — I
+
+Reset eta Checkout ulertzeko Giten fitxategien egoerak eta haien arteko
+trantsizioak ondo ulertu behar dira. Hiru egoera posible daude:
+
+1. HEAD: repositorioaren azkeneko commitaren snapshota
+2. Index: *staging area*, hurrengo commitaren proposamena
+3. Working Directory: Aldaketak egiten ditugun lekua
+
+![Egoren arteko trantsizioak](img/reset-workflow.png){height=150px}
+
+## Reset eta checkout sakonki — II
+
+- `git reset`-ek hiru modu ditu:
+ - `--soft`: HEAD-ak apuntatzen duen adarra mugitu
+ - `--mixed`: `--soft` + egoera indexera pasatu
+ - `--hard`: `--mixed` + egoera *working directory*ra pasatu, bertako
+ aldaketak zapalduz
+
+
+## Reset eta checkout sakonki — III
+
+Grafikoki aztertuz. Repositorio hutsarekin hasita:
+
+![&nbsp;](img/reset-ex1.png)
+
+## Reset eta checkout sakonki — IV
+
+Fitxategi bat *indexera* gehitu:
+
+![&nbsp;](img/reset-ex2.png)
+
+## Reset eta checkout sakonki — V
+
+Fitxategia repositorioan idatzi:
+
+![&nbsp;](img/reset-ex3.png)
+
+## Reset eta checkout sakonki — VI
+
+Fitxategia aldatu:
+
+![&nbsp;](img/reset-ex4.png)
+
+## Reset eta checkout sakonki — VII
+
+Egoera *indexera* bidali:
+
+![&nbsp;](img/reset-ex5.png)
+
+## Reset eta checkout sakonki — VIII
+
+Commit berria gehitu:
+
+![&nbsp;](img/reset-ex6.png)
+
+## Reset eta checkout sakonki — IX
+
+Beste commit bat gehituta:
+
+![&nbsp;](img/reset-start.png)
+
+## Reset eta checkout sakonki — IX
+
+`--soft`:
+
+![&nbsp;](img/reset-soft.png)
+
+## Reset eta checkout sakonki — X
+
+`--mixed` (defektuz egiten da):
+
+![&nbsp;](img/reset-mixed.png)
+
+## Reset eta checkout sakonki — XI
+
+`--hard`:
+
+![&nbsp;](img/reset-hard.png)
+
+## Reset eta checkout sakonki — XII
+
+Hiru aukeraz aparte, `git reset`-i fitxategi bat sartu ahal zaio.
+
+Kasu horretan, lehenengo pausua (HEAD-a mugitzea) ezin da burutu[^head] baina
+hurrengo pausuak arazo barik egin daitezke. Horrek funtzionamendu
+interesgarriak ahalbidetzen ditu.
+
+- `git reset <fitxategia>` egiten denean, benetan
+ `git reset --mixed HEAD <fitxategia>` egiten da.
+ 1. ~~HEAD-a mugitu~~
+ 2. Egoera indexean jarri
+
+ Hau da: **Fitxategia indexetik atera**
+
+[^head]: HEADa ezin da erdizka mugitu, edo repositorio osorako mugitzen da edo
+ ez da mugitzen.
+
+## Reset eta checkout sakonki — XIII
+
+Grafikoki:
+
+![&nbsp;](img/reset-path1.png)
+
+
+## Reset eta checkout sakonki — XIV
+
+Adibide konplexuago bat: `git reset <commit> -- <file>`
+
+1. HEAD-a ezin da mugitu
+2. `<file>`-k `<commit>`-en daukan egoera indexera sartzen da (`--mixed`).
+
+![&nbsp;](img/reset-path3.png){height=220px}
+
+
+## Reset eta checkout sakonki — XV
+
+Ikusitakoa *squash* (commit batzuk bakarrean batu) egiteko erabili
+daiteke[^rebase-interactive].
+
+- `git reset --soft HEAD~<N>` egitean HEADa atzera eraman daiteke, indexean
+ aldaketak mantenduz. `git commit` eginda, aldaketak repositorioan idatzi
+ daitezke, denak **commit bakarrean**.
+
+[^rebase-interactive]: Beste aukera `git rebase --interactive|-i` erabiltzea da
+
+## Reset eta checkout sakonki — XVI
+
+Grafikoki:
+
+![&nbsp;](img/reset-squash-r1.png)
+
+## Reset eta checkout sakonki — XVII
+
+HEADa mugitu aldaketak indexean mantenduz:
+
+![&nbsp;](img/reset-squash-r2.png)
+
+## Reset eta checkout sakonki — XIX
+
+Commit berria sartu aldaketa guztiekin batera eginda
+
+![&nbsp;](img/reset-squash-r3.png)
+
+## Reset eta checkout sakonki — XX
+
+`checkout` eta `reset` antzekoak dira, baina ez dira berdinak:
+
+- `git checkout`-ek ez du HEADa eraldatzen. HEAD erreferentzia non apuntatzen
+ duen aldatzen du, ez du azpian dagoen adarra aldatzen.
+
+- `git checkout <branch>` eta `git reset --hard <branch>` ia berdinak dira
+ baina `checkout`ek ez ditu aldaketak zuzenean zapaltzen.
+
+- `git checkout <fitxategia>` fitxategian zeuden aldaketak **zapaltzen ditu**
+ *working directory*an, `git reset --hard`en antzera. KONTUZ
+
+Bietan `--patch` erabili daiteke zatika egiteko.
+
+
+## Reset eta checkout sakonki — XXI
+
+`git checkout` vs `git reset`en efektua HEADan:
+
+![&nbsp;](img/reset-checkout.png)
+
+
+
+## Merge aurreratuak, konfliktoen kudeaketa — I
+
+Mergeak egin baino lehen, ideia ona da *working directory*a garbitzea (`git
+stash`), horrela, zeozer txarto badabil atzera buelta eman daiteke aldaketak
+galdu barik.
+
+- `git merge --abort` mergea txarto doanean (konfliktoak) mergea ezeztatzen
+ du.
+
+ > KONTUZ: aldaketak badaude *working directory*-an ezin izango da abortatu.
+
+
+## Merge aurreratuak, konfliktoen kudeaketa — II
+
+Konfliktoetan Gitek 3 fitxategi ematen ditu:
+
+1. Stage 1: *common ancestor*-a (*base*), bi adarretatik iritsi daitekeen
+ lehengo commita: `git merge-base`-ekin lortu daiteke puntu hau
+2. Stage 2: Gure (*ours*) bertsioa, gure adarrean dagoena
+3. Stage 3: Haien (*theirs*) bertsioa, mergeatzen dugun adarrean dagoena
+
+- `git show :<stageN>:<file>` stage fitxategiak ikusteko
+ - `:<stageN>:<file>`-k blob horren hasha lortzen du.
+
+- `git diff`-en bitartez ikusi daitezke, stage-a aukeratuz
+ - `git diff -1|--base`
+ - `git diff -2|--ours`
+ - `git diff -3|--theirs`
+
+## Merge aurreratuak, konfliktoen kudeaketa — III
+
+- `git show :<stageN>:<file>` eginez, stage bakoitzaren fitxategiak fitxategi
+ ezberdinetara idatzi daitezke eskuz prozesatzeko
+
+- `git merge-file` erabili daiteke hiru fitxategiak eskuz mergeatzeko. Merge
+ algoritmoak aplikatuko ditu
+
+## Merge aurreratuak, konfliktoen kudeaketa — IV
+
+Konfliktoak hobeto aztertzeko tresna batzuk:
+
+- `git checkout --conflict` konfliktoa daukan fitxategiaren konflikto
+ markadoreak berriro idazten ditu. Eskuz aldatzean nahi gabe ezabatu
+ ditugunean interesgarria da.
+
+- `git checkout --ours/--theirs` egin daiteke alde bat edo bestea ikusteko.
+
+- `git log --oneline --left-right --merge` interesgarria da testuingurua
+ ulertzeko.
+
+- `git diff` egitean konfliktoetan *combined diff* bat agertzen da, bi
+ zutabeetan ikusten dira aldaketak.
+
+- `git show -p|--patch` egitean `--cc` gehitu daiteke *combined diff*a ikusteko
+
+
+## Merge aurreratuak, konfliktoen kudeaketa — V
+
+*Combined diff*-aren itxura, konflikto bat konpontzean:
+
+```
+diff --cc hello.rb
+index 0399cd5,59727f0..0000000
+--- a/hello.rb
++++ b/hello.rb
+@@@ -1,7 -1,7 +1,7 @@@
+ #! /usr/bin/env ruby
+
+ def hello
+- puts 'hola world'
+ - puts 'hello mundo'
+++ puts 'hola mundo'
+ end
+```
+
+Bi zutabe daude `-` eta `+` sinboloekin, alde bakoitzean zer gertatu den
+ikusteko.
+
+## Merge aurreratuak, konfliktoen kudeaketa — VI
+
+Konfliktoetan `diff3` erabiltzea interesgarria izan daiteke, defektuz `merge`
+erabiltzen da. Atal berri bat gehitzen dio konfliktoari, *base*a bistaratzeko.
+```
+<<<<<<< ours
+ puts 'hola world'
+||||||| base
+ puts 'hello world'
+=======
+ puts 'hello mundo'
+>>>>>>> theirs
+```
+
+- `git checkout --conflict=diff3` konfliktoa 3 stagetan bistaratzeko.
+
+- `git config --global merge.conflictstyle diff3` konfliktoak 3 bidetan
+ ikusteko
+
+
+## Mergeak desegiten — I
+
+Bi aukera ezberdin dago mergea desegiteko:
+
+1. `git reset --hard HEAD~` (historikoa berridazten du)
+2. `git revert -m 1 HEAD` commit bat gehitu aldaketak desegiten dituena.
+ Arazoak datoz adarra berriro mergeatu behar denean.
+
+## Mergeak desegiten — II
+
+`git revert -m 1 HEAD` egitean, mergea desegin da beste commit batekin. `^M`
+eta `C6` eduki berdinak dituzte. Baina `topic` adarraren commitak `master`etik
+iritsi daitezke. Gitentzat mergeatuta daudela dirudite. KONTUZ
+
+![](img/undomerge-revert.png)
+
+## Mergeak desegiten — III
+
+Txarragoa izan daitekeena, aldaketak gehitzen badira, Gitek commit berriak
+baino ez ditu hartzen, bestea mergeatuta dagoela uste duelako. KONTUZ
+
+![](img/undomerge-revert2.png)
+
+## Mergeak desegiten — IV
+
+Arazoa saihesteko, aurreko mergea, desegin duguna, aplikatu behar da.
+Horretarako, `revert` commita desegin daiteke beste `revert` bat eginez.
+
+![](img/undomerge-revert3.png)
+
+Orain, `topic`-en aldaketa guztiak `master`-en daude.
+
+## Mergeen preferentziak
+
+`git merge` aukera eta estrategia ezberdinak daude:
+
+- `-X` aukerak gehitzeko erabiltzen da. Adibidez: `-Xours` konfliktoak gure
+ aldera ebazteko
+
+- `-s` estrategiak gehitzeko. Adibidez: `-s ours` mergea egin beharrean, gure
+ aldeko aldaketak bakarrik aukeratu (Giti ziria sartzeko interesgarria da)
+
+Aukerak eta estrategiak ez dira gauza bera. Estrategiak merge algoritmoa
+definitzen dute. Aukerek algoritmoa konfiguratzen dute.
+
+## Subtree-ak
+
+Subtree-ak beste proiektu bat gure proiektuaren barruan sartzeko mekanismo bat
+dira. Azpiproiektua adar independente batean kudeatzen da: beste remote bat
+moduan hasierazten da, baina adar berri batean sartu, beste adarrekin
+zerikusirik ez duena.
+
+- `git read-tree` azpiproiektua irakurri eta beste adar baten azpidirektorio
+ moduan hasiarazteko
+- `git merge -Xsubtree` erabiltzen da *subtree*aren adarra proiektuan
+ arazo barik mergeatzeko
+- `git diff-tree` azpiproiektuaren aldaketak aztertzeko, `diff` normal bat ez
+ dabil
+
+*Ez da asko erabiltzen, *Submodule*ak gehiago erabiltzen dira. Gehiago ikasteko,
+liburua irakurri.*
+
+## Rerere: Reuse Recorded Resolution — I
+
+Konfliktoak nola konpondu ditugun erregistratzeko sistema bat da, gero Gitek
+konfliktoak automatikoki ebazteko kriterio berdina erabiltzen. Adibide baten
+bitartez:
+
+1. Testing adarra mergeatzen konfliktoak daude
+2. Konfliktoak konpontzen dira
+3. Testak txarto doaz
+4. Mergea desegin behar da
+5. Testak konpondu behar dira
+6. Mergea berriro egin => konflikto berdinak berriro konpondu behar dira
+
+`rerere`-ren bitartez lehenengo mergearen konfliktoen ebazpena gorde daiteke.
+Horrela, mergea berriro aplikatzerakoan ez da konfliktoa berriro ebatzi behar,
+automatikoki aurretik gordetako ebazpena erabiltzen delako.
+
+## Rerere: Reuse Recorded Resolution — II
+
+- `git config --global rerere.enabled true`
+- `git rerere status` *rerere*ren egoera ikusteko
+- `git rerere diff` *rerere*k aplikatuko lituzken aldaketak ikusteko
+- `git add` + `git commit` egiterakoan ebazpena gordetzen da:
+ `"Recorded resolution"`
+- `git reset --hard HEAD^` eta mergea berriro egiterakoan konfliktoak
+ automatikoki konpontzen dira:
+ `"Resolved with previous resolution"`
+- `git checkout --conflict=merge <file>` eginda konfliktoa berreskuratu
+ daiteke, `rerere`a aktibatu gabe
+- `git rerere` egiten berriro mergeatu daiteke automatikoki
+
+
+## Gitekin debuggeatzen
+
+- `git blame` fitxategi baten aldaketak zein commitean sartu diren ikusi
+ daiteke. `^`-ekin hasten diren lerroak hasieratik aldatu gabeko lerroak dira.
+ `-C` aukerarekin mugitutako zatiak aurkitu daitezke[^move]
+
+[^move]: Gitek ez ditu mugimenduak gordetzen baina fitxategien zatiak aztertu
+ eta mugimenduak kalkulatu ditzake
+
+- `git bisect` [bisekzio metodoa][bisect] erabiliz errorea sartu zuen commita
+ aurkitzeko tresna oso interesgarria. Metodoa:
+ - Bi commit hartu: bat erroreduna eta bestea errore gabea
+ - Erdiko puntuan commit bat hartu: errorea badauka, errorea sartu zuen
+ commita commit honen eta errore gabeko commitaren artean dago. Errorea ez
+ badago, commit honen artean eta commit erroredunaren artean dago.
+ - Beste puntu bat hartu eta jarraitu tartea txikitzen commita aurkitzen den
+ arte.
+
+[bisect]: https://en.wikipedia.org/wiki/Bisection_method
+
+
+## Gitekin debuggeatzen: `git bisect`
+
+Bisekzio metodoa aplikatzeko workflowa
+
+1. `git bisect start` bisekzio metodoa hasi
+2. `git bisect bad` oraingo commita txarra da
+3. `git bisect good <commit-id>` commit hau ona da
+4. `git bisect good/bad` oraingo commita ona edo txarra da. Gitek
+ hurrengo commita aukeratzen du:
+ `"Bisecting, N revisions left to test"`
+5. `git bisect reset` hasierara bueltatu
+
+Automatizatu daiteke: `git bisect run <command>`
+
+- Komandoak `0` bueltatu behar du testa ondo badoa eta beste edozer errorea
+ badago
+
+
+## Submoduluak
+
+Gure proiektuaren barruan azpiproiektuak kudeatzeko modu bat da.
+
+- `git submodule add <URL>` azpiproiekturako karpeta berri bat gehitzen du eta
+ `.gitmodules` fitxategia hasieratzen du
+- `.gitmodules` fitxategian azpiproiektuen informazioa gordetzen da: URLa,
+ izena eta path-a.
+- `git submodule add ...` eta gero `git diff --cached` egitean ikusten da
+ submoduluen path-a ez dela fitxategi bezala kudeatzen:
+ `"Subproject commit ---"`
+- `git diff --submodule --cached`-ekin hobeto ikusten da
+- `git push` egiterakoan submodule-aren direktorioa erreferentzia moduan
+ pusheatzen da.
+
+## Submoduluak klonatzeko
+
+- `git clone`-ek **ez** ditu proiektuen submoduluak deskargatzen
+- `git submodule init` submoduluen kontrola hasieratzeko
+- `git submodule update` submoduluen fitxategiak berrizteko
+- `git clone --recurse-submodule <URL>` zuzenean submodule guztiak
+ deskargatzeko `clone` egiterakoan. Bestela `git submodule update --init` edo
+ `git submodule update --init --recursive` egin daiteke klonatu eta gero
+
+## Submoduluekin lanean
+
+- `git diff --submodule` ez egiteko `git config --global diff.submodule log`
+ egin daiteke eta zuzenean submoduluaren diffa ikusi daiteke `git diff`
+ egitean
+- `git submodule update --remote <submodule>` submoduluen edukiak berrizteko
+ edo bestela submoduluaren barruan `fetch`+`merge` egin daiteke.
+- `git config -f .gitmodules submodule.<submodule>.branch <adarra>` adarrez
+ aldatzeko, edo fitxategia zuzenean aldatu
+- `git config status.submodulesummary 1` egitean `git status`-ek submoduluen
+ egoera bistaratuko du
+- `git log --submodule` submoduluen aldaketak ikusteko
+
+## Submoduluak dituen proiektua berrizteko
+
+- `git pull` ez ditu submoduluak berritzen, informazioa baino ez du
+ deskargatzen.
+- `git submodule update` aplikatu behar da, `--init`-ekin submodule berriak
+ gehitu badira, hauek gehitzeko eta `--recursive`, submoduluek submoduluak
+ badituzte.
+- `git pull --recurse-submodules`-k efektu berdina dauka. Konfiguratu daiteke
+ automatikoki egiteko.
+- `git submodule sync` egin behar da URLak aldatu badira.
+
+## Submoduluetan lanean
+
+Normalean ez da submoduluetan idazten, baina egin daiteke.
+
+- `git submodule update`-k azpirepositorioa *detached head* egoeran uzten du.
+ Bertak commitak gehitzean galduko lirateke (ez dago adarrik commitetara
+ ailegatzeko). Hau konpontzeko:
+
+ 1. Adarrak konfiguratu behar dira: `cd <submodule> && git checkout <branch>`
+ 2. `git submodule update --remote --merge/--rebase` egin behar da *detached
+ head* egoeran ez gelditzeko. Submoduluan aldaketak badaude, konfliktoa
+ egon daiteke.
+
+## Submoduluen lana publikatzen
+
+- `git push` egin daiteke submodulu bakoitzean, Git repositorio normalak
+ baitira
+- `git push --recurse-submodules=check/on-demand` bi estrategia dago. `check`
+ aldaketak pusheatu behar diren begiratzen du, eta `on-demand`-ek pusha egiten
+ du submodulu bakoitzean aldaketak badaude
+ - `git config push.recurseSubmodules check/on-demand` estrategia defektuz
+ konfiguratzeko
+
+## Submoduluen trukoak
+
+- `git submodule foreach <command>` egin daiteke submodule bakoitzean komando
+ bat executatzeko. Adibidez: `git submodule foreach 'git stash'`
+
+## Bundle
+
+Bundle-ak commitak edo repositorio osoak fitxategi baten bidez partekatzeko
+sistema dira.
+
+- `git bundle create <file> [<commit-selector>]` aukeratutako commitak (edo
+ guztiak) `<file>` fitxategian gorde, bundle formatoan. Normalean, `HEAD`
+ sartzea komeni da, gero bundle-a kargatzean repositorioa non zegoen jakiteko.
+
+- `git clone <bundle-file>` bundle fitxategitik clone bat egiteko. Bundle-a
+ repositorio osoa izan behar du.
+
+- `git bundle verify <bundle-file>` bundle partzial bat repositorio batean
+ aplikatu daitekeen konprobatzeko
+
+- `git bundle list-heads <bundle-file>` bundle fitxategiaren adarrak ikusteko
+
+- `git fetch/pull <bundle-file>` bundle fitxategitik repositorioa
+ berriztatzeko
+
+## Replace
+
+Giten datu basea orokorrean ezin da aldatu, baina `git replace`-en bitartez
+*replace* objektuak eratu daitezke, datu basea aldatu denaren itxura emango
+dutenak.
+
+- `git replace <object> <replacement>` aplikatzetik aurrera, `<object>`
+ erabiltzean `<replacement>` erabili balitz bezala funtzionatuko du
+
+*Erabileren adibide bat ikusteko liburuan ikusi, nahiko arraroa da hau ikustea*
+
+## Kredentzial sistema
+
+HTTP kredentziala erabiltzean, zerbitzariarekin egiten diren interakzio
+guztietan erabiltzailea eta pasahitza eskatzen du Gitek defektuz.
+Portaera konfiguratu daiteke:
+
+- `git config --global credential.helper <modua>`
+ 1. Beti eskatu (defektuz egiten dena)
+ 2. `cache` kredentzialak memorian mantendu 15 minutu
+ 3. `store` kredentzialak gorde
+
+Aukera gehiago dago (`--timeout`, neurrira egindako kredentzial sistemak,
+etab.). *Interesa balego, liburuan begiratu*
+
+# Git konfigurazio aurreratua
+
+## Git konfigurazioa
+
+Konfigurazioaren dokumentazioa ikusteko `git help git-config`. Atal
+interesgarrienak:
+
+- Editorea eta paginadorea: `core.editor` eta `core.pager`
+- Commit mezuen txantiloia: `commit.template`
+- Merge eta diff tresnak: `merge.tool` eta `diff.tool`
+- Espazio hutsen kontrola: `core.autocrlf` eta `core.whitespace`
+
+## Git attribute-ak — I
+
+Proiektuen barruan, fitxategi mailan, Giten portaera aldatzeko erabiltzen dira
+atributuak (*attribute*).
+
+- `.gitattributes` fitxategian edo `.git/info/attributes` fitxategian,
+ repositorioarekin partekatu nahi ezbadira.
+
+Atributu fitxategia `.gitignore` fitxategiaren antzekoa da, baina lerro
+bakoitzean fitxategien izenen txantiloiaz aparte haien atributuak definitu
+behar dira. Askotan konfigurazio gehigarria behar da, *driver* programak
+definitzeko. Ikusi `git help attributes`.
+
+## Git attribute-ak — II
+
+Atributu mota asko dago, interesgarrienetarikoak:
+
+- `binary` fitxategiak binario moduan identifikatzeko
+- `diff=<iragazkia>` diff-a exekutatu baino lehen fitxategiak iragazki batetik
+ pasatzeko. Konfigurazio gehigarria behar da:
+ - `git config diff.<iragazkia>.textconv <programa>`
+ - Adibidez: `*.png diff=exif`
+ - `git config diff.exif.textconv exiftool`
+ png fitxategien estatistikak konparatzen dira, eta ez edukiak
+- `ident` identifikazioa gehitzeko. `$Id$` testu literala SHA-1era bihurtzen da
+ espantsio baten bitartez
+
+## Git attribute-ak — III
+
+- `filter` fitxategiak iragazki batekin prozesatzeko
+ - `smudge` *index*etik *working directory*rako bidean
+ - `clean` *working directory*tik *index*erako bidean
+ - Adibidez: `*.c filter=indent`
+ - `git config filter.indent.clean indent`
+ `git config filter.indent.smudge cat`
+ fitxategiak automatikoki indentatzeko `git add` egiterakoan
+- `export-ignore` artxibo (`git archive`) bat egiterakoan fitxategi batzuk
+ baztertzeko.
+- `export-subst` artxibo bat egiterakoan `git log`-ek aplikatzen dituen
+ espantsioak aplikatzeko
+- `merge` merge estrategiak aukeratzeko
+
+
+## Git hooks
+
+Hookak gertaera garrantzitsuak gertatzen direnean exekutatzen diren programak
+dira. Askotan erabiltzen dira.
+
+- `.git/hooks` direktorioan idazten dira, izen konkretu batekin eta exekuzio
+ baimenekin
+
+Defektuz, `git init` egiterakoan hook batzuk idazten dira, baina desaktibatuta
+daude (haien izena `.sample`-n bukatzen delako). Erreferentzia moduan hartu
+daitezke haien funtzionamendua ulertzeko.
+
+
+## Bezero aldeko hookak
+
+Bakoitzarentzako bakarrik. **Ez dira kopiatzen repositorioarekin
+batera**[^hookak-partekatu].
+Interesgarriak dira garatzaileei alertak botatzeko: testak ez direla pasatu,
+formaturen bat txarto dagoela adierazteko, etab. Interesgarri batzuk:
+
+- `pre-commit` commit mezua idatzi baino lehen exekutatzen da, zeozer ahaztu
+ den konprobatzeko erabili ohi da
+- `prepare-commit-msg` defektuzko commit mezua aldatzeko erabiltzaileak ikusi
+ baino lehen. Informazio gehigarriak sartu ahal zaio horrela, edo txantiloia
+ aldatu...
+- `commit-msg` commit mezua aztertzen duen hooka. Txarto badago commita atzera
+ bota dezake. Normalean commitaren mezua txantiloi konkretu bat jarraitzeko
+ erabiltzen da.
+
+[^hookak-partekatu]: Tresna batzuek mekanismoak dauzkate hook hauek
+ partekatzeko, baina hau ez da Giten defektuzko funtzionamendua. Kontuz
+ workflow guztia honetan oinarritzearekin.
+
+## Zerbitzari aldeko hookak
+
+Politikak inposatzeko aproposak dira, txarto badoaz `push` egiteko eskaerak
+atzera bota ditzaketelako. Interesgarri batzuk:
+
+- `pre-receive` push bat jasotzean erreferentzia guztiak jasotzen dituen
+ programa, errorea ematen badu ez da ezer berriztuko.
+- `update` aurrekoaren antzekoa da, baina behin exekutatzen da adar bakoitzeko
+- `post-receive` dena ondo jaso eta gero exekutatzen da, notifikazio moduan
+ erabili daiteke
+
+
+# Git barrutik
+
+## Git barrutik: Sarrera
+
+Git maila baxuko tresna bat da, eta maila horretan lan egiteko komandoak ditu,
+*plumbing* deiturikoak. Orain arte erabilitakoak *porcelain* deitzen dira,
+maila altuan lan egiten dutelako.
+
+Git *content-addressing* aplikatzen duen datu base bat da, hau da, *Key-Value*
+moduan gordetzen dira elementuak, non Key-a Valuaren edukiaren araberakoa den.
+Orain arte ikusi da: elementuak haien edukiaren SHA-1 hasharen bitartez
+identifikatzen dira.
+
+Eduki guzti hau `.git` karpetan gordetzen da. Baina elementu mota ezberdinak
+daude.
+
+## Giten gordetzen diren elementu motak
+
+Bi elementu mota nagusiak daude Git datu basean:
+
+- Objektuak: edukiak dauzkaten elementuak dira: commitak, blobak, zuhaitzak,
+ etab
+- Erreferentziak: beste elementuei apuntatzen duten elementuak dira: adarrak,
+ lightweight tagak, etab
+
+
+## Objektuak
+
+`.git/objects`-en gordetzen dira, haien hasharen arabera. Lehengo bi
+karaktereak direktorio moduan eta hurrengoak fitxategi moduan.
+Adibidez: `.git/objects/cf/6cbb8a400c7cad0f7f93610366c3672f598cdd`
+
+- `git hash-object -w`-rekin idatzi daitezke (bueltan hash-a ematen du)
+- `git cat-file`-ekin irakurri daitezke. `-p` egin emaitza **p**olita ikusteko.
+
+## Objektu motak
+
+`git cat-file -t`-rekin mota ikusi daiteke.
+
+- `blob`-ak fitxategien edukiak eta bestelako datuak gordetzeko
+- `tree` fitxategien izenak eta direktorioak gordetzeko
+ Sarrera bat edo gehiago dute beste `tree` edo `blob`etara haien izena eta
+ hasha identifikatuz.
+- `commit` commit datuak gordetzeko: `tree` bat snapshotarekin, mezua, autorea,
+ etab.
+
+## Objektu motak: tree
+
+![](img/data-model-1.png)
+
+## Objektu motak: commit
+
+![](img/data-model-3.png)
+
+## Erreferentziak
+
+Haien barruan identifikadore bat baino ez dago.
+
+- `git update-ref` edukia aldatzeko. Eskuz ere egin daiteke.
+
+Erreferentzia mota ezberdinak daude:
+
+- Tag-ak: `.git/refs/tag` karpetan. Edozein objetu tageatu
+ daiteke (normalean commitak). Bi mota dago:
+ - Lightweight tag: erreferentzia bat baino ez dira
+ - Annotated tag: tag *objektu* bat eratzen dute eta erreferentzia bat
+ idazten dute bertara
+- Adarrak: `.git/refs/heads` karpetan. Commit-id batera erreferentzia
+ egiten dute.
+- Remote-ak: `.git/refs/remotes` karpetan. Adarren antzerakoak baina ezin dira
+ aldatu.
+- HEAD-a: `.git/HEAD`-en dago. Adar batera apuntatzen du, baina batzutan commit
+ batera apuntatu dezake (*Detached HEAD*).
+
+## Erreferentziak: adarrak
+
+![](img/data-model-4.png)
+
+## Ariketa: Notak
+
+- `git notes` komandoarekin kudeatzen dira.
+
+*Aztertu zer diren eta nola funtzionatzen duten. Ikusi `git help git-notes`*
+
+## Packfile-ak
+
+Datuen egitura efizienteagoa egiteko Gitek fitxategiak konprimatzen ditu, baina
+hori ez da normalean nahikoa izaten.
+
+Git snapshotetan oinarritzen da, baina ez ditu fitxategi osoak behin eta
+berriro idazten commit bakoitzean, aldaketak baino ez ditu gordetzen.
+
+Gainera fitxategiak taldekatu eta *packfile* deituriko fitxategietan gordetzen
+ditu prozesua arintzeko.
+
+- `.git/objects/pack`-en ikusi daitezke
+- `git gc` (*garbage collector*) fitxategiak taldekatu eta konprimatzeko (berak
+ bakarrik exekutatzen du beharrezkoa ikusten duenean)
+- `git verify-pack` *packfile* baten edukia aztertzeko eta egiaztatzeko
+
+## Mantenamendua eta datuak berreskuratzea
+
+- `git gc --auto`-k packfileak berrorganizatzen ditu.
+- `git reflog`-en HEAD-ean egindako aldaketak gordetzen dira, beraz commiten
+ bat galdu bada bertara salto egin daiteke, `reflog`a begiratu eta commita
+ berreskuratu daiteke.
+- `git fsck --full` galdutako elementuak erakusten ditu, bertatik ere
+ datuak berreskuratu daitezke
+
+*ARIKETA: Fitxategi handiak nahi gabe gehitzea arazo bat da, `git rm`-k ez
+dituelako ezabatzen. Nola egiten da? Zergatik?*
+
+## Refspec-a
+
+Lokalaren eta remotearen arteko adarren mapeoa kudeatzeko. `.git/config`-en
+edukia `git remote add origin https://github.com/schacon/simplegit-progit` egin
+eta gero:
+
+```
+[remote "origin"]
+ url = https://github.com/schacon/simplegit-progit
+ fetch = +refs/heads/*:refs/remotes/origin/*
+```
+
+`fetch` atalak **refspec** baten bitartez adarrak nola kudeatu behar diren
+adierazten du. Sarrera asko egon daitezke arau ezberdinekin. Formatua:
+
+- Aukerako `+` bat *fast forward* ez direnean ere berrizteko
+- `<iturria>:<helmuga>` nola mapeatu behar diren adierazteko. `<iturria>`
+ eta `<helmuga>` patroiak dira (`*`)
+
+## Refspec-a eskuz erabiltzen
+
+`git fetch/push` egitean refspec patroia (1 edo +) gehitu ahal da *"hau hona"*
+eta *"beste hau hona"* esateko.
+
+Refspec-a ikusita, Gitek adarren adierazpenaren espantsioa egiten du:
+
+- `git log origin/master`
+ => `git log remotes/origin/master`
+ => `git log refs/remotes/origin/master`
+
+Adarrak ezabatzeko lehen refspec-a erabili behar zen:
+
+- `git push :<adarra>` iturri atala utzik uztean, remotean adarra ezabatzen zen
+- Orain `git push --delete <adarra>` egin daiteke
+