Un ghid pentru a anula greșelile cu Git (Partea a 2-a)

Publicat: 2022-03-10
Rezumat rapid ↬ Greșeli. Acești răufăcători cruzi nici măcar nu se opresc la frumoasa lume a dezvoltării software. Dar deși nu putem evita să facem greșeli, putem învăța să le anulăm! Acest articol va arăta instrumentele potrivite pentru munca ta zilnică cu Git. Poate doriți să verificați și primul articol al seriei.

În această a doua parte a seriei noastre despre „Anularea greșelilor cu Git”, vom privi cu curaj din nou pericolul în ochi: am pregătit patru noi scenarii de apocalipsa – inclusiv, desigur, câteva modalități inteligente de a ne salva gâtul! Dar înainte de a ne arunca o privire: aruncați o privire la articolele anterioare despre Git pentru și mai multe metode de autosalvare care vă ajută să vă anulați greșelile cu Git!

Să mergem!

Recuperarea unei ramuri șterse folosind Reflog

Ai șters vreodată o ramură și, la scurt timp după, ți-ai dat seama că nu ar fi trebuit? În cazul improbabil în care nu cunoști acest sentiment, pot să-ți spun că nu este unul bun. Un amestec de tristețe și furie se strecoară asupra ta, în timp ce te gândești la toată munca grea care a intrat în comisiile acelei sucursale, la tot codul valoros pe care l-ai pierdut acum.

Din fericire, există o modalitate de a aduce acea ramură înapoi din morți - cu ajutorul unui instrument Git numit „Reflog”. Am folosit acest instrument în prima parte a seriei noastre, dar iată o mică reîmprospătare: Reflog-ul este ca un jurnal în care Git notează fiecare mișcare a indicatorului HEAD în depozitul tău local. Cu alte cuvinte, mai puțin tocilar: de fiecare dată când plătiți, comiteți, îmbinați, rebazați, alegeți și așa mai departe, este creată o intrare de jurnal. Acest lucru face din Reflog o plasă de siguranță perfectă atunci când lucrurile merg prost!

Să aruncăm o privire la un exemplu concret:

 $ git branch * feature/login master

Putem vedea că în prezent avem feature/login filialei verificate. Să presupunem că aceasta este ramura pe care o vom șterge (din neatenție). Înainte de a putea face asta, totuși, trebuie să trecem la o altă ramură, deoarece nu putem șterge ramura noastră HEAD actuală!

 $ git checkout master $ git branch -d feature/login

Ramura noastră valoroasă a dispărut acum – și vă voi acorda un minut pentru (a) să înțelegeți gravitatea greșelii noastre și (b) să vă plângeți puțin. După ce ai șters lacrimile, trebuie să găsim o modalitate de a aduce înapoi această ramură! Să deschidem Reflog-ul (pur și simplu tastând git reflog ) și să vedem ce ne rezervă:

Reflog-ul Git protocoale toate acțiunile majore din depozitul nostru local
Reflog-ul lui Git protocoale toate acțiunile majore din depozitul nostru local. (Previzualizare mare)

Iată câteva comentarii pentru a vă ajuta să înțelegeți rezultatul:

  • În primul rând, trebuie să știți că Reflog-ul își sortează intrările cronologic: cele mai noi articole sunt în fruntea listei.
  • Cel mai de sus (și, prin urmare, cel mai nou) element este comanda git checkout pe care am efectuat-o înainte de a șterge ramura. Este înregistrat aici în Reflog, deoarece este una dintre aceste „mișcări HEAD pointer” pe care Reflog le înregistrează cu atâta grijă.
  • Pentru a remedia greșeala noastră gravă, ne putem întoarce pur și simplu la starea anterioară - care este, de asemenea, consemnată în mod curat și clar în Reflog!

Deci, să încercăm asta, creând o nouă ramură (cu numele ramurii noastre „pierdute”) care începe la această stare „înainte” SHA-1:

 $ git branch feature/login 776f8ca

Și voila! Veți fi încântați să vedeți că acum am restaurat ramura noastră aparent pierdută!

Dacă utilizați o interfață grafică pentru desktop Git, cum ar fi „Tower”, puteți lua o comandă rapidă frumoasă: apăsați pur și simplu CMD + Z de pe tastatură pentru a anula ultima comandă - chiar dacă tocmai ați șters violent o ramură!

O interfață grafică desktop precum Tower poate facilita procesul de anulare a greșelilor.
Mai multe după săritură! Continuați să citiți mai jos ↓

Mutarea unui angajament într-o ramură diferită

În multe echipe, există un acord de a nu se angaja în ramuri de lungă durată, cum ar fi main sau develop : ramurile ca acestea ar trebui să primească noi comiteri numai prin integrări (de exemplu, fuziuni sau rebaze). Și totuși, desigur, greșelile sunt inevitabile: uneori uităm și ne comităm totuși în aceste ramuri! Deci, cum putem curăța mizeria pe care am făcut-o?

Mutarea unui commit la ramura de destinație corectă
Angajamentul nostru a aterizat pe ramura greșită. Cum îl putem muta în ramura sa de destinație corectă? (Previzualizare mare)

Din fericire, aceste tipuri de probleme pot fi corectate cu ușurință. Să ne suflecăm mânecile și să trecem la treabă.

Primul pas este să comutați la ramura de destinație corectă și apoi să mutați commit-ul folosind comanda cherry-pick :

 $ git checkout feature/login $ git cherry-pick 776f8caf

Veți avea acum commit-ul pe ramura dorită, unde ar fi trebuit să fie în primul rând. Minunat!

Dar mai rămâne un lucru de făcut: trebuie să curățăm creanga unde a aterizat accidental la început! Comanda cherry-pick , ca să spunem așa, a creat o copie a commit-ului - dar originalul este încă prezent pe ramura noastră de lungă durată:

O copie a comenzii pe ramura corectă, dar originalul se arată totuși a fi pe ramura greșită
Am creat cu succes o copie a comenzii pe ramura corectă, dar originalul este încă aici - pe ramura greșită. (Previzualizare mare)

Aceasta înseamnă că trebuie să revenim la ramura noastră de lungă durată și să folosim git reset pentru a o elimina:

 $ git checkout main $ git reset --hard HEAD~1

După cum puteți vedea, folosim aici comanda git reset pentru a șterge comiterea defectuoasă. Parametrul HEAD~1 îi spune lui Git să „retoarcă cu 1 revizuire în spatele HEAD”, ștergând efectiv cel mai de sus (și în cazul nostru: nedorit) din istoria acelei ramuri.

Și voilà: commit-ul este acum acolo unde ar fi trebuit să fie în primul rând și ramura noastră de lungă durată este curată - de parcă greșeala noastră nu s-ar fi întâmplat niciodată!

Editarea mesajului unui vechi commit

Este prea ușor să introduci o greșeală de tipar într-un mesaj de confirmare - și să o descoperi mult mai târziu. Într-un astfel de caz, vechea opțiune --amend a git commit nu poate fi folosită pentru a remedia această problemă, deoarece funcționează doar pentru ultima comitere. Pentru a corecta orice comitere mai veche decât aceasta, trebuie să apelăm la un instrument Git numit „Interactive Rebase”.

Un mesaj de confirmare care merită schimbat
Iată un mesaj de confirmare care merită schimbat. (Previzualizare mare)

În primul rând, trebuie să spunem Interactive Rebase care parte din istoricul de comitere vrem să edităm. Acest lucru se face prin introducerea unui commit hash: commit-ul părinte al celui pe care vrem să-l manipulăm.

 $ git rebase -i 6bcf266b

Se va deschide apoi o fereastră de editor. Conține o listă a tuturor comiterilor după cea pe care am furnizat-o ca bază pentru Rebase interactivă în comandă:

Afișează gama de comite pe care le-am selectat pentru editare în sesiunea noastră interactivă Rebase
Gama de comite pe care le-am selectat pentru editare în sesiunea noastră Interactive Rebase. (Previzualizare mare)

Aici, este important să nu urmezi primul impuls: în acest pas, încă nu edităm mesajul de comit. În schimb, îi spunem lui Git doar ce fel de manipulare vrem să facem cu ce comite(e). Destul de convenabil, există o listă de cuvinte cheie de acțiune notate în comentariile din partea de jos a acestei ferestre. Pentru cazul nostru, marcam linia #1 cu reword (inlocuind astfel pick standard).

Tot ce mai rămâne de făcut în acest pas este să salvați și să închideți fereastra editorului. În schimb, se va deschide o nouă fereastră de editor care conține mesajul curent al commit-ului pe care l-am marcat. Și acum este în sfârșit momentul să ne facem modificările!

Iată întregul proces dintr-o privire pentru tine:

Folosind Interactive Rebase pentru a edita mesajul unui vechi commit, de la început până la sfârșit.

Corectarea unui commit întrerupt (într-un mod foarte elegant)

În cele din urmă, vom arunca o privire la fixup , cuțitul elvețian al instrumentelor de anulare. Mai simplu, vă permite să remediați o comitere ruptă/incompletă/incorectă după fapt. Este cu adevărat un instrument minunat din două motive:

  1. Nu contează care este problema.
    Este posibil să fi uitat să adăugați un fișier, ar fi trebuit să ștergeți ceva, să fi făcut o modificare incorectă sau pur și simplu o greșeală de scriere. fixup funcționează în toate aceste situații!
  2. Este extrem de elegant.
    Reacția noastră normală, instinctivă, la o eroare într-o comitere este să producem un nou comit care să rezolve problema. Acest mod de lucru, oricât de intuitiv ar părea, face ca istoricul de comitere să pară foarte haotic, foarte curând. Aveți comiteri „originale” și apoi aceste mici comiteri „aparate” care remediază lucrurile care au mers prost în comiterile originale. Istoria ta este plină de comiteri mici, fără sens, ceea ce face dificil de înțeles ce s-a întâmplat în baza ta de cod.
Istoricul dvs. de comitere poate fi foarte greu de citit dacă remediați în mod constant micile greșeli cu așa-numitele comiteri de band-aid
Remedierea în mod constant a micilor greșeli cu „comiterile de ajutor” face ca istoricul de comitere să fie foarte greu de citit. (Previzualizare mare)

Aici intervine fixup . Vă permite să faceți în continuare această comitere de corectare. Dar aici vine magia: apoi îl aplică la comiterea originală, ruptă (reparându-l în acest fel) și apoi aruncă complet comiterea urâtă de band-aid!

Fixup aplică corecțiile dvs. la comiterea inițială și apoi elimină comiterea superfluă cu band-aid
Fixup aplică corecțiile dvs. la comiterea inițială și apoi elimină comiterea superfluă. (Previzualizare mare)

Putem trece printr-un exemplu practic împreună! Să presupunem că commit-ul selectat aici este rupt.

Remedierea comiterii incorecte selectate într-un mod elegant
Comiterea selectată este incorectă - și o vom remedia într-un mod elegant. (Previzualizare mare)

mai spunem că am pregătit modificări într-un fișier numit error.html care vor rezolva problema. Iată primul pas pe care trebuie să-l facem:

 $ git add error.html $ git commit --fixup 2b504bee

Creăm un nou commit, dar îi spunem lui Git că acesta este unul special: este o remediere pentru un vechi commit cu hash-ul SHA-1 specificat ( 2b504bee în acest caz).

Al doilea pas, acum, este să porniți o sesiune Interactive Rebase - deoarece fixup aparține setului mare de instrumente Interactive Rebase.

 $ git rebase -i --autosquash 0023cddd

Două lucruri merită explicate despre această comandă. În primul rând, de ce am furnizat 0023cddd ca hash de revizuire? Pentru că trebuie să începem sesiunea noastră interactivă Rebase la comiterea părintelui colegului nostru defect.

În al doilea rând, pentru ce este opțiunea --autosquash ? Ne ia multă muncă de pe umeri! În fereastra editorului care se deschide acum, totul este deja pregătit pentru noi:

Fereastra sesiune interactivă Rebase
Fereastra de sesiune interactivă Rebase (previzualizare mare)

Datorită opțiunii --autosquash , Git a făcut deja munca grea pentru noi:

  1. Acesta a marcat micul nostru angajament de band-aid cu cuvântul cheie de acțiune fixup . În acest fel, Git îl va combina cu commit-ul direct de mai sus și apoi îl va renunța.
  2. De asemenea, a reordonat liniile în consecință, mutându-ne comiterea cu band-aid direct sub comiterea pe care vrem să-l reparăm (din nou: fixup funcționează combinând comiterea marcată cu cea de mai sus !).

Pe scurt: Nu e nimic de făcut pentru noi decât să închidem fereastra!

Să aruncăm o privire finală asupra rezultatului final.

  • Commit-ul rupt anterior este remediat: acum conține modificările pe care le-am pregătit în commit-ul de band-aid.
  • Comiterea urâtă a comiterii în sine a fost eliminată: istoricul comisiilor este curat și ușor de citit - ca și cum nu s-ar fi produs nicio greșeală.
Un exemplu despre cum arată un istoric de comitere curat
Rezultatul final după folosirea instrumentului de remediere: un istoric de comitere curat! (Previzualizare mare)

A ști cum să anulezi greșelile este o superputere

Felicitări! Acum poți să-ți salvezi gâtul în multe situații dificile! Nu putem evita cu adevărat aceste situații: indiferent de cât de experimentați suntem ca dezvoltatori, greșelile sunt pur și simplu o parte din muncă. Dar acum că știi cum să le faci față, le poți face față cu o frecvență cardiacă relaxată.

Dacă doriți să aflați mai multe despre anularea greșelilor cu Git, vă pot recomanda „Trusa de prim ajutor pentru Git”, o serie de videoclipuri scurte despre exact acest subiect.

Distrează-te făcând greșeli – și, bineînțeles, anulându-le cu ușurință!