|
|
Bine aţi venit la sistemul de versionare Git! Aici vom învăţa să folosim Git bazîndu-ne pe cunoştinţele sistemului Subversion. Veţi avea nevoie de ultima versiune Git instalată; De asemenea e posibil să aveţi nevoie de tutorialul din documentaţia Git.
|
Dacă doriţi doar să urmăriţi un proiect, aceasta te v-a ajuta să începi repede:
|
În tabelele mici care apar pe parcursul documentului în partea stînga sunt listate comenzile Git, iar în dreapta sunt comenzile corespunzătoare Subversion. Dacă vă grăbiţi, o trecere rapidă cu vederea peste ele ar trebui să vă dea o idee despre folosirea de bază a Git.
Înainte de a rula vre-o comandă pentru prima dată, se recomandă consultarea
fugitivă macar a manualului pentru comanda respectivă. Multe comenzi au
opţiuni interesante şi folositoare (pe care nu le vom detalia aici) şi uneori
sînt note adăugătoare care s-ar putea să vă fie de folos. Pentru fiecare comandă se
pot vedea instrucţiuni rapide folosind parametrul -h.
Sunt cîteva conceptii importante pe care e bine să le cunoaşte-ţi cînd începeţi să lucraţi cu Git. Dacă totuşi sunteţi în grabă, puteţi sări peste secţiunea aceasta şi să vă întoarceţi la ea cînd vă simţiţi derutat; s-ar putea să prindeţi firul folosind numai intuiţia.
.git în directorul proiectului.
Deci puteţi avea ramuri locale şi externe (remote). De asemenea puteţi avea un aşa numit repositoriu singuratic care nu este
ataşat de o copie de lucru; care este de folos în special la publicarea repozitoriului.
Vom ajunge la asta mai tîrziu.
trunk/,
ramuri/ şi tags/. În Git
URL-ul este doar locaţia repozitoriului, şi mereu conţine
ramuri şi tag-uri. Una din ramuri este implicită (deobicei numită
master).
HEAD,
este părinte al HEAD^ şi este părinte al HEAD^^ = HEAD~2
(puteţi continua adăugînd ^),
taie şi lipeşte (cut'n'paste) ajută mult şi puteţi scrie doar cîteva cifre de la început
pentru că sunt unice, Git v-a ghici restul.
(Chiar puteţi şi lucruri mai avansate cu caracteristicile specificatorii de revizie, vedeţi
manualul pentru git-rev-parse pentru mai multe detalii.)
git config -lşi să le setaţi cu:
git config --global user.name "Ion Roată" git config --global user.email ion@roata.md
git command.
Puteţi folosi şi forma git-command pînă la versiunea 1.6.
git config --global color.diff auto git config --global color.status auto git config --global color.branch auto
gitk, qgit.
Pentru început, să facem un repozitoriu Git pentru un proiect şi să vedem cum facem operaţiunile de zi cu zi. Trecem în directorul care conţine proiectul şi iniţializăm repozitoriul Git:
| git init git add . git commit |
svnadmin create repo svn import file://repo |
git init v-a iniţializa repozitoriul,
git add . v-a adăuga fişiere din directorul curent în repozitoriu
şi git commit v-a crea importul iniţial.
Acum directorul este versionat de Git. Puteţi lista
subdirectorul .git dacă doriţi.
Faceţi cîteva schimbări aleatoare în proiect acum. Să verificăm ce am făcut:
| git diff | svn diff | less |
Este una din cele mai puternice comenzi. Pentru a obţine un diff cu o versiune şi o cale:
| git diff rev cale | svn diff -rrev cale |
Git include informaţii în diff-uri despre adăugări, ştergeri şi schimbarea permisiunilor a fişierelor:
| git apply | patch -p0 |
Aceasta v-a aplica patch-ul.
Există un mod de reprezentare mai concisă a schimbărilor:
| git status | svn status |
Asta v-a arăta sumarul concis al schimbărilor inclusiv lista fişierelor depsre care Git încă nu ştie nimic. În plus, de asemnea va arăta ramificarea curentă.
Cu timpul în directorul proiectului vor mai apărea fişiere neversionate.
Dacă o să doriţi să le ştergeţi, puteţi folosi comanda git clean, sau, dacă doriţi să le lăsaţi acolo, dar Git să le ignore adăugaţile în fișierul .gitignore
(funcţionează la fel ca şi svn:ignoreîn SVN).
Pentru a restaura un file din ultima versiune comisă:
| git checkout cale | svn revert cale |
Puteţi restaura tot sau doar un anumit fişier.
Deci, ca şi în SVN, trebuie să spuneţi lui Git cînd adăugaţi, mutaţi sau ştergeţi fişiere:
| git add fișier
git rm fișier git mv fișier |
svn add fișier svn rm fișier svn mv fișier |
De asemenea puteţi adăuga/şterge recursiv directoare, etc.; Git este tare!
Deci, e timpul să comitem modificările noastre. O mare surpriză cu comanda:
| git commit -a | svn commit |
pentru a comite toate schimbările sau, ca şi în Subversion,
puteţi comite doar unele fişiere.
Cîteva cuvinte la mesajul de comitere: este obişnuit
de a avea un sumar scurt al schimbărilor ca prima linie a mesajului,
deoarece diferite unelte care listează commit-urile deseori arată numai
prima linie a mesajului. Puteţi specifica mesajul pentru commit
folosind parametrul -m, Dvs puteţi pune cîteva argumente -m şi ele vor crea
paragrafe separate în mesajul commit-ului:
Dacă nu puneţi nici un parametru -m sau
-e, la executarea comenzii git commit
se va porni editorul dumneavoastră din variabila de mediu $EDITOR
şi veţi putea scrie mesajul acolo, ca şi la Subversion. În afară de asta, se afişează lista fişierilor pentru care urmează a fi comise.
Şi ca bonus, dacă puneţi parametrul -v
va fi afişat întregul patch care se încarcă ca să puteţi revizui rapid.
Apropo, dacă aţi stricat ceva, cu Subversion nu prea aveţi ce face, decît să folosiţi nişte subcomenzi svnadmin enigmatice.
Git face mult mai bine - puteţi corecta ultima comitere
(reeditaţi descrierea şi chiar fişierele din director) folosind
git commit --amend, sau luaţi ultima
încărcare folosind git reset HEAD^,
asta nu v-a afecta directorul de lucru.
Acum că am încărcat cîte ceva, puteţi vedea istoria schimbărilor:
| git log git blame fișier |
svn log | less svn blame fișier |
Comanda log funcţionează similar cu cea din Subversion; iarăşi,
git log este foarte puternică, vedeţi opţiunile ei pentru a-i
vedea posibilităţile.
Comanda blame este mai puternică deoarece poate detecta mişcarea liniilor,
chiar cu copii ale fişierilor şi redenumirilor. Dar probabil aţi vrea să faceţi altceva! Deobicei,
cînd folosiţi annotate căutaţi originea a unei bucăţi de cod,
şi aşa numita unealtă pickaxe al Git-ului este mult mai confortabilă
pentru acest lucru (git log -Sstring arată
comiterile care adaugă sau şterge careva fişiere care conrespund cu masca string).
Puteţi vedea conţinutul unui fişier, al unul director sau a unui commit cu:
| git show rev:calea/spre/fișier
git show rev:calea/spre/directoriu git show rev |
svn cat url
svn list url svn log -rrev url svn diff -crev url |
Subversion marchează unele checkpoint-uri în istorie printre copii, copie este
plasată deobicei în directoriul numit tags. Tag-urile în Git au cu mult mai mult potenţial: ele pot avea o descriere arbitrară ataşată (prima linie
e specială ca şi în cazul commit-ului), unii defapt păstrează
toate anunţurile în tag-ul descriptions. Identitatea
persoanei care a etichetat este păstrată(iarăşi folosind aceleaşi reguli
ca şi identitatea commiter-ului). De obicei etichetaţi commit-urile dar, dacă doriţi,
puteţi să etichetaţi fişiere (sau directoarele).
şi etichetarea poate fi semnată cryptographic PGP pentru a verifica identitatea
(după natura Git-ului, această semnătură deasemenea confirmă validitatea
reviziei asociate, istoria ei şi ramificarea). Deci:
| git tag -a nume_etichetă | svn copy http://example.com/svn/trunk http://example.com/svn/tags/nume_etichetă |
Pentru listarea etichetelor şi afişarea messajelor lor:
| git tag -l git show etichetă |
svn list http://example.com/svn/tags/
svn log --limit 1 http://example.com/svn/tags/tag |
Ca şi Subversion, Git poate face ramificări (surprize surprize!). În Subversion, de fapt copiaţi proiectul într-un subdirector. În Git, îi spuneţi... ăăăă ...să creeze o ramificare.
| git branch ramură
git checkout ramură |
svn copy http://example.com/svn/trunk
http://example.com/svn/branches/ramurpbranch
svn switch http://example.com/svn/branches/ramură |
Prima comandă creează o ramificare, a doua comandă trece directorul de lucru
într-o altă ramificare. Puteţi adăuga încă un argument la
git branch pentru a aduce directorul de lucru la o versiune diferită
de cea mai recentă.
Puteţi lista ramificările convinabil folosind comanda git branch fără argumente.
Ramura curentă e marcată cu "*".
| git branch | svn list http://example.com/svn/branches/ |
Pentru a trece proiectul la o versiune mai veche, folosiţi:
| git checkout rev
git checkout prevbranch |
svn update -r rev svn update |
Sau puteţi crea o ramificare temporară. În Git puteţi commite în versiuni mai vechi şi să o folosiţi ca o altă ramificare.
Git suportă fuzionarea între ramificări mai bine decît Subversion - istoria la ambele ramificări se păstrează în decursul a mai multe fizionări astfel repetarea fuzionilor se face foarte simplu. Asiguraţi-vă că vă aflaţi în una din ramurile pe care doriţi să le fuzionaţi şi o puteţi fuziona cu alta specificînd-o ca parametru:
| git merge ramură | (presupunînd că ramura a fost creată în versiunea 20 şi sînteţi în copia de lucru a trunk)
svn merge -r 20:HEAD http://example.com/svn/branches/branch |
Dacă schimbările au fost făcute numai pe una din ramificări de la ultima fuzionare,
ele pur şi simplu v-or fi copiate pe cealaltă (aşa numita fast-forward merge).
Dacă au fost făcute schimbări pe ambele ramificări, ele sunt fuzionate inteligent
(aşa numit three-way merge): dacă oarecare fuzionarea e cu conflict, git merge
le va reporta şi vă va lăsa să le corectaţi, fuzionînd restul fişierelor; puteţi executa git commit cînd rezolvaţi conflictele. Dacă nu există nici un conflict, o comiterea e făcută automat cu un mesaj de log convenabil (sau puteţi să faceţi
git merge --no-commit ramură pentru a revedea rezultatul
fuzionării şi după aceea să faceţi commit manual).
În afară de fuzionare, uneori e nevoie doar să scoateţi un anumit commit dintr-o altă ramificare. Pentru a aplica schimbările în versiunea rev şi a le comite într-o ramificare curentă folosiţi:
| git cherry-pick rev | svn merge -c rev url |
Pînă aici, noi am neglijat faptul că Git este un sistem distribuit de versionare. Să încercăm să accesăm repozitoriile la distanţă.
Dacă lucraţi la proiectul altcuiva de obicei clonaţi repozitoriul în loc să începeţi unul desinestătător. Noi deja am menţionat la începutul acestui document:
| git clone url | svn checkout url |
Acum aveţi ramificarea implicită a repozitoriului, de obicei numită master,
dar mai aveţi şi alte ramificări la distanţă, şi etichete.
În configuraţia implicită a proiectului clonat, ramificarea implicită locală urmăreşte
ramificarea externă origin, care reprezintă ramificarea implicită în repozitoriul la distanţă.
Vă întrebaţi ce înseamnă repozitoriu la distanţă? Păi, pînă acum am lucrat numai cu repozitorii locale. Repozitoriile la distanţă sînt o imagine-oglindă a ramurilor din repozitoriile la distanţă şi niciodată nu veţi face schimbări direct în ele. Nu aveţi niciodată treabă cu ramificările la distanţă. Dacă vreţi să treceţi în una din ele, trebuie să creaţi o ramificare locală corespunzătoare care va versiona ramificarea externă:
| git checkout --track -b ramură origin/ramură | svn switch url |
Dacă DVS doriţi permanent să urmăriţi ramuri externe (şi să uitaţi
de --track) puteţi seta:
git config --global branch.autosetupmerge auto
Puteţi adăuga mai multe ramificări la distanţă la un repozitoriu clonat, la fel ca şi
unul nou iniţializat, folosind git remote add remote url.
Comanda git remote listează toate repozitoriile la distanţă
şi git remote show remote arată
ramificările într-un repozitoriu la distanţă.
Acum, cum luaţi careva schimbări dintr-un repozitoriu la distanţă?
le descărcați: git fetch.
La acest moment ele sînt în repozitoriul local şi le puteţi examina folosind
git log origin (git log HEAD..origin
pentru a vedea schimbările care nu le aveţi în ramificarea locală), faceţi un diff, şi evident, fuzionaţi-le - doar rulaţi
git merge origin. Notă!!! Dacă nu specificaţi o ramificare
pentru descărcare, implicit se va considera aceeaşi ramificare de la distanţă.
Deoarece se întîmplă foarte des să descărcați și fuzionaţi ramificarea externă, există o comandă pentru automatizarea acestui lucru:
| git pull | svn update |
Repozitoriul local poate fi folosit de alţii pentru a scoate (pull) schimbări, dar
normal aţi vrea să aveţi un repozitoriu privat şi unul public.
Cel public este cel în care comiteţi şi din care ceilalţi descarcă.
Rulăm git push remote pentru a publica ramificările locale în ramificările la distanţă corespunzătoare - aceasta lucrează
de obicei doar prin SSH (sau HTTP dar cu o setare specială a webserverului).
Este recomandat ca să setaţi o cheie SSH şi un mecanism SSH
pentru a nu fi nevoit să introduceţi parola de fiecare dată.
Un lucru important este că de obicei ar trebui să publicaţi numai ramificări îndepărtate care nu sînt la moment luate pe de altă parte (din acelaşi motiv niciodată nu treceţi repozitoriul local la o ramificare de la distanţă)! Altfel copia de lucru a ramificării de la distanţă va fi neactualizată şi va se va crea o situaţie confuză. Cel mai bine pentru a evita aceasta este de a publica numai repozitoriile la distanţă care nu conţin copii de lucru - aşa numitele repozitorii singuratice care este deobicei folosit pentru acces public sau un loc de întîlnire pentru programatori - doar pentru a distribui istoria, pentru care descărcarea unei copii de lucru ar fi inutilă. Puteţi crea un asemenea repozitoriu. Vedeţi Setarea unui repozitoriu public pentru detalii.
Git poate lucra cu acelaşi flux ca şi Subversion, cu un grup de programatori
folosind un singur schimb de repozitorii al lucrului lor. Unica schimbare
este că schimbările lor nu sînt aplicate automat dar trebuie să
fie comise (oricum, puteţi seta un hook post-commit care să publice de fiecare dată cînd rulaţi commit; aceasta pierde flexibilitatea de a corecta commit-urile
eronate). Developerii trebuie să aibă o înregistrare în .htaccess
(pentru HTTP DAV) sau un cont UNIX (pentru SSH). Puteti să-i limitaţi contul
shell numai pentru operaţiuni Git folosind git-shell.
De asemenea puteţi schimba patch-uri prin e-mail. Git are un suport foarte bun
pentru patch-urile primite prin e-mail. Le puteţi aplica transmiţînd e-mail-urile
cu patch-uri spre git am. Dacă vreţi să
trimiteţi patch-uri folosiţi git format-patch şi
posibil git send-email.
Pentru a menţine un set de patch-uri e mai bine să folosiţi
programul StGIT (vedeţi
StGIT Crash Course).
Dacă aveţi întrebări sau probleme care nu sînt înţelese din documentaţie, vă rugăm să ne contactaţi Git mailing list pe adresa git@vger.kernel.org. Sperăm să-l folosiţi Git cu plăcere!