Ghidul începătorului pentru Rebasarea interactivă

La începutul acestui an am făcut pentru prima dată un rebase interactiv și am fost impresionat de ceea ce se poate face cu el. Mi s-a părut, de asemenea, puțin complexă la început. Să sperăm că acest ghid va ajuta la înlăturarea unor incertitudini în jurul ei.

De asemenea, pentru că este atât de puternic și puteți rescrie în esență istoria, un mic avertisment înainte de a începe: Există multe școli de gândire cu privire la Git și dacă rebasarea este o idee bună sau nu. Această postare nu se va scufunda în aceste discuții și este pur și simplu menită să treacă prin elementele de bază ale utilizării rebasării interactive.

TL;DR

  • Rebasarea interactivă poate fi utilizată pentru a modifica comenzi în multe moduri, cum ar fi editarea, ștergerea și strivirea.
  • Pentru a-i spune lui Git de unde să înceapă re-bazarea interactivă, utilizați SHA-1 sau indexul confirmării care precede imediat confirmarea pe care doriți să o modificați.
  • În timpul unei re-bazări interactive, când Git face o pauză la o confirmare pe care ați etichetat-o pentru a o edita, fluxul de lucru nu este diferit de un proces normal de confirmare – etapizați fișierele și apoi le confirmați. Singura diferență este că folosiți comanda git commit --amend în loc de git commit.
  • Rebazarea interactivă va crea noi SHA-1, prin urmare, este mai bine să folosiți rebazarea interactivă pe angajamentele pe care nu le-ați împins pe o ramură la distanță.

Problema

În acest exemplu, vom lucra la o situație în care am lucrat într-o ramură de caracteristici și avem câteva angajamente pe care am dori să le modificăm sau să le ștergem. Iată cum arată jurnalul nostru git:

Din jurnalul git de mai sus, iată cele două comenzi pe care dorim să le modificăm:
4a4d705 – În acest commit am comis din greșeală un conflict de fuziune
6c01350 – În acest commit am eliminat conflictul de fuziune

Ce am dori să facem este să ne întoarcem în timp la 4a4d705, să eliminăm conflictul de fuziune din commit, apoi să ștergem 6c01350, deoarece conflictul de fuziune este rezolvat și nu mai avem nevoie de acest commit. Aceasta va fi o îmbunătățire a istoricului nostru de comenzi din două motive:

  1. Nu vom mai avea comenzi rupte (conflicte de fuziune)
  2. Vom avea doar comenzi semnificative, fără comenzi legate doar de repararea unui conflict de fuziune ratat

Soluția

Această situație este un bun candidat pentru rebasarea interactivă. Scott Chacon, în cartea sa Pro Git, descrie rebasarea interactivă după cum urmează: „Uneori, lucrul reparat … nu poate fi modificat la comiterea nu tocmai perfectă pe care o repară, deoarece acel comitet este îngropat adânc într-o serie de patch-uri. Exact pentru asta este rebaza interactivă: folosiți-o după o mulțime de , rearanjând și editând comenzi și strivind mai multe comenzi într-una singură.”

Ce comenzi dorim să modificăm?

Pentru a începe o rebaza interactivă, trebuie să-i spunem lui Git ce comenzi dorim să modificăm. Facem acest lucru făcând referire la commit-ul imediat anterior celui mai timpuriu commit pe care dorim să-l modificăm. Sau, mai simplu spus, facem referire la „ultimul commit pe care dorim să îl păstrăm așa cum este”, conform lui Scott Chacon.

Să ne uităm la exemplul nostru pentru a înțelege mai bine. Există două moduri de a face referire la această confirmare:
Pe SHA-1 – Ultima confirmare pe care dorim să o păstrăm as-is are un SHA-1 de 528f82epentru a putea trece acest lucru în comanda noastră interactivă rebase.
By Index – Ultima confirmare pe care dorim să o păstrăm as-is are o poziție de indexare de 3 (Git folosește indexarea bazată pe zero), astfel încât putem trece HEAD~3 în comanda noastră interactivă de rebase.

Nota – Dacă aveți doar câteva confirmări pe care să le rebazați interactiv, utilizarea indexului este probabil mai ușoară pentru majoritatea oamenilor. Cu toate acestea, dacă aveți mai multe comenzi, utilizarea SHA-1 este probabil mai ușoară, astfel încât să nu trebuiască să numărați până la capăt în jurnalul git.

Start interactive rebasing

În funcție de exemplul nostru, vom rula fie:

$ git rebase -i 528f82e

Sau

$ git rebase -i HEAD~3

Ceea ce deschide această fereastră în Vim:

Observați că editările sunt în ordinea opusă celei din git log. În git log, cea mai recentă confirmare este în partea de sus. În această vizualizare, cea mai recentă confirmare este în partea de jos. De asemenea, observați că comentariile de mai jos oferă o listă utilă a comenzilor valide pe care le putem folosi la fiecare commit.

Dacă nu cunoașteți Vim, dați click pe fiecare cuvânt pick pe care doriți să-l editați și apoi apăsați tasta <i> (pentru modul de inserție). După ce ați terminat de scris, apăsați tasta <esc> pentru a ieși din modul inserare.

În exemplul nostru, am schimbat comanda în edit pentru commit-ul pe care dorim să-l modificăm și am schimbat comanda în drop pentru commit-ul pe care dorim să-l ștergem. Apoi executăm :wq pentru a salva și ieșim din fereastra Vim.

Modificați confirmarea

Înapoi în terminal vedem acest mesaj:

Este logic că suntem opriți la 4a4d705. Acesta este cel mai vechi commit din seria de commit-uri pe care dorim să le modificăm. Vom începe cu această confirmare și vom trece prin fiecare confirmare până la cea mai recentă.

Ca un memento, 4a4d705 a fost confirmarea cu conflictul de fuziune pe care am comis-o din greșeală. Când deschidem editorul nostru, vedem conflictul de fuziune acolo:

Așa că am rezolvat conflictul de fuziune în fișier, dar ce facem acum? În caz de îndoială, git status:

Fierbinte! Acest lucru este de fapt util. Vedem că suntem în prezent în curs de editare 4a4d705 și vedem următoarele două comenzi asupra cărora se va acționa după aceasta.

Restul mesajului ne explică un flux de lucru familiar. Git ne spune că dacă dorim să modificăm confirmarea pe care o executăm git commit --amend. Acest lucru va acționa în esență ca git commit obișnuit pe care îl folosim într-un flux de lucru normal. În partea de jos a acestui mesaj vedem că fișierul nostru a fost modificat, reflectând modificările pe care tocmai le-am făcut pentru a elimina conflictul de fuziune. Trebuie să etapizăm fișierul înainte de a-l confirma. Acest lucru nu diferă cu nimic de un flux de lucru normal.

Nu facem decât git add tempChanger.js pentru a pune în scenă fișierul modificat și apoi git commit --amend pentru a confirma fișierul pus în scenă! Acest lucru va deschide acum din nou o fereastră Vim cu mesajul de confirmare:

Potem fie să modificăm mesajul de confirmare, fie să îl lăsăm așa cum este. Să alegem să păstrăm mesajul de confirmare la fel și vom tasta :wq pentru a salva și a ieși din fereastră.

Am editat acum vechea noastră confirmare. Și acum ce facem? Executați git status:

Continuă rebase interactivă

Nu mai avem nimic de modificat în commit, așa că să continuăm!

Executăm git rebase --continue și vedem următorul mesaj:

Woah, am terminat? Dar cum rămâne cu celelalte două comenzi? Ei bine, următorul commit la care s-a acționat a fost 6c01350. Această confirmare am marcat-o pentru a fi ștearsă (drop) atunci când am început rebase-ul interactiv. Git l-a șters automat și a trecut la următorul commit, 41aa9d2. Acesta nu a fost modificat niciodată în cadrul rebase-ului interactiv inițial. Comanda sa implicită a fost pick, ceea ce înseamnă că acest commit va fi utilizat. Git a aplicat acel commit și, deoarece acesta a fost ultimul commit, rebase-ul interactiv s-a finalizat.

Rețineți, dacă am fi avut mai multe commit-uri de modificat, am fi trecut pur și simplu la următorul commit și am fi început procesul de modificare a acestuia, așa cum am făcut mai sus. Ciclul continuă până când nu mai există niciun commit.

Botonul de ejectare

Este demn de remarcat faptul că, dacă în orice moment al rebase-ului nostru interactiv dăm lucrurile peste cap și nu știm cum să le reparăm, putem oricând să renunțăm. În orice moment putem rula git rebase --abort în terminal și rebaza interactivă va fi întreruptă fără ca modificările să fie salvate. Atunci va trebui să începem din nou rebaza interactivă.

După rebaza interactivă

Jurnalul nostru git arată acum așa:

Vă veți da seama că s-au schimbat câteva lucruri față de momentul în care am început rebaza interactivă:

  • Nu mai avem confirmarea 6c01350 cu mesajul de confirmare „Remove merge conflict”. Aceasta este confirmarea pe care am eliminat-o în rebaza noastră interactivă.
  • Commiterea noastră pe care am editat-o, 4a4d705, are un SHA-1 diferit, 2b7443d.
  • Cea mai recentă confirmare din jurnalul nostru git original, 41aa9d2, are, de asemenea, un nou SHA-1, 2b95e92. Această confirmare nu a fost modificată, ci a fost pur și simplu aplicată la confirmarea dinaintea ei 2b7443d.

Efecte secundare ale rebasării interactive

Pentru cele mai recente două confirmări din jurnalul nostru git, deoarece au SHA-1-uri noi, Git le vede ca fiind confirmări complet noi. Acest lucru este valabil chiar și pentru ultima noastră confirmare, 2b95e92, unde nici mesajul de confirmare și nici fișierele nu s-au schimbat deloc. Acest lucru aduce în discuție un punct important cu rebasarea interactivă: Dacă modificați o confirmare, acea confirmare și toate confirmările succesive vor avea SHA-1-uri noi.

Acest lucru nu va afecta nimic dacă confirmările pe care le-ați modificat nu au fost împinse pe o ramură la distanță. Cu toate acestea, dacă ați finalizat, de fapt, un rebase interactiv asupra unor comisioane care au fost deja împinse către o ramură la distanță și apoi ați împins din nou ramura dvs. veți vedea:

Tehnic, ați putea ocoli acest lucru folosind git push --force, dar acest lucru este foarte periculos. În cazul în care ramura de la distanță are angajamente de la alte persoane, dar ramura dvs. locală nu are încă acele angajamente, veți șterge efectiv angajamentele lor.

O altă soluție este să folosiți git push --force-with-lease, care va modifica doar angajamentele dvs., dar nu și angajamentele aparținând altora, deși acest lucru poate fi, de asemenea, problematic. De exemplu, dacă un alt dezvoltator are deja acele comitete care au primit noile SHA-1 pe ramura lor locală, atunci când vor trage ramura de la distanță, vor avea conflicte de fuziune cu fiecare dintre aceste comitete.

Când să folosiți --force-with-lease depășește scopul acestui articol de blog, dar ar fi bine să vă consultați cu alți membri ai echipei dvs. înainte de a face acest lucru. Puteți citi mai multe despre git push --force-with-lease aici.

Cel mai important lucru pe care îl puteți reține din această secțiune este că este mult mai ușor și mai sigur să folosiți rebasarea interactivă în cazul comenzilor care nu au fost încă împinse pe o ramură la distanță.

Scris de Blake DeBoer. Postat inițial pe Dev.to

Senior, Lead, sau Principal developer în NYC? Stride face angajări! Doriți să vă ridicați nivelul echipei tehnice? Vedeți cum o facem noi! www.stridenyc.com

.

Tags

Înscrieți-vă la Hacker Noon

Creați-vă un cont gratuit pentru a vă debloca experiența de lectură personalizată.

Leave a Reply