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 /eu | |
parent | 542c485b3a6df9fd68012618d1763e28ce11f67b (diff) |
Gitignore
Diffstat (limited to 'eu')
-rw-r--r-- | eu/1.md | 606 | ||||
-rw-r--r-- | eu/2.md | 1026 |
2 files changed, 1632 insertions, 0 deletions
@@ -0,0 +1,606 @@ +--- +title: GIT — EITB 2022 +subtitle: Sarrera eta erabilera basikoa +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/1.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. + +# Sarrera: Bertsio kontrol sistemak + +## Bertsio kontrolerako sistemak + +`Document_v3_FINAL.pdf` + +--- + +![Bertsio kontrol sistema zentralizatuak](img/zentralizatuak.png){ height=180px } + +--- + +![Bertsio kontrol sistema banatuak](img/banatuak.png){ height=300px } + + +# Git: Hasiera + +## Kontestua + +- 2005-ean argitaratu zen +- Linux garapenerako garatu zen + - Milioika garatzaile + - *Codebase* handiak kudeatzeko +- Sistema banatua (*distributed*) da +- *Snapshot*etan oinarrituta +- Operazio gehienak lokalak dira eta normalean ez ditu datuak ezabatzen +- Integritate kontrola egiten du SHA-1 erabiliz +- Hiru egoera: + `FITXATEGIA — STAGING AREA — REPOSITORIOA` + +## Instalazioa + +Debian-en oinarritutako distribuzioetan: + +``` +apt-get install git +``` + +Beste distribuzioetan antzeko komandoren batekin egin daiteke. + + +## Konfigurazio sistema + +- Sistema mailakoa: `/etc/gitconfig` +- Konfigurazio orokorra: `~/.config/git/config` edo `~/.gitconfig` +- Konfigurazio lokala. Repositorio bakoitzeko: `$REPOSITORIOA/.git/config` + +Kaskada moduan dabil, konfigurazio lokalak orokorra zapaltzen du. +Nondik datorren ikusteko: + +``` +git config --list --show-origin +``` + +## Konfigurazioa kudeatzea + +Komandoek konfigurazio fitxategia irakurri edo idazten dute. Eskuz egin +daiteke. + +Komando orokorra: + +``` +git config [--global] atala.klabea [<balioa>] +``` + +- `<balioa>` gehitzen ez bada konfigurazioa irakurtzen da idatzi beharrean. +- `--global` konfigurazio globala kudeatzeko erabiltzen da. + +Benetan konplexuagoa da, laguntza begiratu. + + +## Hasierako konfigurazioa + +Identitatea definitu (beharrezkoa da commiten egilea nor den jakiteko): + +``` +git config --global user.name "John Doe" +git config --global user.email johndoe@example.com +``` + +Editorea aukeratu: + +``` +git config --global core.editor vim +``` + + + +## Laguntza lortzeko + +- `git help` +- `man` + + +# Git basikoa + +## Repositorio bat lortzen + +Bi aukera: + +- Repositorio berri bat hasi: `git init`. Oraingo direktorioan `.git` + direktorioa eratuko du, bertan Git-en datuak gordeko dira. + +- Repositorio bat klonatu: `git clone <URL>`. Oraingo direktorioan emandako + repositorioa kopiatuko du, bere `.git` direktorioa barne. Protokolo + ezberdinetan egin daiteke komunikazioa. + +## Fitxategien egoerak + +![Fitxategien egoera ezberdinak](img/lifecycle.png){ height=180px } + +## Repositorioaren egoera ikusteko + +- `git status` +- Fitxategi batzuei jaramonik ez egiteko: `.gitignore` fitxategi bat gehitu. + *Glob pattern*ak erabiltzen ditu. + +## Egoeraz aldatzeko + +- Fitxategi berriak gehitzeko: `git add` +- Aldaketak *staging area*ra bidaltzeko: `git add` + +## Aldaketak ikusteko + +- `git diff` +- `git diff --cached|--staged` +- `git difftool` (konfiguratuta badago) + +`diff` komandoaren irteera fitxategi batean gorde eta gero, beste norbaiti +pasatu ahal zaio, berak bere repositoriaren kopian `git apply` erabiliz +aplikatzeko. + +## Aldaketak idazteko + +- `git commit` + +Mezu bat idaztea eskatzen du: `$EDITOR` edo `git config --global core.editor` +programa exekutatuz. + +## Fitxategiak ezabatzeko + +- `git rm` +- `git rm --cached` + +## Izenak aldatzeko + +- `git mv` + +Edo bestela fitxategia eskuz lekuz aldatu eta gero `git rm` + `git add` egin. + + + +## Commit historia ikusteko + +- `git log` + +Oso komando konplexua da. Aukera asko ditu. + +- `-<N>` azkeneko `<N>` commitak aurkezten ditu. `<N>` zenbaki bat izan behar + da. +- `-p/--patch` commit-en *patch*-a ateratzen du. +- `--stat` estatistikak aurkezteko. +- `--pretty` formatua aldatzeko, modu asko dauzka. +- `--graph` grafiko modua. + +Konbinatu daitezke: + +`git log --graph --pretty=oneline --decorate --all` + +## Commit historia iragazteko + +`git log`-en irteera mugatu daiteke, eskaerak eginez: + +- `--since` noiztik ikusi nahi diren. Adibidez: `--since=2weeks`. +- `--author` autorez iragazi. +- `--grep` commit mezuan *keyword*ak bilatzeko. +- `-S/-G/...` *pickaxe function* deiturikoak, aldaketetan testua bilatzen dute. +- `git log -- fitxategia` fitxategi horretan gertatutako aldaketak bakarrik + atera. +- `--no-merges` merge commitak baztertu. + +Laguntza ikusi: `git help log` + + +## Aldaketak desegiteko + +- `git commit --amend` azkeneko commita berridazten du. + - Mezua aldatu + - Fitxategiak edo aldaketak gehitu + - ... + +- `git reset` aldaketak *staging area*tik kentzeko. KONTUZ `--hard`-ekin +- `git checkout` aldaketak desegiteko eta commiteatutako egoera + berreskuratzeko. KONTUZ +- `git restore` komando berria da (>2.23.0) `reset` eta `checkout`-ek egiten + dituzten gauzak egiten dituena, baina intuitiboagoa da. + +## Remoteak + +Repositorioaren kopiak dira. Remoteak eguneratu daitezke repositorio lokaletik +aldaketak igotzen (*push*) edo repositorio lokala eguneratu daiteke remotean +dauden aldaketak ekartzen (*fetch & pull*). + +Remoteak beste makinetan egon daitezke, sarearen bidez sarbidea emanda, edota +makina berdinean, fitxategi sistemaren beste leku batetan. + +## Remote-en kudeaketa + +- `git remote` + +`.git/config` fitxategian daude idatzita. Hortik ere kudeatu daitezke. + + +- `git clone` -k remotea automatikoki gehitzen du konfiguraziora, `origin` + izenarekin. +- `git remote -v` +- `git remote add <izena> <URLa>` +- `git remote show <remotearen_izena>` +- `git remote rename <izena> <izen_berria>` +- `git remote remove <izena>` + + +## Remotearekin informazioa elkarbanatu + +- `git fetch [<remote>]`-ek remotearen informazioa deskargatzen du, + repositorioa zapaldu gabe. + +- `git pull`-ek informazioa deskargatu eta `merge`atzen du adarrak ondo + konfiguratuta badaude: + ``` + git pull = git fetch + git merge + ``` + +- `git push [<remote> <branch>]`-ek datuak eta commitak igotzen ditu. Norbaitek + commitak erdian gehitu baditu ez du uzten (aurrerago azalduko da). + +## Tag-ak + +Commitei jarri ahal zaizkien izenak dira, normalean *release*ak errezago +identifikatzeko. Horrela, tag-en izenak erabiltzen dira *commit-id*-ak balira +moduan baina guk erabakitako izenekin. Adibidez, `v1.0`. + +- `git tag -l` tagak bistaratzeko + +Bi tag mota dago: + +- **Lightweight**: erreferentzia bat dira. Adar finko baten modukoak +- **Annotated**: Git-en datu basean objektu oso bat dira: Mezu bat daukate, + autorea, sinatu daitezke... + +## Annotated tags + +- `git tag -a <tagaren_izena> [<commit>]` + +`git show` -k erakusten ditu. + +## Lightweight tags + +- `git tag <tagaren_izena> [<commit>]` + +`git show`-k ez ditu erakusten, azpitik dagoen commita erakusten du. + + +## Tag-ak partekatzeko + +- `git push [<remote>] <taga>` +- `git push [<remote>] --tags` guztiak bidaltzeko + +## Tag-ak ezabatzeko + +- `git tag -d <taga>` +- `git push [<remote>] --delete <taga>` + +## Aliasak + +Gitek komando berriak eratzea ahalbidetzen du aliasen bitartez. Beste +konfigurazio balioak bezala idazten eta irakurtzen dira: + +- `git config --global alias.co checkout` +- `git co` => `git checkout` + +Nik asko erabiltzen dut: + +``` +git config --global alias.lg log --graph \ + --decorate --all --oneline +``` + + +# Git basikoa: Adarrak + +## Adarrak (*branch*) + +Adarrek repositorioaren garapenean beste bide bat hartzea ahalbidetzen dute, +bertan bide nagusian aldaketarik eragin gabe lan egiteko. + +Git adarrak erabiltzeko diseinatuta dago eta haien erabilera sustatzen du. +Beraz, **oso garrantzitsuak** dira. + +Beste bertsio kontrol sistema batzuetan adarrak erabiltzea prozesu astuna da, +errekurtso asko behar dituena. Git-en oso prozesu sinplea da eta ez du ia +errekurtsorik behar. Git-en bitartez kudeatzen diren proiektuetan ez da arraroa +ehundaka adar ikustea. + +## Git barrutik + +- Fitxategiak *Staging Area*ra bidaltzean, Git-ek haien argazkiak gordetzen + ditu *blob* objektu moduan eta haien checksuma kalkulatzen du (SHA-1) +- Commita egiterakoan direktorio bakoitzaren checksuma kalkulatzen du eta + *tree* objektu bat gordetzen du direktorio bakoitzeko. *Tree* objektuek + *blob* objektuetara apuntatzen duten erreferentziak dituzte. Gainera commitek + beste datuak gordetzen dituzte: autorea, mezua, data... +- Commitek haien gurasoei apuntatzen duten erreferentziak dituzte: + lehengo commitek erreferentziarik ez dute, commit normalek erreferentzia + bakarra dute eta *merge* commitek erreferentzia asko dituzte. + +Adarrak commitetara apuntatzen duten erreferentzia mugikorrak dira. + +## Git barrutik + +![Git repositorio baten barne datuak](img/commit-and-tree.png) + +## Git barrutik + +![Git repositorio baten commit estruktura](img/commits-and-parents.png) + +## Adarrak eratzeko + +- `git branch <branchname>` + +Defektuz `master` deitutako adar bat dago. Izena konfiguragarria da, baina +gutxienez adar bat egon behar da beti, bertan commitak gehitzen direlako. + +Git-ek oraingo adarrera apuntatzen duen erreferentzia bat gordetzen du: `HEAD` +deiturikoa. + +## Adarraz aldatzeko + +- `git checkout <branchname>` +- `git checkout -b <branchname>` adarra eratu eta bertara aldatzeko + +Bertsio berrietan, `checkout` komandoak gauza gehiegi egiten dituenez, komando +espezifiko bat eratu zen adarrekin lan egiteko: + +- `git switch <branchname>` +- `git switch -c <branchname>` adarra eratu eta aldatzeko +- `git switch -` aurreko adarrera bueltatzeko + +## Adarrak eta aldaketak — I + +![`git branch testing`](img/head-to-master.png) + +## Adarrak eta aldaketak — II + +![`git checkout testing`](img/head-to-testing.png) + +## Adarrak eta aldaketak — III + +![`git commit ...`](img/advance-testing.png) + +## Adarrak eta aldaketak — IV + +![`git checkout master`](img/checkout-master.png) + +## Adarrak eta aldaketak — V + +![`git commit ...`](img/advance-master.png) + +## Adarrak eta aldaketak — VI + +Giten interfazetik ikusita: + +``` +$ git log --oneline --decorate --graph --all +* c2b9e (HEAD, master) Made other changes +| * 87ab2 (testing) Made a change +|/ +* f30ab Add feature #32 +* 34ac2 Fix bug #1328 +* 98ca9 initial commit +``` + +> KONTUZ: Ez bada `--all` egiten ez dira defektuz adar guztiak bistaratzen `git +> log`-en bitartez. + + +## Adarrak eta mergeak — I + +![](img/basic-branching-4.png){ height=180px } + +## Adarrak eta mergeak — II + +**Fast forward** kasua. Adar bat bestearen barruan dago. + +![`git checkout master` +`git merge hotfix`](img/basic-branching-5.png){ height=200px } + +## Adarrak eta mergeak — III + +Beti ez da hain erreza. Demagun: + +![](img/basic-branching-6.png){ height=180px } + +## Adarrak eta mergeak — IV + +Arbaso amankomuna (*common ancestor*) ateratzen saiatzen da eta bi buruekin eta +arbaso amankomunarekin *three-way merge* bat egiten du. + +![`git checkout master` +`git merge iss53`](img/basic-merging-1.png){ height=180px } + +## Adarrak eta mergeak — V + +Commit berri bat gehitzen du, bi adarrak lotzen dituena. + +*Merge* commita da: bi guraso (edo gehiago) ditu. + +![`git checkout master` +`git merge iss53`](img/basic-merging-2.png){ height=180px } + +## Konfliktoak — I + +Aurreko kasua ez da beti ondo ateratzen, batzuetan konfliktoak egon daitezke +bi adarretan aldaketak leku berdinetan agertzen direnean: + +``` +$ git merge iss53 +Auto-merging index.html +CONFLICT (content): Merge conflict in index.html +Automatic merge failed; fix conflicts and then +commit the result. +``` + +## Konfliktoak — II + +``` +$ git status +On branch master +You have unmerged paths. + (fix conflicts and run "git commit") + +Unmerged paths: + (use "git add <file>..." to mark resolution) + + both modified: index.html + +no changes added to commit (use "git add" and/or +"git commit -a") +``` + +## Konfliktoak — III + +Fitxategia horrela ikusten da: + +``` +<<<<<<< HEAD:index.html +<div id="footer">contact : + email.support@github.com</div> +======= +<div id="footer"> + please contact us at support@github.com +</div> +>>>>>>> iss53:index.html +``` + +Separadoreak daude `<<<<<<<`, `=======` eta `>>>>>>>`. + +Lehenengo zatian `HEAD`-en zegoena dago eta bigarrenean `iss53`-n zegoena. + +`git mergetool` erabili daiteke konfliktoak errazago konpontzeko. + +## Adarrak kudeatzeko + +- `git branch` adarrak listatzeko +- `git branch --merged | --no-merged` oraingo adarrarekin mergeatuta edo + mergeatu gabe dauden adarrak listatzeko +- `git branch -d <adarra>` adarrak ezabatzeko. Mergeatu gabe dauden adarrak ez + ditu zuzenean ezabatzen. +- `git branch --move <adarra> <izen_berria>` izenez aldatzeko. +- `git push -u|--set-upstream <remote> <adarra>` remoteari zein adar erabili behar + duen esateko +- `git push <remote> --delete <adarra>` remotean adar bat ezabatzeko + +## Adarrekin workflow ezberdinak + +- Long running branches: `master`, `testing` eta `development` +- Topic branches: issue eta feature bakoitzeko adar berri bat eratzen da. + +## Adarrak remotetan + +Gitek remoten erreferentziak gordetzen ditu remoten egoera ikusi ahal izateko. +`git ls-remote <remote>` edo `git remote show <remote>` erabiliz remoteen +egorea ikusi daiteke. + +Remoten adarrak lokalean ikusi daitezke `<remote>/<adarra>` izenarekin. Ezin +dira aldatu. Push egiterakoan aldatzen dira, remotearen egoera aldatu delako. + +![Adibidea: repositorio lokalak bi commit berri ditu](img/remote-branches.png) + +## Push egitea + +- `git push <remote> <adarra>` adarra remotera pusheatzeko. Eskuz egin behar + da. Horrela adar lokalak babesten dira eta ez dira automatikoki igotzen. + +- `<adar_lokala>:<adar_remotoa>` erabiltzean izen ezberdinak jarri ahal zaizkie + adarrei, bata lokalean eta bestea remotean + +## Tracking branches + +Remoteak jarraitzeko erabiltzen mekanismoa da. Remotearen adar bat (*upstream*) +adar lokal baten (*tracking*) arteko erlazioa da. + +- `git checkout -b <adar_izena> <remote>/<adar>`-k `<remote>/<adar>` + `<adar_izena>` izenarekin *track*eatzen du +- `git checkout --track <remote>/<adar>` oraingo adarra eta remotearena + erlazionatu. Sinpleago. +- `git checkout <adarra>`-k erlazioa eratzen du automatikoki, `<adarra>` + lokalean existitzen ez bada. Sinpleago. +- `git clone` egiterakoan `master` adar lokala eratzen da `origin/master` + adarra *track*eatzen. +- `git branch -u|--set-upstream-to <remote>/<adarra>` zure adarraren upstream-a + aldatzeko. Ikusi `git push`-en. + +> `@{upstream}` edo `@{u}` idatzi daiteke hortik aurrera remotearen adarraren +> izen osoa erabili beharrean + +## Pull egitea + +Tracking adarra aktibatuta badago, `git pull` egiteak zuzenean `git fetch` eta +`git merge` aldi berean egingo ditu. + +Kontuz ibili: batzuetan `git pull`-en magia ulertzeko zaila izan daiteke. +Proiektua jende askok ukitzen badu, hobe `git fetch` egitea. + +## Adarrak eta rebaseak — I + +![](img/basic-rebase-1.png) + +## Adarrak eta rebaseak — II + +![`git merge` egitean gertatzen dena](img/basic-rebase-2.png) + +## Adarrak eta rebaseak — II + +![`git checkout experiment` +`git rebase master`](img/basic-rebase-3.png) + +Orain merge-a *fast-forward* izango da eta ez du merge commit-ik gehituko. + +## Rebase konplexuago bat — I + +![](img/interesting-rebase-1.png) + +## Rebase konplexuago bat — II + +![`git rebase --onto master server client`](img/interesting-rebase-2.png) + +`client`-en dauden aldaketak pasatzen ditu `master`-era `server`-en daudenak +izan ezik. + +Orain `server` `master`-en rebaseatu daiteke eta gero `git merge` +*fast-forward* bat egin. + +## Rebasekin kontuz ibili + +Rebaseak egiterakoan commit berriak egiten dira, aurrekoen antzekoak edukiz, ez +dira berdinak. Remote-an pusheatzerakoan beste lankideek rebaseak egitera +behartzen ditu: + +- `git push --force` remotean historia berridazten du. Git zerbitzuetan adar + babestuak existitzen dira hau saihesteko. Kontuz. +- `git pull --rebase`-k lagundu dezake `pull` egiterakoan, remotean historia + berridatzi bada. Pull-en estrategietako bat da, asko daude eta defektuz + egiteko konfiguratu daitezke. + +## Rebase vs Merge + +Filosofiaren arabera bata edo bestea gehiago erabiltzea komeni da: + +- Repositorioa historiko moduan ulertuta: rebase egitea txarra izango + litzateke, historikoa zapaltzen baitu. (*fossil-ek filosofia hau jarraitzen + du, ez dauka rebase egiteko tresnarik*) +- Repositorioa *making of* modura ikusten bada aproposa da rebase egitea. + Historikoa garbiagoa uzten duelako. + +Aholkua: lokalean rebase egin commit historikoa garbitzeko baina behin +zerbitzarira igota historia ez aldatu, lankideen prozesuan eragina baitu. + @@ -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: + +![ ](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 + |