summaryrefslogtreecommitdiff
path: root/1.md
blob: 21825cf71a4a725b082c6346811df31db60548d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
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 <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.