Potpuno savladajte Git za 1 sat, (verovatno) najjednostavniji i najjasniji Git vodič ikada
I. Poreklo Gita
Git je distribuirani sistem za kontrolu verzija. Njegov tvorac je čuveni Linus Torvalds, a prvobitna svrha Gita bila je bolje upravljanje izvornim kodom Linux kernela.

Svi znaju da je Linux kernel otvorenog koda i da ima ogroman broj učesnika — do sada je više od dvadeset hiljada programera poslalo kod u Linux Kernel.
Međutim, od 1991. do 2002. godine, Linus kao administrator projekta nije koristio nijedan alat za upravljanje konfiguracijom, već je ručno spajao kod koji su drugi slali putem zakrpa (patch).
Nije da je Linus voleo ručni rad, nego je bio izuzetno izbirljiv što se tiče alata za kontrolu verzija — ni komercijalni Clearcase, ni otvoreni CVS i SVN nisu mu bili dovoljno dobri.
Tek 2002. godine Linus je pronašao distribuirani sistem za kontrolu verzija pod imenom BitKeeper. Iako je bio komercijalan, BitKeeper je dozvoljavao Linux zajednici da ga besplatno koristi, što je Linusa veoma obradovalo i zadovoljilo.
Došla je 2005. godina. Pošto podrazumevani interfejs koji je pružao BitKeeper nije ispunjavao sve potrebe korisnika Linux zajednice, jedan programer je bez dozvole dekompajlirao BitKeeper i iskoristio nezvanične interfejse. Zbog toga je vlasnik autorskih prava nad BitKeeperom, Larry McVoy, ljutito povukao dozvolu za besplatno korišćenje od strane Linux zajednice.
Nije preostalo ništa drugo, Linus je morao sam da prione na posao. Postavio je nekoliko ciljeva za novi sistem za kontrolu verzija:
- Brzina
- Jednostavan dizajn
- Podrška za hiljade paralelnih razvojnih grana
- Potpuno distribuiran
- Sposobnost da efikasno upravlja projektima ogromne razmere poput Linux kernela
Rezultat je, neočekivano, bio taj što je Linus za samo 10 dana napisao prvu verziju u jeziku C. Hmm... bog je ipak bog. Verziji je dao blago podrugljivo ime — Git (u britanskom slengu znači "neprijatan čovek").
README datoteka izvornog koda to dalje objašnjava:
The name "git" was given by Linus Torvalds when he wrote the very first version. He described the tool as "the stupid content tracker" and the name as (depending on your way)
Iz Gitovog dizajna proizilaze dve vrste komandi: niske komande (plumbing commands) i visoke komande (porcelain commands). U početku je Linus dizajnirao samo komande koje slede Unix KISS princip, namenjene hakerima otvorenog koda. Pošto su hakeri sami majstori za sve — pukne li vodovod, zarolaju rukave i popravljaju — te komande su nazvane plumbing komandama.
Nakon što je Linus poslao prvi git commit, objavio je git alat zajednici. U to vreme, jedan programer iz zajednice po imenu Junio Hamano pomislio je da je alat zanimljiv, preuzeo je kod, i otkrio da ga čini svega 1244 linije — što ga je još više iznenadilo i probudilo mu veliko zanimanje. Junio je komunicirao sa Linusom preko mejling liste, pomogao u dodavanju funkcija poput merge, i zatim neprekidno doterivao git, da bi na kraju potpuno preuzeo održavanje Gita, dok se Linus vratio održavanju projekta Linux Kernel.
Junio Hamano smatrao je da komande koje je dizajnirao Linus nisu previše naklonjene običnim korisnicima, pa je iznad njih obavio lakše za upotrebu, sa lepšim interfejsom, visoke komande — dakle one koje danas koristimo svakodnevno: git add, git commit i slično. Komanda git add obavija update-cache komandu, dok git commit obavija write-tree i commit-tree komande.
Kada bismo birali najveći git commit u istoriji, to bi svakako bio sam prvi commit projekta Git. Taj commit je bez sumnje bio pionirski — ako je Linux projekat doneo uspeh softveru otvorenog koda i preoblikovao industriju, onda je Git promenio način rada i pisanja programera širom sveta.
Danas je Git postao standard za programere širom sveta.

Prvobitno je Git bio namenjen samo za Unix/Linux platforme, ali sa sazrevanjem Cygwin i msysGit okruženja, kao i lakih GUI alata poput TortoiseGit, Git je postepeno sazreo i na Windows platformi.
PS1: Glavna svrha Cygwin-a je da rekonpajliranjem portuje softver sa POSIX sistema (npr. Linux, BSD i ostalih Unix sistema) na Windows.
PS2: Prva 4 slova u nazivu msysGit potiču iz projekta MSYS, a MSYS vodi poreklo od MinGW (Minimalist GNU for Windows, minimalni GNU alatki). Dodavanjem shell okruženja koje pruža bash, zajedno sa ostalim pratećim alatkama, nastao je minimalni sistem (Minimal System). Korišćenjem MinGW alatki i jedne MinGW grane Gita, moguće je na Windows platformi izkompajlirati nativnu aplikaciju za Git; u kombinaciji sa MSYS-om nastaje msysGit.
Git se znatno razlikuje od tradicionalnih alata za kontrolu verzija poput CVS-a i SVN-a: prvi posmatra da li se cela datoteka promenila, dok druga dva više obraćaju pažnju na razlike u sadržaju datoteke.

Pored toga, Git više liči na datotečni sistem: svaka mašina koja ga koristi može poslužiti kao skladište verzija, i ne zavisi od udaljenog skladišta — može raditi van mreže. Programer lokalno ima kopiju istorije verzija, pa nije sputan mrežnim prenosom ka udaljenom skladištu.
Ogromna većina operacija u Gitu zahteva pristup samo lokalnim datotekama i resursima, i obično ne zahteva podatke sa drugih računara na mreži. Pošto se kompletna istorija projekta nalazi na lokalnom disku, većina Git operacija deluje kao da se izvrše u trenu.
U slučaju rada više ljudi, Git omogućava kopiranje lokalnog skladišta drugim programerima; izmenjene datoteke mogu se uvesti kao nove grane, i zatim spojiti sa granama u lokalnom skladištu.
Ako želiš da ti kasnije učenje teče glatko, zapamti ova tri Git stanja:
- Commitovano (committed) — podaci su bezbedno sačuvani u lokalnoj bazi
- Izmenjeno (modified) — datoteka je izmenjena, ali još uvek nije sačuvana u bazu
- Prikazano (staged) — trenutna verzija izmenjene datoteke je označena tako da bude uključena u snimak stanja sledećeg commita
Otuda proizilaze tri Git radna područja:
- Git skladište — čuva metapodatke projekta i bazu objekata
- Radni direktorijum — nezavisno izdvaja određenu verziju projekta
- Zona prikazivanja (staging) — čuva spisak datoteka koje će biti commitovane sledeće; poznata i kao "indeks"
Git tok rada izgleda ovako:

- Izmeni datoteku u radnom direktorijumu
- Prikaži datoteku — stavi snimak datoteke u zonu prikazivanja
- Commituj ažuriranje — pronalazi datoteke u zoni prikazivanja i trajno smešta snimak u Git skladište
II. Instalacija Gita
Dalje, pogledajmo instalaciju Gita. Za Linux i Windows sisteme možete na službenoj stranici Gita pogledati način instalacije — tamo je sve vrlo detaljno opisano.
https://git-scm.com/downloads

Lično koristim macOS, pa mogu direktno instalirati komandom brew install git, što je veoma pogodno.

Nakon uspešne instalacije, komandom git --version možete proveriti broj verzije — na mojoj mašini je instalirana verzija 2.23.0.
III. Gitov model podataka
Iako je Gitov interfejs donekle težak za razumevanje, njegov dizajn i ideje su izuzetno elegantni. Teško razumljiv interfejs mora se naučiti napamet, ali elegantan dizaj ispod je vrlo lako razumeti. Možemo učiti Git pristupom odozdo-nagore: prvo savladati model podataka, a zatim njegov interfejs. Može se reći da, jednom kada razumete Gitov model podataka, postaje vrlo lako naučiti njegov interfejs i razumeti kako taj interfejs manipuliše modelom podataka.
Postoji mnogo načina za kontrolu verzija, a Git ima pažljivo osmišljen model koji mu omogućava da podrži sve osobine potrebne za kontrolu verzija, poput održavanja istorije, podrške za grane i timsku saradnju.
Snimci stanja (snapshot)
Git najviši nivo datoteka i fascikli u direktorijumu naziva skupom, i upravlja istorijom kroz niz snimaka stanja. U Gitovoj terminologiji, datoteka se naziva blob objektom (data object), odnosno skupom podataka. Direktorijum se naziva tree (stablo), i direktorijum može sadržati datoteke i poddirektorijume.
<root> (tree)
|
+- foo (tree)
| |
| + bar.txt (blob, contents = "hello world")
|
+- baz.txt (blob, contents = "git is wonderful")Stablo na vrhu (dakle root) sadrži dva elementa: podstablo po imenu foo (koje sadrži blob objekat "bar.txt") i blob objekat "baz.txt".
Modelovanje istorije: povezivanje snimaka
Kako sistem za kontrolu verzija povezuje snimke stanja? Linearna istorija je najjednostavniji model — sadrži niz snimaka raspoređenih linearno po vremenu. Međutim, iz različitih razloga, Git ne koristi taj model.
U Gitu je istorija usmeren aciklični graf sastavljen od snimaka stanja. "Usmeren aciklični graf" zvuči visoko, ali nije teško razumeti. Dovoljno je znati da to znači kako svaki snimak u Gitu ima niz predaka, odnosno niz prethodnih snimaka. Ti snimci se obično nazivaju "commit", i izgledaju otprilike ovako:
o <-- o <-- o <-- o
^
\
--- o <-- oOznaka o predstavlja jedan commit, odnosno jedan snimak. Strelica pokazuje na pretka trenutnog commita. Nakon trećeg commita, istorija se račva u dve nezavisne grane — verovatno zato što se istovremeno razvijaju dve različite funkcionalnosti koje su međusobno nezavisne. Po završetku razvoja, te grane se mogu spojiti u novi commit koji istovremeno sadrži obe funkcionalnosti, i to izgleda otprilike ovako:
o <-- o <-- o <-- o <---- o
^ /
\ v
--- o <-- oCommit u Gitu je nepromenljiv. Naravno, to ne znači da ne može biti izmenjen — samo što ta "izmene" zapravo stvaraju potpuno novi zapis commita.
Model podataka i njegova pseudokodska reprezentacija
Učenje Gitovog modela podataka preko pseudokoda može biti razumljivije.
// datoteka je skup podataka
type blob = array<byte>
// direktorijum koji sadrži datoteke i poddirektorijume
type tree = map<string, tree | file>
// svaki commit sadrži pretka, metapodatke i stablo najvišeg nivoa
type commit = struct {
parent: array<commit> // predak
author: string // autor
message: string // poruka
snapshot: tree // snimak stanja
}Objekti i adresiranje u memoriji
Objekat u Gitu može biti blob, tree ili commit:
type object = blob | tree | commitGit prilikom skladištenja podataka adresira sve objekte na osnovu njihovog algoritma bezbednog heširanja.
objects = map<string, object>
def store(object):
id = sha1(object)
objects[id] = object
def load(id):
return objects[id]Blob, tree i commit su svi objekti. Kada referenciraju druge objekte, oni na disku ne čuvaju te objekte u potpunosti, već samo njihove heš vrednosti kao reference.
Sećate li se prethodnog primera?
<root> (tree)
|
+- foo (tree)
| |
| + bar.txt (blob, contents = "hello world")
|
+- baz.txt (blob, contents = "git is wonderful")Reference root-a na foo i baz.txt izgledaju ovako:
100644 blob 4448adbf7ecd394f42ae135bbeed9676e894af85 baz.txt
040000 tree c68d233a33c5c06e0340e4c224f0afca87c8ce87 fooReference
Svi snimci stanja mogu se označiti svojim heš vrednostima, ali je 40 heksadecimalnih znakova suviše teško zapamtiti i veoma nezgodno. Rešenje koje Git nudi je davanje tim heš vrednostima čitljivog imena — to je referenca (reference). Referenca je pokazivač na commit; za razliku od objekta, ona je promenljiva i može se ažurirati da pokazuje na novi commit. Obično referenca master pokazuje na najnoviji commit glavne grane.
references = map<string, string>
def update_reference(name, id):
references[name] = id
def read_reference(name):
return references[name]
def load_reference(name_or_id):
if name_or_id in references:
return load(references[name_or_id])
else:
return load(name_or_id)Tako Git može koristiti lako pamtlivo ime poput "master" da označi određeni commit u istoriji, bez potrebe za dugačkim nizom heksadecimalnih znakova.
U Gitu, trenutna pozicija ima poseban indeks — to je "HEAD".
Skladište (repository)
Možemo grubo definisati Git skladište: objekti i reference.
Na disku Git čuva samo objekte i reference, jer njegov model podatak sadrži samo to. Sve git komande odgovaraju operacijama nad stablom commitova.
IV. Gitova interna implementacija
Najbolji način da se nauči Gitova interna implementacija jeste pregled prvobitnog Linusovog commita. Kada se checkout-uje prvi commit Git projekta, vidi se da skladište koda sadrži samo nekoliko datoteka: jedan README, jedan Makefile build skript i još nekoliko C izvornih datoteka. Napomena tog commita je takođe vrlo posebna:
commit e83c5163316f89bfbde7d9ab23ca2e25604af290
Author: Linus Torvalds <torvalds@ppc970.osdl.org>
Date: Thu Apr 7 15:13:13 2005 -0700
Initial revision of "git", the information manager from hellU README-u Linus detaljno opisuje dizajnerske ideje Gita. Ono što deluje kao složen Git rad, u Linusovom dizajnu sadrži samo dve apstrakcije objekata:
- Baza objekata ("object database");
- Keš trenutnog direktorijuma ("current directory cache").
Suština Gita je skup objekata datoteka: datoteka koda je objekat, stablo direktorijuma datoteka je objekat, i commit je takođe objekat. Imena ovih objekata datoteka su SHA1 vrednosti njihovog sadržaja, a SHA1 heš algoritam daje vrednost od 40 znakova. Linus prvih par znakova koristi kao ime fascikle, a preostalih 38 znakova kao ime datoteke. Možete videti u direktorijumu .git/objects mnogo poddirektorijuma sa dvoslovnim imenima od slova/brojeva, u kojima se čuva mnogo datoteka sa imenima od 38 heš znakova — to je sva Gitova informacija.
Kada je Linus dizajnirao strukturu podataka objekta, definisao je format kao: <oznaka u ascii kodu>(blob/tree/commit) + <razmak> + <dužina u ascii kodu> + <\0> + <sadržaj binarnih podataka>. Možete komandom xxd pregledati objektne datoteke u direktorijumu objects (potrebno je zlib dekompresovanje). Na primer, sadržaj jednog tree objekta izgleda ovako:
00000000: 7472 6565 2033 3700 3130 3036 3434 2068 tree 37.100644 h
00000010: 656c 6c6f 2e74 7874 0027 0c61 1ee7 2c56 ello.txt.'.a..,V
00000020: 7bc1 b2ab ec4c bc34 5bab 9f15 baPostoje tri vrste objekata: BLOB, TREE, CHANGESET.
BLOB: binarni objekat — to je datoteka koju Git čuva. Za razliku od nekih VCS alata (poput SVN-a) koji čuvaju delta informacije o promenama, Git čuva potpune informacije datoteke u svakoj verziji.
Na primer, kada se prvi put commituje hello.c u Git skladište, generiše se BLOB datoteka koja kompletno beleži sadržaj hello.c; nakon izmene hello.c i ponovnog commita, generiše se nova BLOB datoteka koja beleži kompletan sadržaj izmenjenog hello.c.
U Linusovom dizajnu, BLOB beleži samo sadržaj datoteke, bez imena datoteke, atributa i drugih metapodataka — te informacije se čuvaju u drugom objektu, TREE.
TREE: objekat stabla direktorijuma. U Linusovom dizajnu, TREE objekat je apstrakcija informacije stabla direktorijuma u jednom vremenskom isečku. Sadrži ime datoteke, atribute datoteke i SHA1 vrednost BLOB objekta, ali ne i istorijske informacije. Prednost ovakvog dizajna je što omogućava brzo poređenje TREE objekata dva istorijska zapisa, bez čitanja sadržaja — na osnovu SHA1 vrednosti prikazuje se poklapanje i razlika datoteka.
Pored toga, pošto TREE beleži ime i atribute datoteke, u slučajevima izmene atributa datoteke, promene imena datoteke ili pomeranja direktorijuma bez izmene sadržaja datoteke, BLOB objekat se može ponovo iskoristiti, čime se štede resurse za skladištenje. U kasnijem razvoju Git je optimizovao dizajn TREE-a, tako da TREE postaje apstrakcija informacije fascikle u određenom trenutku — TREE sadrži informacije o TREE objektima svojih poddirektorijuma (SHA1). Na taj način, za Git skladišta sa složenom strukturom direktorijuma ili dubokom hijerarhijom štedi se resurse za skladištenje. Istorijske informacije se beleže u trećoj vrsti objekata — CHANGESET.

CHANGESET: commit objekat. CHANGESET objekat beleži informaciju TREE objekta tog commita (SHA1), kao i podatke o podnosiocu (committer), poruku commita (commit message) i slično.
Za razliku od drugih SCM (Software Configuration Management) alata, Gitov CHANGESET objekat ne beleži operacije preimenovanja datoteka i izmene atributa, niti delta informacije o izmenama datoteka; CHANGESET beleži SHA1 vrednost roditeljskog CHANGESET objekta, i razlika se dobija poređenjem TREE informacija trenutnog i roditeljskog čvora.
Prilikom dizajniranja roditeljskih čvorova CHANGESET-a, Linus je dozvolio da jedan čvor ima najviše 16 roditeljskih čvorova. Iako je merge sa više od dva roditelja prilično neobična stvar, Git zapravo podržava više-grana merge sa više od dve grane.
Nakon objašnjenja dizajna tri vrste objekata, Linus posebno ističe poverenje (TRUST). Iako Git po dizajnu ne obuhvata poverenje, Git kao alat za upravljanje konfiguracijom može postići poverenje. Razlog je taj što su svi objekti SHA1 kodirani (Google napad pronalaženja kolizije SHA1 je druga priča, a Git zajednica je već spremna da ga zameni pouzdanijim SHA256 kodiranjem), a procesa potpisivanja objekata je poverljiv uz podršku alatki za potpisivanje, poput GPG alatke.
Kada se razumeju tri osnovna Git objekta, lako je razumeti Linusove dve prvobitne apstrakcije — "bazu objekata" i "keš trenutnog direktorijuma". Dodavanjem prvobitnog radnog direktorijuma, Git ima tri sloja apstrakcije, kao na slici: prvi je trenutna radna zona (Working Directory), gde pregledamo/pišemo kod; drugi je Git skladište (Repository), odnosno Linusova "baza objekata" — sadržaj koji vidimo u .git fascikli Git skladišta (Linus je u prvoj verziji to nazvao .dircache); između ove dve apstrakcije skladištenja nalazi se srednja zona keširanja (Staging Area), odnosno informacije sačuvane u .git/index. Kada izvršimo komandu git add, naše trenutne izmene se dodaju u zonu keširanja.
Linus objašnjava dizajn "keša trenutnog direktorijuma": taj keš je binarna datoteka čija struktura sadržaja podseća na TREE objekat. Za razliku od TREE objekta, index ne sadrži ugnežđene index objekte — sadržaj stabla trenutno izmenjenog direktorijuma nalazi se u jednoj index datoteci. Ovakav dizajn ima dve prednosti:
- Omogućava brzo vraćanje kompletnog sadržaja keša; čak i ako se slučajno obrišu datoteke iz trenutne radne zone, sve datoteke se mogu oporaviti iz keša.
- Omogućava brzo pronalaženje datoteka čiji se sadržaj u kešu razlikuje od sadržaja u trenutnoj radnoj zoni.

Linus je u prvom commitu Gita završio najosnovnije funkcije Gita, koje je već mogao da se kompajlira i koristi. Kod je izuzetno sažet — sa Makefile-om ukupno samo 848 linija. Ako vas zanima, možete prethodno opisanim putem checkout-ovati najraniji Git commit i probati kompajliranje — potreban vam je samo Linux okruženje.
Zbog verzija zavisnih biblioteka, potrebno je napraviti sitne izmene u prvobitnom Makefile skriptu. Prva verzija Gita zavisi od biblioteka openssl i zlib, pa te dve razvojne biblioteke treba ručno instalirati. Na Ubuntu-u izvršite: sudo apt install libssl-dev libz-dev; zatim u Makefile-u u redu LIBS= -lssl promenite -lssl u -lcrypto i dodajte -lz; na kraju izvršite make, zanemarite upozorenja o kompajliranju, i videćete da su generisana 4 izvršna programa: init-db, update-cache, write-tree, commit-tree, cat-file, show-diff i read-tree.
Ukratko o implementaciji ovih izvršnih programa:
- init-db: inicijalizuje lokalno Git skladište — to je komanda git init koju danas koristimo pri svakom inicijalizovanju Git skladišta. Samo što se skladište i fascikla za keš koje je Linus prvobitno napravio zvale .dircache, a ne .git fascikla koju danas poznajemo.
- update-cache: prima putanju datoteke i dodaje tu datoteku (ili više njih) u zonu keširanja. Konkretna implementacija: proverava ispravnost putanje, zatim izračunava SHA1 datoteke, dodaje blob zaglavlje sadržaju datoteke, vrši zlib kompresiju i upisuje u bazu objekata (.dircache/objects); konačno ažurira putanju datoteke, atribute i blob SHA1 vrednost u .dircache/index keš datoteci.
- write-tree: iz informacije stabla direktorijuma u kešu generiše TREE objekat i upisuje ga u bazu objekata. Struktura TREE objekta je: 'tree ' + dužina + \0 + lista stabla datoteka. Lista stabla datoteka čuva se u strukturi: atribut datoteke + ime datoteke + \0 + SHA1 vrednost. Nakon uspešnog upisa, vraća SHA1 vrednost tog TREE objekta.
- commit-tree: iz informacije TREE objekta generiše čvor commit objekta i submituje ga u istoriju verzija. Konkretna implementacija: prima SHA1 vrednost TREE objekta za commit i opciono prima roditeljske commit čvorove (najviše 16). commit objekat sadrži TREE, roditeljske čvorove, podatke o podnosiocu i autoru (ime, imejl, datum), i konačno se upisuje kao novi čvor commit objekta, pri čemu se vraća SHA1 vrednost commit čvora.
- cat-file: pošto su sve objektne datoteke zlib kompresovane, za pregled sadržaja datoteke potrebno je koristiti ovu alatku za dekompresiju i generisanje privremene datoteke, kako bi se pregledao sadržaj objektne datoteke.
- show-diff: brzo poredi razliku između trenutnog keša i trenutne radne zone. Pošto su i atributi datoteke (uključujući vreme izmene, dužinu itd.) sačuvani u strukturi podataka keša, može se brzo utvrditi da li je datoteka izmenjena i prikazati delovi koji se razlikuju.
- read-tree: na osnovu unete SHA1 vrednosti TREE objekta ispisuje sadržaj informacija TREE-a.
To je svih sedam potprograma prve upotrebljive verzije Gita. Neki od vas koji su koristili Git će reći: "Kako to da se ne poklapa sa Git komandama koje ja koristim? Gde su git add, git commit?" Da, u prvobitnom dizajnu Gita nije bilo ovih komanda koje svakodnevno koristimo.
U dizajnu Gita postoje dve vrste komandi: niske komande (plumbing commands) i visoke komande (porcelain commands). U početku je Linus dizajnirao komande koje slede Unix KISS princip, namenjene hakerima otvorenog koda — pošto su hakera sami majstori za sve, pukne li vodovod, zarolaju rukave i popravljaju — te komande su nazvane plumbing komandama.
Junio Hamano, koji je kasnije preuzeo Git, smatrao je da te komande nisu previše naklonjene običnim korisnicima, pa je iznad njih obavio lakše za upotrebu, sa lepšim interfejsom, visoke komande — dakle one koje danas koristimo svakodnevno: git add, git commit i slično. Komanda git add obavija update-cache komandu, dok git commit obavija write-tree i commit-tree komande.
V. 60 često korišćenih Git komandi
Iako svakodnevno unosim poneku Git komandu, i dalje ih mnogo ne zapamtim — jadna moja glava...
Uglavnom, za svakodnevnu upotrebu dovoljno je zapamtiti 6 komandi sa slike ispod, ali za vešto korišćenje Gita verovatno će te morati zapamtiti 60 do 100 komandi.

U uvodnom članku Git serijala podsetio sam vas da obavezno zapamtite sledeće specijalizovane termine — oni mnogo pomažu u savladavanju Gita:
- Workspace: radna zona
- Index / Stage: zona prikazivanja
- Repository: zona skladišta (ili lokalno skladište)
- Remote: udaljeno skladište
Naravno, ako niste zapamtili, nije problem — iskoristite danas priliku da još jednom ponovite.
U nastavku je spisak često korišćenih Git komendi koje je sastavio učitelj Ruan Yifeng. Po potrebi ga odštampajte i držite na radnom stolu.
1. Novo skladište koda
# Napravi novo Git skladište koda u trenutnom direktorijumu
$ git init
# Napravi novi direktorijum i inicijalizuj ga kao Git skladište koda
$ git init [project-name]
# Preuzmi projekat i kompletnu istoriju njegovog koda
$ git clone [url]2. Konfiguracija
Gitova konfiguraciona datoteka je .gitconfig; može se nalaziti u glavnom korisničkom direktorijumu (globalna konfiguracija) ili u direktorijumu projekta (konfiguracija projekta).
# Prikaži trenutnu Git konfiguraciju
$ git config --list
# Uredi Git konfiguracionu datoteku
$ git config -e [--global]
# Podesi korisničke podatke pri commitovanju koda
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"3. Dodavanje/brisanje datoteka
# Dodaj navedenu datoteku u zonu prikazivanja
$ git add [file1] [file2] ...
# Dodaj navedeni direktorijum u zonu prikazivanja, uključujući poddirektorijume
$ git add [dir]
# Dodaj sve datoteke iz trenutnog direktorijuma u zonu prikazivanja
$ git add .
# Traži potvrdu pre svake izmene
# Za više izmena iste datoteke moguće je raditi izdvajanje po delovima
$ git add -p
# Obriši datoteku iz radne zone i stavi to brisanje u zonu prikazivanja
$ git rm [file1] [file2] ...
# Prestani da pratiš navedenu datoteku, ali je zadrži u radnoj zoni
$ git rm --cached [file]
# Preimenuj datoteku i stavi tu promenu imena u zonu prikazivanja
$ git mv [file-original] [file-renamed]4. Commitovanje koda
# Commituj zonu prikazivanja u zonu skladišta
$ git commit -m [message]
# Commituj navedene datoteke iz zone prikazivanja u zonu skladišta
$ git commit [file1] [file2] ... -m [message]
# Commituj izmene u radnoj zoni od poslednjeg commita direktno u zonu skladišta
$ git commit -a
# Pri commitovanju prikaži sve diff informacije
$ git commit -v
# Koristi novi commit da zameni prethodni
# Ako kod nema novih izmena, koristi se za prepisivanje poruke prethodnog commita
$ git commit --amend -m [message]
# Ponovi prethodni commit i uključi nove izmene navedenih datoteka
$ git commit --amend [file1] [file2] ...5. Grane
# Izlistaj sve lokalne grane
$ git branch
# Izlistaj sve udaljene grane
$ git branch -r
# Izlistaj sve lokalne i udaljene grane
$ git branch -a
# Napravi novu granu, ali ostani na trenutnoj grani
$ git branch [branch-name]
# Napravi novu granu i prebaci se na nju
$ git checkout -b [branch]
# Napravi novu granu koja pokazuje na navedeni commit
$ git branch [branch] [commit]
# Napravi novu granu koja uspostavlja odnos praćenja sa navedenom udaljenom granom
$ git branch --track [branch] [remote-branch]
# Prebaci se na navedenu granu i ažuriraj radnu zonu
$ git checkout [branch-name]
# Prebaci se na prethodnu granu
$ git checkout -
# Uspostavi odnos praćenja između postojeće i navedene udaljene grane
$ git branch --set-upstream [branch] [remote-branch]
# Spoji navedenu granu u trenutnu granu
$ git merge [branch]
# Izaberi jedan commit i spoji ga u trenutnu granu
$ git cherry-pick [commit]
# Obriši granu
$ git branch -d [branch-name]
# Obriši udaljenu granu
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]6. Tagovi
# Izlistaj sve tagove
$ git tag
# Napravi novi tag na trenutnom commitu
$ git tag [tag]
# Napravi novi tag na navedenom commitu
$ git tag [tag] [commit]
# Obriši lokalni tag
$ git tag -d [tag]
# Obriši udaljeni tag
$ git push origin :refs/tags/[tagName]
# Prikaži informacije o tagu
$ git show [tag]
# Pošalji navedeni tag
$ git push [remote] [tag]
# Pošalji sve tagove
$ git push [remote] --tags
# Napravi novu granu koja pokazuje na određeni tag
$ git checkout -b [branch] [tag]7. Pregled informacija
# Prikaži datoteke koje su izmenjene
$ git status
# Prikaži istoriju verzija trenutne grane
$ git log
# Prikaži istoriju commitova i datoteke izmenjene u svakom commitu
$ git log --stat
# Pretraži istoriju commitova prema ključnoj reči
$ git log -S [keyword]
# Prikaži sve promene nakon određenog commita, po jedan commit po redu
$ git log [tag] HEAD --pretty=format:%s
# Prikaži sve promene nakon određenog commita čija "poruka commita" mora ispunjavati uslov pretrage
$ git log [tag] HEAD --grep feature
# Prikaži istoriju verzija navedene datoteke, uključujući preimenovanja datoteke
$ git log --follow [file]
$ git whatchanged [file]
# Prikaži svaki diff povezan sa navedenom datotekom
$ git log -p [file]
# Prikaži poslednjih 5 commita
$ git log -5 --pretty --oneline
# Prikaži sve korisnike koji su slali commitove, sortirano po broju commitova
$ git shortlog -sn
# Prikaži ko je i kada izmenio navedenu datoteku
$ git blame [file]
# Prikaži razliku između zone prikazivanja i radne zone
$ git diff
# Prikaži razliku između zone prikazivanja i prethodnog commita
$ git diff --cached [file]
# Prikaži razliku između radne zone i najnovijeg commita trenutne grane
$ git diff HEAD
# Prikaži razliku između dva commita
$ git diff [first-branch]...[second-branch]
# Prikaži koliko ste linija koda danas napisali
$ git diff --shortstat "@{0 day ago}"
# Prikaži metapodatke i promene sadržaja određenog commita
$ git show [commit]
# Prikaži datoteke koje su izmenjene u određenom commitu
$ git show --name-only [commit]
# Prikaži sadržaj određene datoteke u vreme određenog commita
$ git show [commit]:[filename]
# Prikaži nekoliko najnovijih commita trenutne grane
$ git reflog8. Udaljena sinhronizacija
# Preuzmi sve promene iz udaljenog skladišta
$ git fetch [remote]
# Prikaži sva udaljena skladišta
$ git remote -v
# Prikaži informacije o određenom udaljenom skladištu
$ git remote show [remote]
# Dodaj novo udaljeno skladište i imenuj ga
$ git remote add [shortname] [url]
# Preuzmi promene iz udaljenog skladišta i spoji ih sa lokalnom granom
$ git pull [remote] [branch]
# Pošalji navedenu lokalnu granu u udaljeno skladište
$ git push [remote] [branch]
# Forsirano pošalji trenutnu granu u udaljeno skladište, čak i ako postoje konflikti
$ git push [remote] --force
# Pošalji sve grane u udaljeno skladište
$ git push [remote] --all9. Poništavanje
# Vrati navedenu datoteku iz zone prikazivanja u radnu zonu
$ git checkout [file]
# Vrati navedenu datoteku određenog commita u zonu prikazivanja i radnu zonu
$ git checkout [commit] [file]
# Vrati sve datoteke iz zone prikazivanja u radnu zonu
$ git checkout .
# Resetuj navedenu datoteku u zoni prikazivanja da se poklapa sa poslednjim commitom, ali ne menjaj radnu zonu
$ git reset [file]
# Resetuj zonu prikazivanja i radnu zonu da se poklapaju sa poslednjim commitom
$ git reset --hard
# Resetuj pokazivač trenutne grane na navedeni commit, uz reset zone prikazivanja, ali bez izmene radne zone
$ git reset [commit]
# Resetuj HEAD trenutne grane na navedeni commit, uz reset zone prikazivanja i radne zone da se poklapaju sa navedenim commitom
$ git reset --hard [commit]
# Resetuj trenutni HEAD na navedeni commit, ali zadrži zonu prikazivanja i radnu zonu nepromenjenim
$ git reset --keep [commit]
# Napravi novi commit kojim se poništava navedeni commit
# Sve izmene ovog drugog biće poništene prvom, i primenjeno na trenutnu granu
$ git revert [commit]
# Privremeno ukloni nekomitovane izmene, a kasnije ih vrati
$ git stash
$ git stash pop10. Ostalo
# Generiši arhivu pogodnu za objavljivanje
$ git archiveVI. Ilustrovano: Git grane
U poređenju sa sličnim alatima, Git ima mnogo prednosti. Jedna od najupadljivijih je što su operacije grananja (branch) i spajanja (merge) izuzetno zgodne.
Neki tradicionalni alati za upravljanje verzijama pri grananju zapravo stvaraju fizičku kopiju postojećeg koda, dok Git generiše samo pokazivač na trenutnu verziju (tzv. "snapshot"), pa je izuzetno brz i lak za upotrebu.
Međutim, prevelika pogodnost ima i nuspojave. Bez pažnje, lako možete ostaviti skladište verzija obraslo granama sa svih strana, bez jasne linije razvoja glavne grane.

Postoji li dobra strategija grananja? Naravno da postoji.
1. Glavna grana Master
Pre svega, skladište koda treba da ima jednu, i samo jednu, glavnu granu. Sve zvanične verzije koje se pružaju korisnicima objavljuju se na toj glavnoj grani.

Ime Git glavne grane podrazumevano je Master. Ona se kreira automatski — nakon inicijalizacije skladišta verzija, podrazumevano se razvija na glavnoj grani.
2. Razvojna grana Develop
Glavna grana služi samo za objavljivanje značajnih verzija; svakodnevni razvoj treba da se obavlja na drugoj grani. Tu granu za razvoj nazivamo Develop.

Ova grana se može koristiti za generisanje najnovije noćne verzije (nightly) koda. Ako želite zvaničnu objavu, na grani Master izvršite "merge" (spajanje) grane Develop.
Komanda za kreiranje Develop grane u Gitu:
git checkout -b develop masterKomanda za objavljivanje Develop grane na Master granu:
# Prebaci se na Master granu
git checkout master
# Izvrši merge Develop grane
git merge --no-ff developOvde ukratko objasnimo šta znači parametar --no-ff u prethodnoj komandi. Podrazumevano Git izvršava "brzo spajanje" (fast-forward merge), koje direktno postavlja pokazivač Master grane na Develop granu.

Kada se koristi parametar --no-ff, izvršava se normalan merge i na Master grani generiše se novi čvor. Radi jasnoće evolucije verzija, želimo da koristimo baš taj pristup.

3. Privremene grane
Prethodno su pomenute dve glavne grane skladišta verzija: Master i Develop. Prva služi za zvanično objavljivanje, a druga za svakodnevni razvoj. Zapravo, stalne grane treba da su samo te dve — drugi nisu potrebne.
Međutim, pored stalnih grana, postoje i privremene grane za razvoj verzija sa određenom svrhom. Postoje tri glavne vrste privremenih grana:
- Funkcionalna (feature) grana
- Grana pred-izdanja (release)
- Grana za ispravku grešaka (fixbug)
Sve tri vrste grana su privremene potrebe — nakon upotrebe treba ih obrisati, tako da stalne grane skladišta koda uvek ostaju samo Master i Develop.
Dalje, redom pogledajmo ove tri "privremene grane".
Prva je funkcionalna grana — ona se, radi razvoja određene funkcionalnosti, odvaja od grane Develop. Nakon završetka razvoja, ponovo se spaja u Develop.

Ime funkcionalne grane može se zadati u obliku feature-*.
Kreiranje funkcionalne grane:
git checkout -b feature-x developNakon završetka razvoja, spojite funkcionalnu granu u develop granu:
git checkout develop
git merge --no-ff feature-xBrisanje feature grane:
git branch -d feature-xDruga je grana pred-izdanja — ona služi za testiranje verzije pre zvaničnog objavljivanja (odnosno pre spajanja u Master granu).
Grana pred-izdanja se odvaja od grane Develop, a nakon završetka pred-izdanja mora se spojiti u Develop i Master granu. Njeno ime može biti u obliku release-*.
Kreiranje grane pred-izdanja:
git checkout -b release-1.2 developNakon potvrde da nema problema, spojite je u master granu:
git checkout master
git merge --no-ff release-1.2
# Na novi čvor nastao spajanjem, postavite tag
git tag -a 1.2Zatim je spojite u develop granu:
git checkout develop
git merge --no-ff release-1.2Konačno, obrišite granu pred-izdanja:
git branch -d release-1.2Treća je grana za ispravku grešaka. Nakon zvaničnog objavljivanja softvera, greške su neizbežne. Tada je potrebno kreirati granu za ispravku grešaka.
Grana za ispravku grešaka se odvaja od Master grane. Nakon ispravke, ponovo se spaja u Master i Develop granu. Njeno ime može biti u obliku fixbug-*.

Kreiranje grane za ispravku grešaka:
git checkout -b fixbug-0.1 masterNakon ispravke, spojite je u master granu:
git checkout master
git merge --no-ff fixbug-0.1
git tag -a 0.1.1Zatim je spojite u develop granu:
git checkout develop
git merge --no-ff fixbug-0.1Konačno, obrišite "granu za ispravku grešaka":
git branch -d fixbug-0.1VII. Git u praksi
Za početnike, Git operacije zaista lako mogu uneti izvesnu zbrku u skladište verzija koda — na kraju krajeva, tokom fakulteta fokus učenja je na programskim jezicima i osnovama računarstva. Ali čim počnete da radite, morate ozbiljno da poradite na skladištu verzija koda, jer je u pitanju rad više ljudi... pa, višeljudska saradnja.
1. Kreiranje skladišta
Skladište, odnosno repository, može se jednostavno shvatiti kao direktorijum u kom će Git upravljati svim datotekama — svaki pokret svake datoteke Git će zabeležiti, kako bi u svakom trenutku mogao da se prati i povrati.
Napravite novu fasciklu, recimo testgit, a zatim komandom git init možete inicijalizovati tu fasciklu kao Git skladište.

Nakon uspešne inicijalizacije Git skladišta, videćete da se pojavio novi .git direktorijum — nemojte ga bespotrebno dirati, da ne biste oštetili strukturu Git skladišta.
Zatim ćemo dodati novu datoteku readme.txt sa sadržajem "Prijatelju, seti se da Ergeu daš tri puta lajk", i poslaćemo je u Git skladište.
Prvi korak: komandom git add dodajemo novu datoteku u zonu prikazivanja.
Drugi korak: komandom git commit govorimo Gitu da pošalje datoteku u skladište.

Komandom git status možete proveriti da li još uvek ima neposlatih datoteka.
Možete i dodati novu liniju sadržaja "Tradicionalne vrline ne smeju nestati, seti se da lajkuješ~" u datoteku, a zatim komandom git status pogledati rezultat.

Ako želite da vidite gde je tačno izmenjena datoteka, možete koristiti komandu git diff:

Nakon potvrde sadržaja izmena, možete ponovo izvršiti git add i git commit.
2. Vraćanje verzije
Ponovo izmenite datoteku, dodajte liniju sadržaja: "xxx, volim te❤", i pošaljite je u Git skladište.
Do sada sam tri puta izmenio datoteku readme.txt. Komandom git log možete pregledati istoriju:

Možete i komandom gitk pokrenuti grafički interfejs za pregled istorije verzija.

Ako želite da se vratite, recimo na prethodnu verziju, možete izvršiti jednu od sledeće dve komande:
git reset --hard HEAD^— za verziju pre prethodne to jegit reset --hard HEAD^^, i tako redom.git reset --hard HEAD~100— ako se vraćate 100 verzija unazad, ova komanda je zgodnija od prethodne.

Ako ste greškom vratili pogrešnu verziju i želite da povratite, a ne sećate se broja verzije, prvo izvršite komandu git reflog da biste videli broj verzije:

Zatim komandom git reset --hard povratite:

3. Razlika između radne zone i zone prikazivanja
Pojmove radne zone i zone prikazivanja već smo istakli u prethodnim poglavljima, ali s obzirom na to da neki prijatelji i dalje imaju nedoumice između komandi git add i git commit, ovde ćemo još jednom istaći — tako je sa učenjem: samo neprekidnim ponavljanjem možemo zaista razumeti i savladati gradivo.
Radna zona — na primer, prethodno pomenuti direktorijum testgit pripada radnoj zoni; datoteka readme.txt kojom upravljamo nalazi se u njoj.
Zona prikazivanja — skriveni direktorijum .git ne pripada radnoj zoni; u njemu (Git skladištu) čuva se mnogo toga, a najvažnije je zona prikazivanja.
Git u slanju datoteka postupa u dva koraka: prvi korak git add dodaje datoteku u zonu prikazivanja, a drugi korak git commit šalje sav sadržaj iz zone prikazivanja u Git skladište.
"Zašto je prvo potrebno add, pa tek onda commit?"
Neposredan razlog je što je Linus uveo pojam "zone prikazivanja". A zašto je uopšte uveo taj pojam? Ne može bez zone prikazivanja?
Da bismo odgovorili na to pitanje, moramo krenuti od korena.
Pre Gita, SVN je bio vrhunski sistem za upravljanje verzijama koda. SVN je u odnosu na svog prethodnika CVS bio bolji po tome što svaki commit može sadržati više datoteka, i taj commit je atomičan — ili uspeše sve ili ne uspe ništa.
Prednost atomičnosti je očigledna: omogućava nam da projekat u celosti vratimo na određeni trenutak, i po toj tački SVN potpuno nadmašuje sisteme poput CVS-a.

Git, kao sistem za upravljanje verzijama koda sa najvećim ugledom, naravno je morao da preuzme tu odličnu osobinu od SVN-a. Ali za razliku od SVN-a, Git je od početka radio isključivo komandnom linijom, bez grafičkog interfejsa. Pošto se setite da želite kao u SVN-u da odjednom izaberete više datoteka ili da ne izaberete određene datoteke (vidi sliku iznad), to je zaista bila gnjavaža.
Za genijalca poput Linusa, grafički interfejs je svakako "low", ali komandna linija je u ovoj situaciji zaista nezgodna...
Pa, šta sad?
Božanstvo je božanstvo zato što, kada naiđe na problem, smisli savršeno rešenje — zar ne rešava sve uvođenjem zone prikazivanja?
Zona prikazivanja omogućava slobodno ubacivanje izmena raznih datoteka; dovoljna je prosta komanda poput git add da pažljivo izaberete koje datoteke šaljete, a zatim ih jednokratno (atomski) git commit-ujete u skladište verzija — i svaki problem je rešen.
U direktorijumu testgit dodajmo novu datoteku readyou.txt sa sadržajem "Erge, hoću da izađemo na ručak~~~"; a u datoteci readme.txt dodajmo još jednu liniju sadržaja "Lajk, pregled, komentar, prosledi — sve u jednom~".
Prvo komandom git status pogledajmo stanje, zatim komandom git add dodajmo datoteke u zonu prikazivanja, i konačno komandom git commit jednokratno pošaljimo u Git skladište.

4. Poništavanje izmena
Sada sam u datoteci readyou.txt dodao liniju sadržaja: "Erge, hoću da se nađemo~~~". U trenutku kada sam želeo da pošaljem, iznenada primetih da dodati sadržaj nije ispravan, pa moram da se vratim na raniju verziju — šta da radim?
Ako znam šta želim da izmenim, izmenim direktno, pa onda add i commit da prekrijem.
Ako sam zaboravio šta treba da izmenim, komandom
git reset --hard HEADvraćam se na prethodnu verziju.
Ima li još nekog načina?
Naravno da ima. Zapravo, kada komandom git status pregledamo Git stanje, rezultat nam već sugeriše da možemo koristiti komandu git restore da poništimo ovu operaciju.

A zapravo, pre verzije git 2.23.0, poništavanje se moglo obaviti komandom git checkout.

Komanda checkout može da kreira granu, izveze granu, prebaci granu, obriše datoteku iz zone prikazivanja itd. — previše funkcija u jednoj komandi stvara zabunu. Verzija 2.23.0 je promenila tu zbrku, pa su nastale dve nove komande: git switch i git restore.
Komanda switch je posvećena prebacivanju grana, a restore poništavanju izmena.

5. Udaljeno skladište
Git je distribuirani sistem za kontrolu verzija, pa se isto Git skladište može rasporediti na različite mašine. U početku postoji samo jedna mašina sa jednim originalnim skladištem verzija; kasnije druge mašine mogu od te mašine kopirati originalnu verziju — baš kao Agent Smith u Matrici, bez ikakve razlike.
To je jedna od osobina po kojoj je Git poseban u odnosu na centralizovane sisteme za kontrolu verzija poput SVN-a.
Možemo sami da podignemo jedan Git server koji radi 24 časa dnevno, a zatim ostali samo kopiraju sa tog "servera". Međutim, zahvaljujući postojanju GitHub-a, taj korak podizanja sopstvenog Git servera se može preskočiti.
Već po imenu se vidi da GitHub pruža uslugu hostovanja Git skladišta — dovoljno je da otvorimo jedan GitHub nalog, i besplatno dobijemo jedan Git udaljeni server koji radi 24 časa dnevno.
Na GitHub-u zapravo postoji odgovarajuća dokumentacija na srpskom jeziku koja objašnjava kako preko SSH protokola povezati lokalnu mašinu sa GitHub-om, tako da ne morate pri svakom pristupu da unosite korisničko ime i lozinku.
https://docs.github.com/cn/authentication/connecting-to-github-with-ssh/about-ssh
Prvi korak: komandom ls -al ~/.ssh proverite da li SSH ključ postoji

Ako ne postoje datoteke id_rsa.pub, id_ecdsa.pub, id_ed25519.pub, to znači da ključ ne postoji.
Drugi korak: generišite novi SSH ključ
Izvršite sledeću komandu, obratite pažnju da unosite svoj imejl:
ssh-keygen -t ed25519 -C "your_email@example.com"Zatim pritiskajte Enter do kraja:

Ne zaboravite da kopirate ključ iz datoteke id_ed25519.pub:

Treći korak: dodajte SSH ključ u GitHub nalog
U meniju settings ličnog naloga pronađite SSH and GPG keys, dodajte kopirani ključ u polje key i kliknite na "add SSH key" da ga pošaljete.

Title ne morate popuniti; nakon uspešnog slaja biće izlistani odgovarajući ključevi:

Zašto GitHub zahteva SSH ključ?
Zato što GitHub mora da potvrdi da ste "vi lično" taj koji šalje verzije u svoje udaljeno skladište, a ne neko ko se predstavlja kao vi.
Četvrti korak: kreirajte lično skladište na GitHub-u
Kliknite na kreiranje novog skladišta, popunite ime skladišta i ostale informacije:

Peti korak: sinhronizujte lokalno skladište sa GitHub-om
Kopirajte adresu udaljenog skladišta:

U lokalnom skladištu izvršite komandu git remote add kojom ćete GitHub skladište dodati lokalno:

Kada prvi put komandom git push povežemo se sa GitHub-om, dobićemo upozorenje ⚠️:
The authenticity of host 'github.com (20.205.243.166)' can't be established.
ECDSA key fingerprint is SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yesTo je zato što je potrebna ručna potvrda — unesite yes.
Zatim, komandom git push šaljemo trenutnu lokalnu granu na GitHub. Uz parametar -u, Git ne samo što će lokalnu master granu poslati na udaljenu master granu, već će i povezati lokalnu master granu sa udaljenom master granom, što u kasnijim slanjima ili preuzimanjima omogućava pojednostavljene komande (npr. git push github master).

Sada, kada osvežimo GitHub, vidimo da se pojavila master grana, i obe lokalne datoteke su uspešno poslate!

Od sada, čim lokalno napravite izmenu, možete komandom git push poslati je u GitHub udaljeno skladište.
Takođe možete komandom git clone kopirati udaljeno skladište na lokalnu mašinu. Na primer, sada imam skladište JavaBooks sa 3.4k zvezdica,

Zatim komandom git clone kopiram ga lokalno.

VIII. Detaljno o komandi sparse-checkout
Prekjuče sam postavio sajt "Ergeov put u naprednom Javi", a pri tome sam koristio Git kao alatku za sinhronizaciju između cloud servera i GitHub udaljenog skladišta.

Predstaviću vam jednu moćnu komandu — git sparse-checkout, koja je mom cloud serveru saštedela barem polovinu prostora za skladištenje.
1. Jedan veliki problem pri korišćenju Gita
Pre svega, da vas obavestim: sajt "Ergeov put u naprednom Javi", pokrenut pre jednog dana, već je prešao 1000 poseta.

Kao što se kaže: korak po korak se stiže na hiljadu milja, i potok po potok nastaje reka.
Možda 1000 poseta nije mnogo, ali i 10 miliona je samo 10 hiljada puta po hiljadu. Za svaki mali napredak koji Erge ostvari, zahvalan sam svima vama na podršci.
Prijatelji koji su pročitali prethodni članak o procesu postavljanja već znaju da sam na cloud serveru klonirao GitHub udaljeno skladište, a zatim putem zakazanog zadatka panela Baota izvršavao komandu git pull kojom sam sa GitHub-a preuzimao najnoviji sadržaj. Zatim sam preko Nginx servera postavio sajt, čiji se sadržaj prikazuje renderovanjem md datoteka pomoću docsify.
Direktno git pull bezumno sinhronizuje codes i images direktorijume sa GitHub-a na cloud server, mada ti codes i images direktorijumi zapravo i ne moraju da se sinhronizuju.
U čemu je stvar?
Možete prvo pogledati strukturu direktorijuma mog GitHub skladišta.

- docs je direktorijum dokumentacije; u njemu se nalaze md datoteke, svi originalni nacrti tutorijala.
- codes je direktorijum koda; u njemu se nalazi prateći izvorni kod tutorijala.
- images je direktorijum slika; u njemu se nalaze prateće ručno nacrtane slike tutorijala.
Tako se GitHub može iskoristiti kao besplatno skladište slika, a uz to se besplatno koristi i globalno ubrzanje jsDelivr CDN-a — zaista odlično!

Na primer, u direktorijumu images nalazi se jedna logo slika logo-01.png:

Ako se pristupa preko originalne putanje GitHub skladišta, brzina je užasno spora!
https://github.com/itwanger/toBeBetterJavaer/tree/master/images/logo-01.png
Uz jsDelivr ubrzanje drugačije je — brzina leti!
https://cdn.paicoding.com/tobebetterjavaer/images/logo-01.png
Ukratko, pravilan način korišćenja GitHub-a kao skladišta slika svodi se na dve stavke:
- Kreirajte GitHub skladište kao skladište slika i u njega pošaljite slike
- Tamo gde želite da koristite slike iz GitHub skladišta, zamenite link sa
https://cdn.jsdelivr.net/gh/{user}/{repo}/putanja-do-slike
Prijatelji koji plaćaju Qiniu ili Alibaba Cloud skladište slika mogu probati ovaj pristup — besplatno je, a zašto trošiti novac bez potrebe.
Dakle, slike na sajtu "Ergeov put u naprednom Javi" učitavaju se preko GitHub skladišta slika, pa nije potrebno preuzimati slike iz GitHub skladišta na cloud server. Prostor na cloud serveru je izuzetno skup, pa svaku uštedu moramo iskoristiti.
2. Jedno veliko otkriće pri učenju Gita
Zato sam jutros razmišljao kako da saštedim taj skupi prostor.
Pretraživao sam mnogo postova, ali su većina bile haotične i bez vrednosti — jedva da je neka pogodila suštinu.
Na kraju sam u službenom Git priručniku (možete pogledati i Pro Git) pronašao jednu moćnu komandu: git sparse-checkout, koja nam omogućava da prilikom preuzimanja udaljenog skladišta sinhronizujemo samo one direktorijume i datoteke koje želimo.
Kako se koristi, možete pogledati u službenoj dokumentaciji:
Ali nije neophodno, hhhh, idemo direktno u praksu.
Prvi korak: komandom git remote add -f orgin git@github.com:itwanger/toBeBetterJavaer.git preuzmite skladište sa GitHub-a.

Drugi korak: omogućite sparse-checkout i inicijalizujte ga
Nakon preuzimanja skladišta, izvršite komandu git config core.sparseCheckout true da omogućite sparse-checkout.
Zatim izvršite git sparse-checkout init da biste ga inicijalizovali.

Treći korak: koristite sparse-checkout da preuzmete željene direktorijume skladišta

Na primer, ako želimo da preuzmemo samo docs direktorijum, možemo izvršiti komandu git sparse-checkout set docs.

Ako prvi put koristite sparse-checkout, potrebno je još izvršiti komandu git pull orgin master da jednom preuzmete sadržaj.
Četvrti korak: proverite da li je primenjeno
Možete izvršiti komandu ls -al da potvrdite da li je sparse-checkout primenjen.

Kao što se vidi na slici, zaista je preuzet samo docs direktorijum.
Ako želite da preuzmete i neke druge datoteke ili direktorijume, možete ih dodati komandom git sparse-checkout add.

Tako se ostvaruje prilagođena sinhronizacija između udaljenog skladišta i skladišta na cloud serveru — sinhronizuju se samo oni direktorijumi i datoteke koji su potrebni, a sve nepotrebno se može odbaciti.
GitHub skladište se može koristiti besplatno i prostor je neograničen, ali cloud server mora da se štedi — proširenje prostora za skladištenje je zaista skupo!
Uporedio sam: udaljeno skladište je oko 145 M, od čega slike zauzimaju 72 M — dakle saštedela se tačno polovina prostora za skladištenje.

Kako onemogućiti git sparse-checkout?
Jednostavno — izvršite komandu git sparse-checkout disable.

Vidite da su se svi oni direktorijumi i datoteke koje nismo želeli ponovo pojavili.
Ako ga ponovo želite omogućiti?
Takođe jednostavno — izvršite komandu git sparse-checkout reapply.

Ukratko: ako želite da na lokalnu mašinu preuzmete udaljeno skladište toliko veliko da bi vam popunilo disk, a potrebni su vam samo neki od direktorijuma i datoteka, probajte git sparse-checkout.
3. Nekoliko iskrenih reči nakon korišćenja Gita
Mora se priznati — Git je zaista moćan. Samo jedna komanda rešila je problem koji me mučio čitav dan; moj cloud server sa 80G prostora može ponovo da radi još 3 godine, i od sada više nemam briga.

Git je zaista moćan, Linus je zaista moćan — bog je ipak bog!
Preporučeno čitanje:
Reference:
- Wikipedia: https://zh.wikipedia.org/wiki/Git
- hutusi: Commit koji je promenio svet
