În fluxul de lucru Git fundamental, dezvoltați o nouă caracteristică într-o ramură tematică dedicată, apoi îmbinați-o într-o ramură de producție odată terminată. Asta face git merge
o unealtă integrală pentru combinarea ramurilor. Cu toate acestea, nu este singura ofertă oferită de Git.
Ca alternativă la scenariul de mai sus, puteți combina ramurile cu git rebase
comanda. În loc să leagă ramurile împreună cu o comitere de îmbinare, rebasingul mișcă întreaga ramură a elementului până la vârful lui maestru
așa cum se arată mai jos.
Aceasta are același scop ca și git merge
, integrarea comitetelor de la diferite ramuri. Dar există două motive pentru care am putea dori să optăm pentru o renunțare la o fuzionare:
În acest tutorial, vom explora aceste două cazuri comune de utilizare a git rebase
. Din păcate, beneficiile git rebase
veniți la un compromis. Dacă este folosit incorect, poate fi una dintre cele mai periculoase operații pe care le puteți efectua într-un depozit Git. Deci, vom fi, de asemenea, o privire atentă la pericolele de rebasing.
Acest tutorial presupune că sunteți familiarizat cu comenzile de bază Git și cu fluxurile de colaborare. Ar trebui să fiți pregătiți confortabil și să faceți instantanee, să dezvoltați trăsături în ramuri izolate, să îmbinați sucursalele împreună și să împingeți / trageți sucursalele în / din depozitele de la distanță.
Primul caz pe care îl vom explora implică o istorie divergentă a proiectului. Luați în considerare un depozit în care sucursala dvs. de producție a avansat în timp ce dezvoltați o caracteristică:
Pentru a renova caracteristică
ramificați pe maestru
ramură, ați rula următoarele comenzi:
git checkout caracteristică git rebase master
Aceasta transplantează caracteristică
ramură de la locația sa actuală până la vârful maestru
ramură:
Există două scenarii în care doriți să faceți acest lucru. În primul rând, dacă caracteristica se bazează pe noul angajament maestru
, acum avea acces la ele. În al doilea rând, în cazul în care caracteristica a fost complet, ar fi acum setat pentru o îmbinare rapidă înainte în maestru
. În ambele cazuri, rebasingul are ca rezultat o istorie liniară, în timp ce git merge
ar duce la comiteri de fuziune inutile.
De exemplu, luați în considerare ceea ce s-ar întâmpla dacă integrați angajamentele din amonte cu o fuziune în loc de o rebază:
git checkout caracteristică git merge master
Acest lucru ne-ar fi dat un angajament suplimentar de îmbinare în caracteristică
ramură. Mai mult, acest lucru s-ar întâmpla de fiecare dată când ați vrut să încorporați angajamentele din amonte în caracteristica dvs. În cele din urmă, istoricul proiectelor dvs. va fi îngrădit de angajamente de îmbinare fără sens.
Același beneficiu poate fi văzut și atunci când fuzionează în cealaltă direcție. Fără o rebază, integrarea finalizată caracteristică
ramificați în maestru
necesită o comitere de îmbinare. Deși aceasta este de fapt o comitere de fuziune semnificativă (în sensul că reprezintă o caracteristică completă), istoricul rezultat este plin de furci:
Când rebasezi înainte de a fuziona, Git este capabil să avanseze rapid maestru
la vârful lui caracteristică
. Veți găsi o poveste liniară despre modul în care proiectul dvs. a progresat în git log
ieșire - se angajează caracteristică
sunt bine grupate împreună în partea de sus a angajamentelor maestru
. Acest lucru nu este neapărat cazul când ramurile sunt legate împreună cu o comitere de îmbinare.
Când alergi git rebase
, Git ia fiecare comitere în ramură și le mută, câte unul, pe noua bază. Dacă oricare dintre aceste comitete modifică aceeași linie (linii) de cod ca și comitetele în amonte, va duce la un conflict.
git merge
vă permite să rezolvați toate conflictele de ramură la sfârșitul îmbinării, care este unul dintre scopurile primare ale unui comitet de îmbinare. Cu toate acestea, funcționează un pic diferit când faceți rebrand. Conflictele sunt rezolvate pe baza unei comiteri. Astfel, dacă git rebase
găsește un conflict, va opri procedura de rebază și va afișa un mesaj de avertizare:
Conectarea automată readme.txt CONFLICT (conținut): Merge conflictul în readme.txt Nu a reușit să fuzionezi în modificări ... Când ai rezolvat această problemă, rulați "git rebase --continue". Dacă preferați să săriți acest patch, executați în schimb "git rebase - skip". Pentru a verifica ramura originală și a renunța la rebasing, rulați "git rebase --abort".
Din punct de vedere vizual, arată istoricul proiectului când git rebase
întâmpină un conflict:
Conflictele pot fi inspectate prin difuzare git status
. Rezultatul arată foarte similar cu un conflict de îmbinare:
Căile neregulate: (utilizați "git reset HEAD... "la unstage) (utilizați" git add ... pentru a marca rezoluția) ambele modificate: readme.txt nu s-au adăugat modificări la comitere (utilizați "git add" și / sau "git commit -a")
Pentru a rezolva conflictul, deschideți fișierul în conflict (readme.txt în exemplul de mai sus), găsiți liniile afectate și editați-le manual la rezultatul dorit. Apoi, spuneți lui Git că conflictul este rezolvat prin stadializarea fișierului:
git adăugați readme.txt
Rețineți că acesta este exact același mod în care marcați a git merge
conflict ca rezolvat. Dar nu uitați că sunteți în mijlocul unei rebade - nu doriți să uitați de restul angajamentelor care trebuie mutate. Ultimul pas este să-i spunem lui Git să termine rebalizarea cu --continua
opțiune:
git rebase - continuă
Aceasta va muta restul angajamentelor, una câte una, iar dacă apar alte conflicte, va trebui să repetați acest proces din nou.
Dacă nu doriți să rezolvați conflictul, puteți opta pentru unul dintre ele --ocolire
sau --avorta
steaguri. Acesta din urmă este deosebit de util dacă nu aveți nicio idee despre ceea ce se întâmplă și doriți doar să reveniți la siguranță.
# Ignorați comitetul care a provocat conflictul git rebase - skip # Abandonați întreaga rebază și reveniți la desenul de bază git rebase --abort
Până acum, am folosit doar git rebase
pentru a muta ramurile, dar este mult mai puternic decât asta. Prin trecerea lui -eu
flag, puteți începe o sesiune de rebazare interactivă. Rebasingul interactiv vă permite să definiți exact modul în care fiecare comitet va fi mutat la noua bază. Acest lucru vă oferă posibilitatea de a curăța istoricul unei caracteristici înainte de al împărtăși cu alți dezvoltatori.
De exemplu, să presupunem că ați terminat lucrul la dvs. caracteristică
ramură și sunteți gata să o integrați maestru
. Pentru a începe o sesiune de rebazare interactivă, executați următoarea comandă:
git checkout caracteristică git rebase -i master
Aceasta va deschide un editor care conține toate comitetele din caracteristică
care urmează să fie mutate:
selectați 5c43c2b [Descrierea celei mai vechi comite] alege b8f3240 [Descriere pentru cel de-al doilea cel mai vechi comite] pick c069f4a [Descriere pentru cel mai recent angajament]
Această listă definește ce caracteristică
ramura va arata ca dupa rebase. Fiecare linie reprezintă un comitet și alege
înainte de fiecare comitet de hash, definește ce se va întâmpla în timpul rebasei. Rețineți că comitetele sunt listate de la cele mai vechi la cele mai recente. Modificând această listă, obțineți un control complet asupra istoricului proiectului.
Dacă doriți să modificați ordinea comitetelor, reordonați pur și simplu liniile. Dacă doriți să modificați mesajul unui comitet, utilizați reformularea
comanda. Dacă doriți să combinați două comitete, schimbați alege
comanda pentru suc de fructe
. Aceasta va schimba toate schimbările din acea comitet în cea de deasupra. De exemplu, dacă ați răsturnat al doilea comitet în lista de mai sus, caracteristică
ramura arata ca dupa salvarea si inchiderea editorului:
Editați | ×
comanda este deosebit de puternică. Când ajunge la comitetul specificat, Git va întrerupe procedura de rebalizare, la fel ca atunci când întâmpină un conflict. Aceasta vă oferă posibilitatea de a modifica conținutul comitetului git commit - amend
sau chiar să adăugați mai multe angajamente cu standardul adăugați git
/git comite
comenzi. Orice nouă comitet pe care îl adăugați va face parte din noua ramură.
Rebasingul interactiv poate avea un impact profund asupra fluxului dvs. de lucru pentru dezvoltare. În loc să vă faceți griji pentru a vă împărți modificările în angajamente încapsulate, vă puteți concentra pe scrierea codului. Dacă ați ajuns să comiteți ceea ce ar trebui să fie o singură modificare în patru instantanee separate, atunci aceasta nu este o problemă-rescrie istoria cu git rebase -i
și le împușcați pe toate într-o singură comisie semnificativă.
Acum că ai o înțelegere git rebase
, putem vorbi despre când să nu o folosim. Pe plan intern, rebasingul nu duce, de fapt, la o nouă filială. În schimb, creează comitete noi, care conțin modificările dorite. Cu acest lucru este minte, rebasing este mai bine vizualizat ca următoarele:
După rebază, se angajează caracteristică
vor avea diferite hash-uri de comitere. Asta înseamnă că nu am repoziționat doar o ramură - am redactat literalmente istoricul proiectului nostru. Acesta este un efect secundar foarte important git rebase
.
Când lucrați singur pe un proiect, rescrierea istoriei nu este o afacere mare. Cu toate acestea, de îndată ce începeți să lucrați într-un mediu colaborativ, acesta poate deveni foarte periculos. Dacă rescrieți comitetele pe care le utilizează alți dezvoltatori (de ex., Se angajează pe maestru
ramura), se va părea că acele comitete au dispărut următoarea dată când încearcă să-ți tragă lucrarea. Acest lucru are ca rezultat un scenariu confuz, dificil de recuperat.
În acest sens, nu trebuie să refaceți niciodată comitetele care au fost împinse într-un depozit public dacă nu sunteți sigur că nimeni nu și-a fondat munca.
Acest tutorial a prezentat cele mai frecvente două cazuri de utilizare git rebase
. Am vorbit foarte mult despre mutarea ramurilor în jurul valorii de, dar rețineți că rebasing-ul este de fapt despre controlul istoricul proiectului dumneavoastră. Puterea de rescriere se obligă după ce vă eliberează să vă concentrați asupra sarcinilor de dezvoltare, în loc să vă descompuneți lucrarea în snapshot-uri izolate.
Rețineți că rebalizarea este o adăugare complet opțională în caseta de instrumente Git. Încă poți să faci tot ce ai nevoie cu bătrânul simplu git merge
comenzi. Într-adevăr, acest lucru este mai sigur, deoarece evită posibilitatea rescrierii istoriei publice. Totuși, dacă înțelegeți riscurile, git rebase
poate fi o modalitate mult mai curată de a integra ramurile comparativ cu comitetele de fuziune.