diff options
author | Ekaitz Zarraga <ekaitz@elenq.tech> | 2023-09-04 19:52:41 +0200 |
---|---|---|
committer | Ekaitz Zarraga <ekaitz@elenq.tech> | 2023-09-04 19:52:41 +0200 |
commit | 3d08769c9b942a42fe8dc3a9074a92882fc5f7c9 (patch) | |
tree | 6516ab82a462f603f26d06873e265f1ff4cdd7af /2.md | |
parent | 542c485b3a6df9fd68012618d1763e28ce11f67b (diff) |
Gitignore
Diffstat (limited to '2.md')
-rw-r--r-- | 2.md | 1026 |
1 files changed, 0 insertions, 1026 deletions
@@ -1,1026 +0,0 @@ ---- -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: - -![ ](img/reset-ex1.png) - -## Reset eta checkout sakonki — IV - -Fitxategi bat *indexera* gehitu: - -![ ](img/reset-ex2.png) - -## Reset eta checkout sakonki — V - -Fitxategia repositorioan idatzi: - -![ ](img/reset-ex3.png) - -## Reset eta checkout sakonki — VI - -Fitxategia aldatu: - -![ ](img/reset-ex4.png) - -## Reset eta checkout sakonki — VII - -Egoera *indexera* bidali: - -![ ](img/reset-ex5.png) - -## Reset eta checkout sakonki — VIII - -Commit berria gehitu: - -![ ](img/reset-ex6.png) - -## Reset eta checkout sakonki — IX - -Beste commit bat gehituta: - -![ ](img/reset-start.png) - -## Reset eta checkout sakonki — IX - -`--soft`: - -![ ](img/reset-soft.png) - -## Reset eta checkout sakonki — X - -`--mixed` (defektuz egiten da): - -![ ](img/reset-mixed.png) - -## Reset eta checkout sakonki — XI - -`--hard`: - -![ ](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: - -![ ](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`). - -![ ](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: - -![ ](img/reset-squash-r1.png) - -## Reset eta checkout sakonki — XVII - -HEADa mugitu aldaketak indexean mantenduz: - -![ ](img/reset-squash-r2.png) - -## Reset eta checkout sakonki — XIX - -Commit berria sartu aldaketa guztiekin batera eginda - -![ ](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: - -![ ](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 - |