Toate ghidurile

Git în practică: fluxul de lucru de zi cu zi

Fluxul Git de la job, pas cu pas: branch-uri, commit-uri, pull request-uri, merge vs. rebase, conflicte și repararea greșelilor.


Majoritatea tutorialelor de Git îți arată comenzile una câte una, dar la job nu folosești comenzi izolate, ci un flux de lucru care se repetă zilnic: actualizezi codul, creezi un branch, faci commit-uri, deschizi un pull request și rezolvi conflicte. Ghidul acesta urmărește exact acest flux, cu comenzile actuale (inclusiv git switch și git restore) și cu soluții pentru greșelile pe care le face toată lumea.

Modelul mental: cele trei zone

Aproape toată confuzia legată de Git dispare când înțelegi unde se află modificările tale în fiecare moment.

ZonaCe conțineCum ajungi acolo
Working directoryFișierele așa cum le vezi în editorEditezi fișierele
Staging area (index)Modificările pregătite pentru următorul commitgit add
Repository localIstoricul de commit-uri de pe calculatorul tăugit commit
Remote (de exemplu GitHub)Istoricul partajat cu echipagit push

git status îți spune oricând ce se află în fiecare zonă. Folosește-l des: este cea mai sigură comandă din Git și răspunde la întrebarea „ce se întâmplă acum?”.

Configurarea inițială

Înainte de primul commit, setează-ți identitatea și câteva opțiuni utile:

git config --global user.name "Ana Popescu"
git config --global user.email "ana.popescu@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase true

Ultima linie face ca git pull să aplice commit-urile tale locale peste cele noi de pe server, în loc să creeze un commit de merge la fiecare actualizare. Este o alegere frecventă în echipe; dacă proiectul tău are altă convenție, urmeaz-o.

Pentru autentificarea la GitHub sau GitLab, cea mai comodă variantă este o cheie SSH:

ssh-keygen -t ed25519 -C "ana.popescu@example.com"

Adaugi apoi conținutul fișierului ~/.ssh/id_ed25519.pub în setările contului tău de pe platformă.

Fluxul de zi cu zi

Iată ce faci, în ordine, când primești o sarcină nouă.

1. Pornești de la un main actualizat

git switch main
git pull

git switch a fost introdus în Git 2.23 ca alternativă mai clară la git checkout pentru schimbarea branch-urilor. git checkout funcționează în continuare, dar face prea multe lucruri diferite, ceea ce îl face ușor de folosit greșit.

2. Creezi un branch pentru sarcină

git switch -c feature/filtrare-produse

Câteva convenții frecvente pentru nume: feature/... pentru funcționalități noi, fix/... pentru bug-uri, chore/... pentru întreținere. Multe echipe includ și numărul tichetului, de exemplu fix/SHOP-142-total-gresit.

3. Lucrezi și verifici ce ai schimbat

git status
git diff

git diff arată modificările care nu sunt încă în staging. După git add, le vezi cu git diff --staged.

4. Pregătești și faci commit

git add src/filtre.js
git commit -m "Adaugă filtrarea produselor după categorie"

O opțiune foarte utilă este git add -p, care îți arată modificările bucată cu bucată și te întreabă ce vrei să incluzi. Așa poți separa în commit-uri diferite două modificări făcute în același fișier și eviți să incluzi din greșeală un console.log uitat.

5. Publici branch-ul

git push -u origin feature/filtrare-produse

Opțiunea -u leagă branch-ul local de cel de pe server; de acum înainte, un simplu git push sau git pull știe unde să meargă.

6. Deschizi un pull request

Pe GitHub, după push, apare un buton pentru crearea unui pull request. Dacă preferi terminalul, GitHub CLI face același lucru:

gh pr create --title "Filtrare produse după categorie" --body "Rezolvă SHOP-142"

În descrierea pull request-ului explică ce ai schimbat, de ce și cum se poate testa. Colegii care fac review îți vor fi recunoscători.

7. După merge, faci curat

git switch main
git pull
git branch -d feature/filtrare-produse
git fetch --prune

git fetch --prune elimină referințele locale către branch-urile care au fost șterse de pe server.

Dacă echipa folosește „Squash and merge” pe GitHub, commit-urile tale ajung pe main sub forma unui singur commit nou, iar git branch -d poate refuza ștergerea, considerând branch-ul nemerge-uit. După ce ai verificat că pull request-ul a fost într-adevăr integrat, folosește git branch -D.

Code review: de partea cealaltă a pull request-ului

În majoritatea echipelor, nicio modificare nu ajunge pe main fără aprobarea cel puțin a unui coleg. Câteva lucruri utile despre acest proces:

  • Când primești comentarii, faci modificările pe același branch și dai git push; pull request-ul se actualizează automat. Răspunde la fiecare comentariu, chiar și cu un simplu „rezolvat”.
  • Când faci tu review, poți aduce branch-ul colegului local cu git fetch și git switch nume-branch, ca să rulezi codul, nu doar să-l citești.
  • Comentariile sunt despre cod, nu despre persoană. Formulările de tipul „Ce-ar fi dacă am extrage asta într-o funcție?” funcționează mai bine decât „Asta e greșit”.

Pentru un junior, review-urile primite sunt una dintre cele mai rapide surse de învățare din primul an de job.

Mesaje de commit care chiar ajută

Un istoric bun îți permite să înțelegi peste șase luni de ce a fost schimbat un fișier. Câteva reguli larg acceptate:

  • Primul rând scurt (în jur de 50 de caractere), la imperativ: „Adaugă”, „Corectează”, „Elimină”.
  • Dacă e nevoie de detalii, lași un rând gol și explici de ce, nu ce (diff-ul arată deja ce).
  • Un commit face un singur lucru logic. „Repară bug-ul de login și redenumește variabile” sunt două commit-uri.

Multe proiecte folosesc convenția Conventional Commits, cu prefixe precum feat:, fix: sau docs:. Dacă proiectul are un fișier CONTRIBUTING.md, verifică acolo regulile.

Sincronizarea cu main: merge sau rebase

Cât timp lucrezi pe branch-ul tău, colegii adaugă commit-uri noi pe main. Înainte de a finaliza pull request-ul, trebuie să-ți actualizezi branch-ul. Ai două variante:

# Varianta 1: merge
git fetch origin
git merge origin/main

# Varianta 2: rebase
git fetch origin
git rebase origin/main
MergeRebase
IstoricPăstrează exact ce s-a întâmplat, cu un commit de mergeLiniar, ca și cum ai fi pornit de la main actualizat
Rescrie commit-uriNuDa, commit-urile tale primesc identificatori noi
Push după operațiegit push normalNecesită git push --force-with-lease
Potrivit pentruBranch-uri partajate cu alți colegiBranch-uri personale, înainte de review

Regula de bază: nu face rebase pe un branch pe care lucrează și alți oameni, pentru că le rescrii istoricul. Iar când trebuie să forțezi push-ul, folosește --force-with-lease în loc de --force: refuză suprascrierea dacă între timp altcineva a împins modificări pe același branch.

Rezolvarea conflictelor

Un conflict apare când două modificări ating aceleași linii. Git oprește operația și marchează fișierul:

<<<<<<< HEAD
const TVA = 0.21;
=======
const TVA = calculeazaTVA(produs);
>>>>>>> feature/tva-dinamic

Partea de sus este versiunea curentă, partea de jos este cea care vine din celălalt branch. Pașii de rezolvare:

  1. Rulezi git status ca să vezi fișierele în conflict.
  2. Editezi fiecare fișier și păstrezi varianta corectă (uneori o combinație a celor două), apoi ștergi marcajele.
  3. Rulezi testele sau pornești aplicația ca să verifici rezultatul.
  4. Marchezi conflictul ca rezolvat cu git add fisier.js.
  5. Continui operația: git merge --continue sau git rebase --continue.

Dacă te-ai încurcat, poți renunța complet cu git merge --abort sau git rebase --abort și o iei de la capăt. Majoritatea editoarelor moderne au și o interfață vizuală pentru conflicte, care face pașii 1-2 mult mai ușori.

„Am greșit, ce fac?”

Partea bună la Git este că aproape orice greșeală se poate repara. Tabelul de mai jos acoperă situațiile cele mai frecvente:

SituațiaComanda
Vreau să anulez modificările necommise dintr-un fișiergit restore fisier.js
Am adăugat un fișier în staging din greșealăgit restore --staged fisier.js
Am greșit mesajul ultimului commit (încă nepublicat)git commit --amend -m "Mesaj corect"
Am uitat un fișier în ultimul commit (încă nepublicat)git add fisier.js apoi git commit --amend --no-edit
Vreau să desfac ultimul commit, dar să păstrez modificărilegit reset --soft HEAD~1
Vreau să anulez un commit deja publicatgit revert <sha>
Trebuie să schimb branch-ul, dar am lucru neterminatgit stash push -m "lucru neterminat" apoi git stash pop
Am pierdut un commit după un reset sau rebasegit reflog, apoi git switch -c recuperare <sha>

Două atenționări importante:

  • git restore fisier.js șterge definitiv modificările necommise din fișier. Nu există „undo” pentru ele.
  • Pentru commit-uri deja publicate pe un branch partajat, folosește git revert, care adaugă un commit nou ce anulează modificarea, în loc să rescrie istoricul.

git reflog este plasa de siguranță: păstrează pentru o perioadă istoricul tuturor pozițiilor prin care a trecut HEAD, așa că poți recupera commit-uri care par pierdute.

Explorarea istoricului

Câteva comenzi pe care le vei folosi ca să înțelegi un proiect existent:

git log --oneline --graph --all     # istoricul compact, cu branch-uri
git log -p -- src/cos.js            # toate modificările unui fișier
git show a1b2c3d                    # detaliile unui commit
git blame src/cos.js                # cine și în ce commit a modificat fiecare linie
git log -S "calculeazaTVA"          # commit-urile care au adăugat sau eliminat un text

Poți crea aliasuri pentru comenzile lungi:

git config --global alias.lg "log --oneline --graph --all"

De acum, git lg îți afișează istoricul în format compact.

Fișierul .gitignore

Unele fișiere nu trebuie să ajungă niciodată în repository: dependențele, fișierele generate la build și, mai ales, secretele. Un .gitignore tipic pentru un proiect JavaScript:

node_modules/
dist/
.env
.env.local
*.log
.DS_Store

Atenție: .gitignore afectează doar fișierele care nu sunt deja urmărite. Dacă ai făcut commit cu un fișier .env, adăugarea lui în .gitignore nu îl scoate din istoric. Îl oprești din urmărire cu git rm --cached .env, dar secretele din el trebuie considerate compromise și schimbate.

Obiceiuri care te scutesc de probleme

  • Rulezi git status înainte de orice git add, git commit sau schimbare de branch.
  • Faci commit-uri mici și dese, nu unul uriaș la final de zi.
  • Actualizezi des branch-ul cu main, ca să ai conflicte mici în loc de unul mare.
  • Ții pull request-urile mici: sunt revizuite mai repede și mai atent.
  • Nu lucrezi direct pe main nici în proiectele personale; exersezi fluxul pe care îl vei folosi la job.

Pașii următori

  1. Creează un repository de test și parcurge fluxul complet din acest ghid: branch, commit-uri, push, pull request, merge.
  2. Provoacă intenționat un conflict, modificând aceeași linie pe două branch-uri, și rezolvă-l.
  3. Continuă cu roadmap-ul Git și GitHub pentru subiecte precum tag-uri, GitHub Actions și colaborarea în proiecte open source.
  4. Ține la îndemână documentația oficială Git și cartea gratuită Pro Git pentru detalii despre fiecare comandă.