Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • rlacko/git-presentation
  • blintmester/git-presentation
2 results
Show changes
Commits on Source (33)
Showing
with 2096 additions and 25 deletions
node_modules
\ No newline at end of file
image: kroniak/ssh-client
stages:
- deploy
home:
stage: deploy
before_script:
- eval $(ssh-agent -s)
- echo "$SSH" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh/socket
- chmod 700 ~/.ssh
- cp .magic_ssh_config ~/.ssh/config
script:
# AFS magic incoming
- ssh rlacko@centaur.sch.bme.hu cp /afs/sch.bme.hu/home/rlacko/.system/rlacko.keytab /tmp/rlacko.keytab
- ssh rlacko@centaur.sch.bme.hu kinit -k -t /tmp/rlacko.keytab rlacko
- ssh rlacko@centaur.sch.bme.hu rm /tmp/rlacko.keytab
- ssh rlacko@centaur.sch.bme.hu aklog sch.bme.hu -k SCH.BME.HU
- ssh rlacko@centaur.sch.bme.hu mkdir -p /home/rlacko/public_html/git
# actual work
- scp -r $PWD/* rlacko@centaur.sch.bme.hu:/home/rlacko/public_html/git/
only:
refs:
- master
Host *
StrictHostKeyChecking no
ControlMaster auto
ControlPersist yes
ControlPath ~/.ssh/socket/%r@%h:%p
This diff is collapsed.
# Git előadás
# Git doksi
[Bevezető](/guide/intro/1_intro.md)
<script>
window.location.href += "guide/intro/1_intro.md";
</script>
# Headline
> An awesome project.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css">
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
name: '',
repo: ''
}
</script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
</body>
</html>
favicon.ico

6.37 KiB

# Intro
## Bevezetés
Először is üdvözlök mindenkit. Ezen doksi és előadás
végére remélem sikerül egy olyan szintű tudást átadnom,
hogy a jövőben ne okozzon problémát a verziókezelés.
Olyan kérdésekre fogok választ adni, mint "Miért kell
git-et használnom?", "Miért ilyen bonyolult ez az egész?"
és "Mégis mi a francot nyerek ezzel?".
Ja és előre is bocsi a helyesírási hibákért, várom majd
a javításokat a dokumentáció [git repo-jába](https://github.com/rlacko58/gitPresentation) :)
Amire szükséged lesz: Egy konzol működő git-el ([Workshop elején](workshop/1_installation.md)
van egy útmutató)
## Tippek
Próbáld a parancsokat saját magad is kiadni, ugyanis
leghatékonyabban gyakorlati módon lehet a git-et elsajátítani.
Emellett légy kitartó és ne ijedj meg a rengeteg információtól.
A git nem egy egyszerű témakör, de hidd el, megéri a
belefektett munkát.
## Ki vagyok én?
Rafael László (Lackó), harmadéves mérnökinformatikus
szoftverjlesztő speces hallgató.
Jelenleg a DevTeam körvezetője, de a KSZK többi körében
is aktívan tevékenykedem.
Manapság főleg webfejlesztéssel foglalkozom,
olyan projekteken dolgoztam, mint az AdminSCH
vagy a KSZK Újonc weboldala.
Ha bármi kérdésed merülne fel a doksi olvasása vagy az előadás
során nyugodtan keress meg
- Emailben: laszlo.rafael [kukac] kszk.bme.hu
<div style="text-align:center"><img src="guide/intro/img/me.jpg" alt="Kép magamról" /></div>
Forrás: [Pro Git könyv](https://git-scm.com/book/en/v2/)
# Verziókezelés
Mi is az a verzió kezelés?
Talán a legegyszerűbb egy példán keresztül szemléltetni.
Tegyük fel egy docx fájlt szerkesztünk és ezt hetente
frissítve rendszeresen el kell küldenünk emailben valakinek.
Ilyenkor különböző verziók keletkeznek a fájlból és ezeket
a postafiókunkból könnyedén előtudjuk szedni.
Na ugyanazen a példán tovább mehetünk.
Mi van ha lokális kezdjük ezeket a fájlokat tárolni?
Gondolom mindenki találkozott már hasonló fájlnevekkel:
```
├── elso_beadasom.docx
├── masodik_beadasom.docx
├── masodik_beadasom (1).docx
├── masodik_beadasom (1) Javított.docx
├── masodik_beadasom (1) Javított másolata.docx
├── asd.docx
├── asdasd.docx
└── asdasdasdasd.docx
```
Ha ügyesek vagyunk még mappákat is készítünk és dátumot is hozzá cimkézünk.
```
└── 2020
└── 09
├── 13
│ └── elso_beadasom.docx
├── 19
│ └── masodik_beadasom_felkesz.docx
├── 20
│ ├── masodik_beadasom.docx
│ ├── masodik_beadasom_javitott.docx
│ └── masodik_beadasom_vegleges.docx
└── ideiglenes
├── asd.docx
├── asdasd.docx
└── asdasdadsads.docx
```
Persze az operációs rendszer képes dátum alapján rendezni,
és megspórol nekünk pár lépést, de mi van ha ezt valakinek
el is szeretnénk küldeni? Mi van ha a módosítás dátuma közben
módosul? Hogyan biztosítjuk, hogy közben nem sérülnek a fájlok?
Ezekre megoldást adnak a különböző verziókezelő rendszerek.
Többek közt dolguk, hogy fájljaink számon tartsák, ahogy például
kézileg tettük.
### Milyen verzió kezelő rendszereink lehetnek?
#### Helyi
Erre a fenti példa legjobb példa.
Vannak különböző verziói a fájlunknak és ezeket valamilyen
adatbázisban rögzítjük.
<div style="text-align:center"><img src="intro/img/vcstype_local.png" alt="Local Version Control Systems" /></div>
Ilyen az [RCS](https://www.gnu.org/software/rcs/)
### Központosított
Ez már egy fokkal okosabb.
A különböző verziókat a központi szerverre rakjuk fel és
onann szedjük le.
Például van egy Fájlszerverünk amit minden gépről elérnek
az emberek és oda dolgoznak közösen.
Érezhető probléma, hogy így ha meghal a központi szerver,
akkor mindent elvesztünk.
Továbbá probléma lehet, hogy egymás munkáját felülírjük,
szerencsére egy jó rendszernél erről értesítést kapunk,
hozzá és nem felülírjuk a módosításaink.
<div style="text-align:center"><img src="intro/img/vcstype_central.png" alt="Centralized Version Control Systems" /></div>
### Megosztott
Na és itt lépünk be a ma is használt Git világába.
Ennél a megoldásnál már az a trükk, hogy mindenkinek meg van
a teljes projekt az összes verziójával. Felmerül, hogy na
de akkor honnan szedjük le a legújabb verziót?
Különböző megoldások léteznek, például a fejlesztők a
módosításokat azonnal megosztják egymással
(pl.: p2p Torrenthez hasonló módon) vagy
kijelölnek egy központi szervert amivel mindenki
szinkronban van.
Ilyen központi szerver lehet például a Github vagy a Gitlab.
Csak megjegyzem, de akár a módosításokat Emailben is ellehet
küldeni és a szoftver automatikusan megcsinálja a többi a mi részünkön.
<div style="text-align:center"><img src="guide/intro/img/vcstype_distributed.png" alt="Distributed Version Control Systems" /></div>
# Git története
Még mielőtt belemerülnék a git telepítésébe, használatába,
szeretnék némi sztorizást is megejteni.
Annó a Linux kernel fejlesztése során okozott nagy fejtörést
az egész verziókezelés megoldása.
1991-től 2002-ig, tehát 11 éven át patchekben
(pl.: e-mailben elküldött szöveg a módosításokkal)
és tömörített fájlokban küldözgették a verziókat a fejlesztők.
Aztán 2002-től egy zárt licenszű verzió kezelőre, a
[BitKeeper](http://www.bitkeeper.org/)-re váltottak.
Ezt a Linux fejlesztői ingyen használhatták egészen 2005-ig,
mikorra annyira elromlott a kapcsolat a fejlesztők és a cég
között, hogy elvették tőlük a licenszt.
Az i-re a pontott az tette le, mikor az egyik
kernel fejlesztő
[reverse engineer-elte](https://lwn.net/Articles/132938/)
a BitKeeper-t.
Ekkoriban
[Linus Torvalds](https://en.wikipedia.org/wiki/Linus_Torvalds)
úgy döntött, hogy egy új megoldást kell találnia, mely
- Gyors
- Egyszerű
- Támogatja a többszálú fejlesztést
- Teljesen elosztott
- Nagy projekteket is képes kezelni (pl.: Linux kernel)
Így hát megírta a [Git-et](https://en.wikipedia.org/wiki/Git), mely a mai napig a legelterjedtebb, leggyorsabb és
legkényelmesebb verzió kezelő rendszerünk.
guide/intro/img/me.jpg

58.2 KiB

guide/intro/img/vcstype_central.png

22.3 KiB

guide/intro/img/vcstype_distributed.png

26 KiB

guide/intro/img/vcstype_local.png

19.8 KiB

# Alapok és SSH kulcs
### Alapok
Hogyan lehet a mi `.git` mappánkat megosztani a nagyvilággal?
Több módja is van ennek, például akár egy .git mappát
is lelehet magunkhoz klónozni.
A `git clone <elérési út>` parancsot használjuk ahhoz, hogy
valahonnan lehúzzunk egy git repo-t.
Ha például csak egy mappára utalunk, aminek a neve
`awesome_project.git`:
```
$ git clone --bare awesome_project awesome_project.git
Cloning into bare repository 'awesome_project.git'...
done.
```
Ezt akár kirakhatjuk egy fájlszerverre és onnan megoszthatnánk.
Következő szint, mikor weben keresztül szedjük le a nekünk
kellő repo-t. Ilyenkor HTTP protokollt használhatunk,
ami hasonló az előzőhöz és olyan, mint mikor egy fájlt
töltünk le egy oldalról.
```
$ git clone https://github.com/rlacko58/git-presentation.git
Cloning into 'git-presentation'...
remote: Enumerating objects: 173, done.
remote: Counting objects: 100% (173/173), done.
remote: Compressing objects: 100% (114/114), done.
remote: Total 173 (delta 65), reused 155 (delta 47), pack-reused 0
Receiving objects: 100% (173/173), 291.34 KiB | 1.22 MiB/s, done.
Resolving deltas: 100% (65/65), done.
```
Ez szimplán fogja és készít nekünk egy olyan repository-t, mint
amit az előzőkben csináltunk kézzel.
Lemásolja a .git mappát, majd pedig onnan kiszedi a megfelelő
dolgokat a mi `work tree`-nkbe.
### SSH
Másik protokoll amit tudunk használni az az SSH.
Ez azért nagyon jó, mert ha ezen keresztül szedünk le,
akkor nem kell minden alkalommal a github, gitlab
felhasználónkba belépnünk egy repo-n való dolgozáskor.
Ahhoz, hogy ilyet tudjunk csinálni viszont SSH kulcsot kell
készítenünk.
Ennek annyi a trükkje, hogy rakunk a saját gépünkre egy
privát kulcsot és a távoli szerverre egy publikus kulcsot,
vagy bárhova ahova szeretnénk.
Ezután mikor az adott szerverre felakarunk menni, valamit
csinálni ott, akkor előtte a szerver leauthentikál minket
és egy kulcs csere után elkezdhetünk vele kommunikálni.
Az authentikáció lépése nagy vonalakban:
- Szerver publikus kulcsal letitkosít valamit és elküldi nekünk
- Ezt amit elküld csak a privát kulccsal lehet kibontani,
ezt mi elvégezzük
- A kibontott adatok közt lesz egy másik kulcs, mellyel
titkosítva elküldjük a szervernek ami kell az authentikációhoz
- A szerver kibontja, látja hogy minden oké és
megtörténik a kulcs csere
Ezután áttérnek egy másik módszerre amihez már mindkét oldalt
megvan a megfelelő kulcs és titkosítva küldik egymásnak
az adatokat
Nagyon király dolog, mivel gyors, hatékony és nem kell
jelszót beírogatni minden művelet közt
#### Saját SSH kulcs
###### Linuxon / MacOS-en
1. Terminált megnyitjuk
2. Generálunk egy SSH kulcsot
`ssh-keygen -t rsa -b 4096`
3. Alapértelmezett helyre mentjük
4. Megadunk egy jelszót ha szeretnénk
_Ha valaki megszerzi a privát kulcsunk nem tudja használni
a jelszó beírása nélkül_
Adjuk hozzá az SSH agent-ünkhöz.
1. Elindítjuk az agent-et ha még nem ment volna
`$ eval "$(ssh-agent -s)"`
`Agent pid 59566`
2. Hozzáadjuk az új kulcsunk
`ssh-add ~/.ssh/id_rsa`
Végezetül a publikus kulcsot feltöltjük például githubra
A publikus kulcs helye: `~/ssh/id_rsa.pub`
###### Windowson
1. Git Bash-t megnyitjuk
2. Generálunk egy kulcsot
`ssh-keygen -t rsa -b 4096`
3. Elmentjük az alapértelmezett helyre
4. Jelszó adunk hozzá ha szeretnénk
Hozzá adjuk az SSH agent-ünkhöz
1. Elindítjuk az agent-et ha még nem ment volna
`$ eval $(ssh-agent -s)`
`> Agent pid 59566`
2. Hozzáadjuk az új kulcsunk
`ssh-add ~/.ssh/id_rsa`
Végezetül a publikus kulcsot feltöltjük például githubra
A publikus kulcs helye: `~/ssh/id_rsa.pub`
Forrás: [docs.github.com](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)
# Telepítés és konfiguráció
A Git-nek vannak grafikus kliens-ei is, de ahhoz, hogy igazán
megérthessük konzolt fogunk használni.
Továbbá azt is hozzátenném, hogy a grafikus alkalmazások nem tudják lefedni a Git összes rendelkezésre álló funkcióját
és néha nagyon lebutítják a felhasználó felé, ezért
nem is lehet feltétlen megtanulni a működését grafikus
alkalmazásból.
## Telepítés
#### Windows
Elég egyszerű a telepítés.
Felmész a [https://git-scm.com/download/win](https://git-scm.com/download/win) címre és az ott lévő .exe fájlt letöltöd.
A telepítőben a beállításokkal nem kell foglalkozni, az
alapértelmezett mindenhol jó lesz.
Esetleg később ha szeretnél egy grafikus felület, akkor a Github
Desktop is egy jó opció. Ez magába foglalja mind a konzolos,
mind az asztali programot.
[https://desktop.github.com/](https://desktop.github.com/)
#### MacOS
Nincs sok tapasztalatom vele, de ha megpróbálod konzolból
kiadni a
`git --version`
parancsot, akkor fel fogja ajánlani,
hogy telepítsd. Itt kapsz egy telepítőt és az alapértelmezett
beállításain végig mész.
#### Linux
Talán a legtriviálisabb. Attól függően milyen disztrót használsz,
letölthető a megfelelő csomagkezelővel.
RPM alapúak (Fedora, RHEL, CentOS, ...):
`sudo dnf install git`
Debian alapúak (Ubuntu, ...):
`sudo apt install git`
Többi Disztróra:
[git-scm.com/download/linux](https://git-scm.com/download/linux)
## Konfiguráció
### Hol vannak a konfigok?
Legegyszerűbben ezzel a paranccsal lehet a jelenlegi konfig
fájlok helyzetét kiírni:
`git config --list --show-origin`
Látható, hogy a konfigok valamilyen config fájlba menti
a fájlrendszerben elszórva. Erről egy pár táblázat:
##### Windows
| Scope | Hely | Fájlnév |
| -------- | ---------------------------- | --------------- |
| Rendszer | mingw32\etc vagy mingw64\etc | gitconfig |
| Globális | C:\Users\\<felhasználónév> | .gitconfig |
| Lokális | Git repo .git mappája | config |
| Worktree | Git repo .git mappája | config.worktree |
| Portable | C:\ProgramData\Git\ | config |
##### Linux (Ubuntu)
(MacOS ehhez hasonló)
| Scope | Hely | Fájlnév |
| -------- | --------------------- | --------------- |
| Rendszer | /etc | gitconfig |
| Globális | ~ | .gitconfig |
| Lokális | Git repo .git mappája | config |
| Worktree | Git repo .git mappája | config.worktree |
Nálam a konfig a home mappámban például így néz ki:
```
$ cat ~/.gitconfig
[user]
email = rlacko99 [AT] gmail.com
name = Rafael László
```
### Állítsuk be a dolgokat magunknak
##### Saját adatok
Először is a saját adataink:
```
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe [AT] example.com
```
##### Szövegszerkesztő
Állítsuk be a szövegszerkesztőnket.
Erre főként a mentéspontokhoz tartozó üzenet megírásához van
szükség.
```
$ git config --global core.editor nano
```
vagy például notepad++-ra windows-on:
```
$ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
```
##### Jelenlegi konfig
Nézzük meg az összes beállításunk:
```
$ git config --list
user.email=rlacko99 [AT] gmail.com
user.name=Rafael László
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
...
```
Ha pedig csak egy adottat szeretnénk:
```
$ git config user.name
Rafael László
```
# Alapok
##### Mit tegyek ha elakadok?
Git-ben van egy beépített git help parancs:
```
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
```
Például a config-al kapcsolatos dolgok:
```
$ git help config
```
De ha csak egy gyors áttekintésre van szükséged:
```
$ git config -h
usage: git config [<options>]
Config file location
--global use global config file
--system use system config file
--local use repository config file
--worktree use per-worktree config file
-f, --file <file> use given config file
--blob <blob-id> read config from given blob object
Action
--get get value: name [value-regex]
...
```
#### Repository
A Git repository egy olyan mappa, mely Git verziókezelés alatt
áll.
Tehát az a mappa, ahol van egy .git mappa, az egy git repo.
```
$ ls -al
total 20
drwxrwxr-x 4 rlacko rlacko 4096 okt 8 12:59 .
drwxrwxr-x 3 rlacko rlacko 4096 okt 7 12:04 ..
drwxrwxr-x 5 rlacko rlacko 4096 okt 7 12:46 docs
drwxrwxr-x 8 rlacko rlacko 4096 okt 8 16:39 .git
-rw-r--r-- 1 rlacko rlacko 17 okt 7 12:09 README.md
```
Csináljunk egy sajátot!
Hozzunk létre egy tetszőleges projekt mappát és lépjünk bele
```
$ mkdir projektem
$ cd projektem
```
Nézzük meg, hogy mi a helyzet a git-el.
Ehhez a `git status` parancsot tudjuk használni.
Ez a parancs a jelenlegi git repo-nkról képes
információkat kiírni.
```
$ git status
fatal: not a git repository (or any of the parent directories): .git
```
Teljesen üres a mappa, még nincs verzió kontroll alatt.
`ls -al` -el tudjuk is ellenőrizni, hogy nincsen `.git`
mappa.
Tegyük verziókontroll alá a `git init` paranccsal.
Ez beállítja nekünk a `master` branchet és más alap dolgokat.
A branch-ről még később beszélek, de azt jegyezzük meg addig,
hogy ide kerülnek a mentéspontjaink egymás után sorban, mint
egy fa ága.
<div style="text-align:center"><img src="guide/workshop/img/basic-branching.png" alt="Git branch" /></div>
```
$ git init .
Initialized empty Git repository in .../projektem/.git/
```
Ha megnézzük, mostmár van egy .git mappánk
```
$ ls -al
total 12
drwxrwxr-x 3 rlacko rlacko 4096 okt 8 16:52 .
drwxrwxr-x 12 rlacko rlacko 4096 okt 8 16:49 ..
drwxrwxr-x 7 rlacko rlacko 4096 okt 8 16:52 .git
```
Ebben van minden adatunk a git repo-val kapcsolatban.
Gyakorlatilag mikor egy távoli git repo-t leszedünk, akkor
ezt a mappát kapjuk meg. Ebből ezután a git alkalmazásunk
előállítja nekünk a master ág legutóbbi mentéspontját.
#### Mentéseink tárolása
Egy logikus megoldásnak tűnhet, hogy az egyes fájlok közt
csak az eltéréseket tároljuk. Például:
```gyumolcskosar
1. mentés:
alma
2. mentés:
[1.mentés 1.sora]
alma
```
Ez annyiból jó, hogy a tárhellyel spórol, viszont nem gyors.
Képzeljünk el egy 1000 commit-ból álló repo-t.
Mi történik mikor a legutóbbit lekérjük?
Erre egyik megoldás más verziókezelőknél, hogy optimalizálnak
és mondjuk 50 mentésenként csinálnak egy teljes mentést, stb.
A Git ezt úgy oldja meg, hogy egy mentés az összes fájlt
egy az egybe lemásolja.
Például egyik mentés alkalmával feltöltök egy 1gb-os videót,
majd a következő mentéskor pár bitet átírok, akkor már
2gb-nyi videó lesz a repóban és ha utána egy másik mentésel
ki is töröljük, az attól még megmarad.
Persze utólag tudunk olyat, hogy visszmegyünk és kitöröljük
az adott mentésből.
Oké, tehát például mappákba bemásolja a mentéseinket valamilyen
módon, de mégis hova?
```
$ tree .git/objects/
.git/objects/
├── 13
│ └── 46dac32baea8123272f60b6a04227fe3872bdb
...
├── e6
│ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
├── f4
│ └── 5a6ff55496414b573e97064e998f065182eeee
├── info
└── pack
```
Mégis mik ezek?
A Git tömörítve és hashelve tárolja a fájlokat.
A hashelésnek annyi a lényege, hogy a fájl teljes tartalmán
átfuttatunk egy algoritmust, mely ezután kiköp egy 0-9a-z
szöveget és ha akár 1 bit-et is változtatunk egy fájlon, akkor
más lesz a hash-e.
Tehát ha valaki elcommitol valamit, akkor azt már más nem tudja
megváltoztatni anélkül, hogy változna a hash.
Így tudjuk biztosítani a teljes konzisztenciát az elosztott
repo-k között.
Hash-t láthatunk például a mentéspontjainkon, fájljainkon, stb.
Például itt egy ábra, hogy hogyan társítja a git egy
commit-hoz a megfelelő fájlokat egy kis pointer mágia keretében.
<div style="text-align:center"><img src="guide/workshop/img/commit-and-tree.png" alt="Commit and Tree" /></div>
Ennél jobban nem megyek bele a témába, de érdekes olvasmány.
#### Változtatások mentése
Hogyan néz ki egy mentés?
```
commit c45abc3d64c7840b4088b77d5a60d02198a78854
Author: Rafael László <rlacko99 [AT] gmail.com>
Date: Thu Oct 8 17:19:28 2020 +0200
Készítettem egy gyümölcskosarat
```
Van egy commit-nak `commit hash`-e, `készítője`,
`létrehozási dátuma`, és `commit üzenete`
Na de hogyan készítünk egy mentéspontot?
A fájljainknak különböző állapotai létezhetnek egy
repo-ban.
- Untracked: Ami még nincs verziókontroll alatt
- Staged: Ami már verziókontroll alatt van de még nem
mentettük el
- Unmodified: Amit már elmentettünk és azóta nem változott
- Modified: Az a fájl, ami már verziókontroll alatt van
és változott. Ezt utánna szintén Stage-be tudjuk tenni
Nézzük meg ezen az ábrán és egy példa projekten keresztül:
<div style="text-align:center"><img src="guide/workshop/img/git_lifecycle.png" alt="Git Life cycle" /></div>
Mi a jelenlegi helyzet a frissen inicializált repo-ban?
```
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
```
Láthatjuk, hogy még nincsenek mentéspontjaink, nincs mit
elmentenünk és egyben a git próbál segíteni, hogy hogyan
tudunk stagelni valamit.
Ezt több helyen is megfigyelhetjük a git-ben.
Próbál segíteni ahol csak tud.
Vegyünk fel egy új fájlt.
```
echo 'alma' > gyumolcskosar
```
_Itt az `echo` egy olyan parancs volt, mely kiírta nekünk a
terminálra azt, hogy "alma", de átirányítottuk egy fájlba
a `>` operátorral és mivel nem létezett a fájl, azt létre is
hozta._ - Linux magic #01
Újra megvizsgálva a status-t, látni fogjuk, hogy megjelent, de
még nincs verziókontroll alatt.
```
$ git status
...
Untracked files:
(use "git add <file>..." to include in what will be committed)
gyumolcskosar
nothing added to commit but untracked files present (use "git add" to track)
```
Ahhoz, hogy git alá helyezzük, a `git add <fájl>` parancsot
fogjuk kiadni.
_Ezek a parancsok mind képesek rá, hogy
Unix-os módon több fájlra is kiadhatóak legyenek.
Például a `<fájl>` lehet `*.jpg`amivel minden .jpg fájlt kijelölünk a jelenlegi mappában"_ - Linux magic #02
```
$ git add gyumolcskosar
```
Ezután megjelenik, mint új fájl a git adatbázisában.
```
$ git status
...
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: gyumolcskosar
```
A fájlunk átkerült staged módba és ezt akár el is
tudjuk menteni.
A mentéshez a `git commit` parancsot tudjuk
használni.
`$ git commit`-ot kiadva megnyilik a beállított szövegszerkesztőnk és némi
információ a leendő mentéspontról.
```
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
#
# Initial commit
#
# Changes to be committed:
# new file: gyumolcskosar
```
Láthatjuk amit a `git status` parancs írna ki és pár extra
segítséget a git-től.
A # -el kezdődő sorok kommentek, ezek nem fognak a commit
üzenetbe belekerülni.
Írjuk be az első sorba, hogy `Készítettem egy gyümölcskosarat`,
majd mentsük el a fájlt és zárjuk be a szövegszerkesztőt.
```
$ git commit
[master (root-commit) c45abc3] Készítettem egy gyümölcskosarat
1 file changed, 1 insertion(+)
create mode 100644 gyumolcskosar
```
A git mikor érzékelte, hogy bezártuk a fájlt, akkor abból
kiolvasta a sorokat, ignorálva a #-el kezdődőket és hozzáadta
a mentéspontunkhoz, mint üzenet.
Ezt láthatjuk is a visszajelzésben.
Továbbá megjelent pár további hasznos információ is.
Ismételten nézzük meg mi a helyzet a reponkban:
```
$ git status
On branch master
nothing to commit, working tree clean
```
Mostmár nem szól amiatt, hogy még nincsen mentésünk, továbbá
azt is írja, hogy még semmin nem változtattunk, nem tudunk
mit elmenteni.
Nézzük meg a további két állapotot is amiben lehet egy fájl.
Írjuk bele a gyumolcskosar fájlba, hogy `korte`
```gyumolcskosar
alma
korte
```
Ezután kiadva a `git status`-t:
```
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: gyumolcskosar
no changes added to commit (use "git add" and/or "git commit -a")
```
Látható, hogy mostmár `modified` a fájlunk, mentsük is el,
de most picit másképp. A git és általában minden Unix
parancsnak áttudunk adni úgynevezett kapcsolókat.
Például `git commit -m <message>`.
Ez annyit spórol meg nekünk, hogy nem kell szövegszerkesztőt
megnyitnia a git-nek mikor új commit-ot készítünk,
hanem átrakjuk a parancsot olyan módba,
hogy várjon egy szöveget, mint mentéshez kapcsolódó üzenet.
Általában logikusak az egy betűs rövidítések:
`-m: message, -a: all`, de tudunk hosszabb verziókat is
használni, mint `--message, --all`.
> Ne felejtsük el először stagelni a mentendő fájljaink egy
> `git add <fájl>` parancs kiadásával.
```
$ git add gyumolcskosar
$ git commit -m "Raktam bele egy körtét"
```
Készítsünk egy új fájlt `hordo` néven és nézzük mit ír ki
a `git status -s` parancs.
```
$ git status -s
?? hordo
```
Ezzel a kapcsolóval képesek vagyunk egy rövidített státuszt
lekérni. Stageljük majd pedig commitoljuk el
`"Hoztunk egy hordót"` üzenettel. A lépések közt nézzük meg
mit ír ki a `git status -s`.
Mi van akkor, ha valami fájlt nem szeretnénk verziókontroll
alá tenni? Gondolok például a build-ek mappáira vagy
egy IDE által generált fájlokra.
Hozzunk létre egy `.gitignore` fájlt és egy `jegyzeteim.txt`
fájlt.
Ezután adjuk ki a `git status` parancsot.
Láthatjuk, hogy a `jegyzeteim` fájl megjelent.
Most írjuk be a fájl nevét a `.gitignore`-ba.
```.gitignore
jegyzeteim.txt
```
Ezt követően adjuk ki újra a `git status` parancsot.
Oh, eltünt a fájlunk! Pont ezt akartuk, mostmár nem fogja
figyelni a git ha ilyen fájlt készítünk.
Mostmár csak stageljük és mentsük el az új fájlunk.
`git add .`, `git commit -m "jegyzeteim ignorálása"`
#### Fájlok mozgatása
A git semmi adatot nem tárol változásokról, csak
mentéseket készít, ahogy említettem.
Próbáljuk ki, hogy mi történik ha átnevezünk egy fájlt?
```
mv gyumolcskosar gyumolcskosar.txt
```
```
git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: gyumolcskosar
Untracked files:
(use "git add <file>..." to include in what will be committed)
gyumolcskosar.txt
no changes added to commit (use "git add" and/or "git commit -a")
```
Látható, hogy az eredeti fájlt "töröltük" és egy új
fájlt vettünk fel a repo-ba. Érdekes, mi lenne ha stagelnénk
a változtatásokat `git add .` -al?
```
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: gyumolcskosar -> gyumolcskosar.txt
```
Most meg már látszik, hogy csak átnevezés történt?
A Git képes rá, hogy felismerje a fájlokat és eldöntse, hogy
ugyanaz volt a kettő, tehát átnevezés, mozgatás, stb. történt.
De nem tudja követni a fájlt, csak látja, hogy jött egy új
fájl ami szinte ugyanaz, mint ami törölve lett nemrég.
#### Mentési előzmények
A Git egyik legjobb parancsa a `git log` a `git status` után és
szeretném ha kipróbálnád.
```
commit 80560db1f5a83496b80f1959fbcbae2ccfff320e (HEAD -> master)
Author: Rafael László <rlacko99 [AT] gmail.com>
Date: Thu Oct 8 21:07:25 2020 +0200
jegyzeteim ignorálása
commit 30bf35d36399e484b03090570e13cb95da92ab8b
Author: Rafael László <rlacko99 [AT] gmail.com>
Date: Thu Oct 8 20:11:58 2020 +0200
Hoztunk egy hordót
commit b677a8639193479157f7a576dffe0186b0dbe2c8
Author: Rafael László <rlacko99 [AT] gmail.com>
Date: Thu Oct 8 17:33:07 2020 +0200
Raktam bele egy körtét
commit c45abc3d64c7840b4088b77d5a60d02198a78854
Author: Rafael László <rlacko99 [AT] gmail.com>
Date: Thu Oct 8 17:19:28 2020 +0200
Készítettem egy gyümölcskosarat
```
Itt azt láthatjuk, hogy milyen mentéspontjaink vannak
és a hozzájuk tartozó dolgokat, mint a commit hash vagy
a üzenet.
Picit tegyük szebbé. Adjuk ki az előző parancsot a
`--oneline` kapcsolóval.
```
80560db (HEAD -> master) jegyzeteim ignorálása
30bf35d Hoztunk egy hordót
b677a86 Raktam bele egy körtét
c45abc3 Készítettem egy gyümölcskosarat
```
Máris csak a lényeget látjuk. Az is látható, hogy csak 7
karaktert kaptunk a hashből.
Elég csak pár karakter, hogy beazonosítsunk
például egy commitot a hash-ével.
# Branch-ek, elágazás
#### Mik azok a branch-ek?
Talán legegyszerűbb, ha előbb készítünk egyet.
Az előző témakörben átneveztünk egy fájlt, de
nem commitoltuk el.
Ezt ne tegyük meg, hanem készítsünk egy ágat onnan,
ahol jártunk mondjuk azzal a névvel, hogy `atnevezes`.
Először nézzük meg, mi a helyzet jelenleg a
`git status` paranccsal.
```
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: gyumolcskosar -> gyumolcskosar.txt
```
Látható, hogy a `master` nevű ágon vagyunk.
Ezt képzeljük el úgy, mint egy fa törzse, melyből
le ágazunk.
Nézzük meg jelenleg milyen branch-ek vannak a repo-nkban
a `git branch` paranccsal.
```
$ git branch
* master
```
Látható, hogy még csak egy van.
Ha a `git branch <új branch neve>` parancsot kiadjuk, akkor
készül egy új ág, de arra figyeljünk, hogy ilyenkor még nem
megyünk át rá.
Nézzük is meg, hogy tényleg elkészült a `git branch` paranccsal.
```
$ git branch
atnevezes
* master
```
Itt a `*` azt jelöli, hogy melyiken vagyunk jelenleg.
Ha kiadnánk a `git status` parancsot, akkor is láthatnánk
melyik ágon vagyunk.
Gyerünk át az új ágra.
Ehhez a `git checkout <ág neve>` parancsot tudjuk használni.
```
$ git checkout atnevezes
D gyumolcskosar
A gyumolcskosar.txt
Switched to branch 'atnevezes'
```
Itt azt is látjuk azonnal, hogy a módosításainkkal nem történt
semmi.
Ezek jelenleg még `staged`-be vannak és ha elmentjük őket
a commital, akkor az épp jelenlegi ágra fogja
beilleszteni őket.
Nézzük meg `git status`-al, hogy mi a helyzet.
```
$ git status
On branch atnevezes
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: gyumolcskosar -> gyumolcskosar.txt
```
Látszik is, hogy az `atnevezes` ágon vagyunk.
Mentsük el ide a módosításaink
`Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz`
üzenettel
```
$ git commit -m "Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz"
[atnevezes 7de1c94] Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
1 file changed, 0 insertions(+), 0 deletions(-)
rename gyumolcskosar => gyumolcskosar.txt (100%)
```
Ezt követően ha kiadjuk a `git log --graph --oneline` parancsot, akkor
meg is láthatjuk a jelenlegi helyzetet a mi fánkban:
```
* 7de1c94 (HEAD -> atnevezes) Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
* 80560db (master) jegyzeteim ignorálása
* 30bf35d Hoztunk egy hordót
* b677a86 Raktam bele egy körtét
* c45abc3 Készítettem egy gyümölcskosarat
```
#### Hogy épül fel?
Először is, ahhoz hogy tudja a git melyik mentéspont után
melyik jön, mutatókat használ ehhez az ábrához
hasonló módon:
<div style="text-align:center"><img src="guide/workshop/img/commits-and-parents.png" alt="Commits and parents" /></div>
A mentéspontjaink az előzőre mutatnak.
Ahogy láthattuk az előző fejezetben, a mentéspontok pedig
mutatnak a megfelelő fájlokra amiket épp módosítottunk.
Vizsgáljuk meg a jelenlegi repo-nkat, hogy pontosan
mi merre is van.
<div style="text-align:center"><img src="guide/workshop/img/tree_with_one_branch.png" alt="Tree with one branch" /></div>
A mentéspontok képesek mutatni az előzőre, ezt láthatjuk
az ábrán.
Továbbá azt is látjuk, hogy van még 3 pointerünk.
Az egyik `master`, ez az ami a legfrissebb mentésre
mutat a master ágon.
Ugyanez igaz az `atnevezes` ág esetében, de oda még mutat
egy `HEAD` mutató is.
Ez az a mutató ami azt jelzi, hogy hol vagyunk mi jelenleg.
Mikor egy új mentést hozunk létre, akkor az a mentés ide
fog mutatni.
Ezért is kellett figyelni az előzőnél, hogy mentés
előtt átváltsunk a megfelelő ágra.
#### Ágak közti mozgás
Még mielőtt vissza mennénk a master-re, nézzük meg milyen
fájljaink vannak az `ls -al` -el.
```
$ ls -al
total 20
drwxrwxr-x 3 rlacko rlacko 4096 okt 8 21:07 .
drwxrwxr-x 12 rlacko rlacko 4096 okt 8 16:49 ..
drwxrwxr-x 8 rlacko rlacko 4096 okt 9 15:01 .git
-rw-rw-r-- 1 rlacko rlacko 15 okt 8 20:43 .gitignore
-rw-rw-r-- 1 rlacko rlacko 11 okt 8 17:29 gyumolcskosar.txt
-rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:09 hordo
-rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:42 jegyzeteim.txt
```
Egy pár extra adatot is kapunk, de nekünk most a
`gyumolcskosar.txt` a lényeges.
Most gyerünk vissza a `master` ágra a `git checkout <ág neve>`
paranccsal.
```
$ git checkout master
Switched to branch 'master'
```
Most adjuk ismét ki az `ls -al` parancsot.
```
$ ls -al
total 20
drwxrwxr-x 3 rlacko rlacko 4096 okt 9 15:24 .
drwxrwxr-x 12 rlacko rlacko 4096 okt 8 16:49 ..
drwxrwxr-x 8 rlacko rlacko 4096 okt 9 15:24 .git
-rw-rw-r-- 1 rlacko rlacko 15 okt 8 20:43 .gitignore
-rw-rw-r-- 1 rlacko rlacko 11 okt 9 15:24 gyumolcskosar
-rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:09 hordo
-rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:42 jegyzeteim.txt
```
Látható, hogy vissza léptünk arra az állapotra mikor még
nem változtattunk rajta.
Ez elképesztően jó, ugyanis két teljesen külön álló munkát
így elkülönítöttünk egymástól!
Írjuk a `gyumolcskosar` fájl végére, hogy `szolo` és mentsük el
azzal az üzenettel, hogy `Tettem a kosaramba szőlőt`.
```
$ git commit -m "Tettem a kosaramba szőlőt"
[master 932cbeb] Tettem a kosaramba szőlőt
1 file changed, 1 insertion(+)
```
Most újra kiadva a `git log --graph --oneline` parancsot,
már érdekesebb eredményt láthatunk.
```
$ git log --graph --oneline
* 15719cf (HEAD -> master) Tettem a kosaramba szőlőt
* 80560db jegyzeteim ignorálása
* 30bf35d Hoztunk egy hordót
...
```
Mégis hova tünt a másik águnk?
A git nem fogja alapból jelezni nekünk azt amit nem lát
a jelenlegi mentéstől vissza menve.
Hogy lássuk a másik ágat is, tegyük hozzá a `--all` kapcsolót.
```
$ git log --graph --oneline --all
* 15719cf (HEAD -> master) Tettem a kosaramba szőlőt
| * 7de1c94 (atnevezes) Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
|/
* 80560db jegyzeteim ignorálása
* 30bf35d Hoztunk egy hordót
...
```
Na így már látjuk a másik ágat is.
Még vizuálisabban jelenleg így állunk:
<div style="text-align:center"><img src="guide/workshop/img/tree_awesome.png" alt="Tree with one branch" /></div>
Menjünk vissza az `atnevezes` ágra és módosítsunk picit.
```
$ git checkout atnevezes
```
Majd pedig nevezzük át a `hordo`-t `hordo.txt`-re.
```
$ mv hordo hordo.txt
```
És ezt is mentsük el
```
$ git add .
$ git commit -m "Adtam kiterjesztést a hordónak"
```
Egy ismételt `git log`-al láthatjuk is a fánkat.
```
$ git log --graph --oneline --all
* 9dcfc79 (HEAD -> atnevezes) Adtam kiterjesztést a hordónak
* 7de1c94 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
| * 15719cf (master) Tettem a kosaramba szőlőt
|/
* 80560db jegyzeteim ignorálása
```
#### Mergelés
Az egyik legfontosabb dolog az ágak létrehozása után, hogy
betudjuk olvasztani az águnk valahova.
Az lenne a feladat, hogy a `master`-re beillesszük az
`atnevezes` ágon végzett módosításaink.
Ehhez a `git merge <branch neve>` parancsot használhatjuk.
A lényege, hogy ez a parancs azt az ágat amit kiválasztottunk
megpróbálja beolvasztani oda ahol épp a `HEAD` mutatónk van.
Gyerünk is át a `master` ágra.
```
$ git checkout master
Switched to branch 'master'
```
Ezután pedig mergeljük át a `master`-re az `atnevezes` ágat.
```
git merge atnevezes
```
Ekkor meg fog nyílni a szövegszerkesztőnk, ugyanis egy
új mentéspontot fogunk készíteni a `master águnkra`.
A feladott merge üzeneten nem kell módosítanünk, teljesen
jó úgy.
A merge lefut és láthatjuk mi is történt:
```
$ git merge atnevezes
Removing hordo
Merge made by the 'recursive' strategy.
gyumolcskosar => gyumolcskosar.txt | 0
hordo => hordo.txt | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename gyumolcskosar => gyumolcskosar.txt (100%)
rename hordo => hordo.txt (100%)
```
Most egy újabb `git log`-al ezt láthatjuk:
```
* 366140d (HEAD -> master) Merge branch 'atnevezes'
|\
| * 9dcfc79 (atnevezes) Adtam kiterjesztést a hordónak
| * 7de1c94 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
* | 15719cf Tettem a kosaramba szőlőt
|/
* 80560db jegyzeteim ignorálása
* 30bf35d Hoztunk egy hordót
```
Ez a bizonyos `merge commit` egyszerre mutat a két ág
tartalmára.
#### Merge conlict
Mi van akkor ha ketten egyszerre ugyanazt változtatjuk?
Úgy döntöttünk, hogy pálinkát szeretnénk főzni józsival,
szóval a hordóba teszünk ízlés szerint valami
gyümölcsöt.
Gyerünk át a saját águnkra, de egy paranccsal.
Ezt a `-b` kapcsolóval tudjuk
elérni a `git checkout` mellett.
```
$ git checkout -b lacko
```
Most egy újabb `git branch` kiadásával már látható, hogy
3 ággal rendelkezünk.
```
atnevezes
* lacko
master
```
Tegyünk bele a `hordo.txt`-be egy nekünk tetsző gyümölcsöt.
```gyumolcs.txt
korte
```
Ezt mentsük is el, de most picit csaljunk és ne rakjuk
`staged`-be, hanem azonnal mentsük el `-a` kapcsolót használva.
```
$ git commit -a -m "Raktam a hordóba körtét"
```
Úgy döntöttünk a szomszéd Józsi, hogy ugyanebbe a hordóba
körtét szeretne rakni. Menjünk át a master ágra és
tegyük meg ott.
Azt mondta a szomszéd, hogy szilvát szeretne beletenni, szóval:
```hordo.txt
szilva
```
Ezt is mentsük el.
```
$ git commit -a -m "Raktam szilvát a hordóba"
```
Most ha megnézzük a gráfunkat újra, akkor láthatjuk is,
hogy mi a helyzet:
```
$ git log --graph --oneline --all
* 41f1c05 (HEAD -> master) Raktam szilvát a hordóba
| * 6d6d1ac (lacko) Raktam a hordóba körtét
|/
* 366140d Merge branch 'atnevezes'
|\
| * 9dcfc79 (atnevezes) Adtam kiterjesztést a hordónak
| * 7de1c94 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
* | 15719cf Tettem a kosaramba szőlőt
|/
* 80560db jegyzeteim ignorálása
* 30bf35d Hoztunk egy hordót
...
```
Na és akkor most mergeljünk be a master-re a módosításaink.
```
$ git merge lacko
Auto-merging hordo.txt
CONFLICT (content): Merge conflict in hordo.txt
Automatic merge failed; fix conflicts and then commit the result.
```
Oh! Merge conlict keletkezett.
Nem kell megijedni, nem a világ vége és a git segít ahol tud.
Az a helyzet, hogy egyszerre ugyanazt a sort módosítottuk és a git nem tudta
eldönteni mit tegyen. Megtartsa az egyiket vagy mindkettőt? Mégis mi legyen?
Ezeket a kérdéseket nekünk kell megválaszolnunk.
Először nézzük meg, mit a státusz.
```
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: hordo.txt
no changes added to commit (use "git add" and/or "git commit -a")
```
Az van, hogy ilyenkor a git beírja a fájlunkba mind a két branch változásait
és utána azt várja tőlünk, hogy átalakítsuk a fájlt, majd pedig azt elmentsük.
Szóval nem kell megijedni, csak átírjuk mi kell nekünk és mentünk egyet.
Nézzük meg mi van a fájlunkban.
```hordo.txt
<<<<<<< HEAD
szilva
=======
korte
>>>>>> lacko
```
Mit is jelent ez? Ketté szedte az bejövő adatokat a git arra ahová mergeltünk
(`HEAD`) és amit mergeltünk (`lacko`). Köztük pedig egy sor "======="-t láthatunk.
Itt már csak átírjuk a fájlt ahogy szeretnénk, hogy kinézzen.
```hordo.txt
korte
```
Nézzük meg mi a státusz ezután:
```
git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: hordo.txt
no changes added to commit (use "git add" and/or "git commit -a")
```
Továbbra is azt írja, amit az imént. Amíg nem commitoljuk a módosításunk,
addig ezt is fogja. Hát akkor mentsünk.
```
git commit -a -m "lacko branch mergelve és konflikt megoldva"
```
Nézzük meg hogy néz ki a gráfunk ezután.
```
* 7341274 (HEAD -> master) lacko branch mergelve és konflikt megoldva
|\
| * 6d6d1ac (lacko) Raktam a hordóba körtét
* | 41f1c05 Raktam szilvát a hordóba
|/
* 366140d Merge branch 'atnevezes'
...
```
Tehát most a merge commitunk egyben a konfliktusok megoldását is tartalmazza.
Nem elképesztő? Innentől már csak együtt kell dolgozni, margeknél a konfliktusokat
megoldani.
Semmi extra effortot nem fog igényelni egy hasonló elvégzése.
File moved