--- title: GIT subtitle: Sarrera eta erabilera basikoa license: CC-BY-NC-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` --- { height=180px } --- { 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 { 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 barrutik  ## 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  ## Adarrak eta aldaketak — II  ## Adarrak eta aldaketak — III  ## Adarrak eta aldaketak — IV  ## Adarrak eta aldaketak — V  ## 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 { height=180px } ## Adarrak eta mergeak — II **Fast forward** kasua. Adar bat bestearen barruan dago. { height=200px } ## Adarrak eta mergeak — III Beti ez da hain erreza. Demagun: { 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. { height=180px } ## Adarrak eta mergeak — V Commit berri bat gehitzen du, bi adarrak lotzen dituena. *Merge* commita da: bi guraso (edo gehiago) ditu. { 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.  ## 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  ## Adarrak eta rebaseak — II  ## Adarrak eta rebaseak — II  Orain merge-a *fast-forward* izango da eta ez du merge commit-ik gehituko. ## Rebase konplexuago bat — I  ## Rebase konplexuago bat — II  `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.