Rebase pe scurt
Lectură estimată: 4 minute
Estimare pentru text, la un ritm de 180 de cuvinte pe minut. Timpul pentru analizarea codului, exerciții și proiecte se adaugă separat și depinde de ritmul tău.
Rebase are o reputație proastă nemeritată. E o unealtă simplă, cu o singură regulă de siguranță care, dacă e respectată, face istoricul proiectului mult mai ușor de citit.
Ce face rebase
Merge combină două istorii și lasă urma acestei combinări (merge commit). Rebase face altceva: ia commit-urile tale și le rejoacă peste alt punct de plecare, ca și cum ai fi început să lucrezi de acolo.
Înainte:
A---B---C---F (main)
\
D---E (feature)
După git rebase main:
A---B---C---F---D'---E' (feature)
Observă apostroful: D' și E' nu sunt aceleași commit-uri. Au alt hash, pentru că au alt părinte. Conținutul e același, identitatea nu. Din asta derivă toate regulile de mai jos.
Cum îl folosești
git switch feature/export-facturi
git fetch origin
git rebase origin/main
Dacă apar conflicte, le rezolvi la fel ca la merge, dar continui altfel:
# editezi fișierele, apoi
git add fisier-rezolvat.php
git rebase --continue
# sau, dacă vrei să renunți complet
git rebase --abort
La rebase, conflictele pot apărea de mai multe ori: o dată pentru fiecare commit rejucat. E normal și e motivul pentru care rebase pe un branch cu 30 de commit-uri e obositor.
Regula de aur
Nu faci rebase la commit-uri pe care le-au luat deja alții.
Dacă rescrii istoricul unui branch pe care lucrează și un coleg, la următorul lui pull Git nu mai recunoaște nimic, iar el ajunge cu commit-uri duplicate și o dimineață pierdută.
Practic: rebase pe branch-ul tău, care e doar al tău. Merge pentru ce e public (main, develop, branch-uri partajate).
Push după rebase
Dacă branch-ul era deja publicat, după rebase push-ul normal va fi respins — pe bună dreptate, pentru că istoricul e diferit. Soluția corectă:
git push --force-with-lease
Folosește --force-with-lease, nu --force. Diferența e importantă: --force-with-lease refuză să suprascrie dacă între timp altcineva a împins ceva ce tu nu ai văzut. --force șterge fără să întrebe.
Rebase interactiv: curățenie înainte de review
Asta e partea cu adevărat utilă zilnic. Ai un branch cu commit-uri de lucru:
* 9f1a2b3 fix typo
* 3c4d5e6 inca o incercare
* 7a8b9c0 wip
* 1d2e3f4 Adaugă export PDF pentru facturi
Nimeni nu vrea să vadă asta într-un pull request. Le combini:
git rebase -i HEAD~4
Se deschide editorul:
pick 1d2e3f4 Adaugă export PDF pentru facturi
pick 7a8b9c0 wip
pick 3c4d5e6 inca o incercare
pick 9f1a2b3 fix typo
Schimbi pick în squash (sau s) pe cele care trebuie topite în cel de deasupra:
pick 1d2e3f4 Adaugă export PDF pentru facturi
squash 7a8b9c0 wip
squash 3c4d5e6 inca o incercare
squash 9f1a2b3 fix typo
Salvezi, Git îți cere un mesaj final și rămâi cu un singur commit curat.
Alte comenzi disponibile în lista aceea: reword (schimbi doar mesajul), edit (te oprește ca să modifici commit-ul), drop (îl elimini), fixup (ca squash, dar aruncă mesajul).
Corectarea ultimului commit
Pentru cazul banal — ai uitat un fișier sau ai greșit mesajul — nu ai nevoie de rebase:
git add fisierul-uitat.php
git commit --amend --no-edit # păstrează mesajul
git commit --amend -m "Mesaj corect"
Și --amend rescrie istoricul, deci aceeași regulă: doar pe commit-uri nepublicate.
Cum arată istoricul, în practică
Diferența dintre cele două abordări se vede cel mai bine pe un proiect real, după câteva săptămâni.
Cu merge la fiecare sincronizare, istoricul lui main arată așa:
* Merge branch 'main' into feature/facturi
|\
| * Repară afișarea totalului
* | Adaugă export CSV
|/
* Merge branch 'main' into feature/facturi
|\
| * Actualizează dependențele
Jumătate din linii nu spun nimic despre produs; sunt doar urme ale sincronizărilor. Cu rebase înainte de integrare, aceeași muncă arată așa:
* Adaugă export CSV pentru facturi
* Repară afișarea totalului
* Actualizează dependențele
Al doilea istoric poate fi citit de cineva care caută când s-a introdus un bug. Primul, nu prea.
Un rebase tipic, pas cu pas
git switch feature/facturi
git fetch origin
git rebase origin/main
Auto-merging app/Services/Factura.php
CONFLICT (content): Merge conflict in app/Services/Factura.php
error: could not apply 1d2e3f4... Adaugă export CSV
Deschizi fișierul, rezolvi exact ca la merge, apoi:
git add app/Services/Factura.php
git rebase --continue
Dacă apare din nou conflict, repeți. Când termini, Git îți spune Successfully rebased and updated refs/heads/feature/facturi.
Dacă la un pas constați că un commit a devenit inutil (modificarea lui e deja în main), îl poți sări:
git rebase --skip
Plasa de siguranță înainte de rebase
Dacă rebase-ul te sperie, fă-ți o etichetă temporară. Costă două secunde și îți garantează întoarcerea:
git branch backup/facturi-inainte-de-rebase
git rebase origin/main
# dacă iese prost:
git reset --hard backup/facturi-inainte-de-rebase
Aceeași siguranță o ai și din git reflog, dar un branch de rezervă e mai ușor de găsit când ești sub presiune.
Merge sau rebase? Răspunsul practic
- Actualizezi branch-ul tău cu ce e nou în main → rebase, ca să nu umpli istoricul de merge commit-uri inutile.
- Integrezi o funcționalitate terminată în main → merge (de obicei prin pull request).
- Cureți commit-urile de lucru înainte de review → rebase interactiv cu squash.
- Branch-ul e partajat cu altcineva → merge, niciodată rebase.
Exercițiu
- Creează un branch cu patru commit-uri, dintre care trei cu mesaje inutile („wip", „fix", „iar").
- Combină-le într-unul singur cu
git rebase -i HEAD~4și scrie un mesaj corect. - Între timp, adaugă un commit pe
main, apoi ruleazăgit rebase mainîn branch și observă hash-urile noi. - Explică-ți, cu propriile cuvinte, de ce push-ul ar fi respins dacă branch-ul era deja publicat.
Aplicație practică
Sarcina
Compară merge cu rebase într-un repository de laborator.
Rezolvare orientativă și verificare
Desenează istoricul înainte și după. Folosește rebase doar pe istoricul pentru care poți coordona rescrierea.
Greșeală de evitat
Nu rescrie istoricul partajat fără acordul echipei.
Documentație și surse
- Pro Git — Git
Verifică-ți înțelegerea
4 întrebări · îți trebuie 70% ca să promovezi și ca lecția să fie marcată parcursă.
Autentifică-te ca să rezolvi testul și să-ți salvezi progresul.