Git Succinct Sucursale

Filialele înmulțesc funcționalitatea de bază oferită de comitete, permițând utilizatorilor să-și schimbe istoricul. Crearea unei noi sucursale este asemănătoare cu solicitarea unui nou mediu de dezvoltare, completat cu un director de lucru izolat, zona de așteptare și istoricul proiectului.


Dezvoltarea ramificată de bază

Acest lucru vă oferă aceleași liniște ca și comiterea unei copii "sigure" a proiectului dvs., dar acum aveți capacitatea suplimentară de a lucra în mai multe variante în același timp. Filialele permit a fluxul de lucru neliniar-capacitatea de a dezvolta caracteristici independente în paralel. Așa cum vom descoperi mai târziu, un flux de lucru neliniar este un precursor important al naturii distribuite a modelului de colaborare al lui Git.

Spre deosebire de SVN sau CVS, implementarea ramurii Git este incredibil de eficientă. SVN permite filialele prin copierea întregului proiect într-un folder nou, la fel cum ați proceda fără software de control al reviziilor. Acest lucru face ca fuzionarea să fie neclară, predispusă la erori și lentă. În schimb, ramurile Git sunt pur și simplu un indicator al unei comiteri. Deoarece acestea lucrează la nivel de comitet în loc direct la nivelul fișierului, ramurile Git fac mult mai ușor combinarea istoriilor divergente. Acest lucru are un impact dramatic asupra fluxurilor de lucru ramificate.


Manipularea ramurilor

Git separă funcționalitatea ramificațiilor în câteva comenzi diferite. git ramură comanda este utilizată pentru înregistrarea, crearea sau ștergerea sucursalelor.

Listarea filialelor

În primul rând, va trebui să puteți vizualiza sucursalele existente:

 git ramură

Aceasta va afișa toate sucursalele dvs. actuale, împreună cu un asterisc în dreptul celui care este "verificat" (mai târziu, mai târziu):

 * master-some-feature rapid-bug-fix

maestru ramură este ramura implicită a lui Git, care este creată cu prima comitere în orice depozit. Mulți dezvoltatori folosesc această ramură drept "principala" istorie a proiectului - o ramură permanentă care conține toate schimbările majore pe care le trece.

Crearea de filiale

Puteți crea o nouă filă prin trecerea numelui filialei la același git ramură comanda:

 git ramură 

Acest lucru creează un indicator pentru curent CAP, dar nu nu treceți la noua ramură (veți avea nevoie Git checkout pentru asta). Imediat după ce ați solicitat o nouă filială, magazia dvs. va arăta mai degrabă după cum urmează.


Crearea unei noi filiale

Sucursala dvs. curentă (maestru) și noua ramură (unele feature), ambele fac referire la acelasi angajament, dar orice nou angajat pe care il inregistrati va fi exclusiv pentru sucursala actuala. Din nou, aceasta vă permite să lucrați în paralel cu caracteristici independente, menținând în același timp istorii sensibile. De exemplu, dacă sucursala dvs. a fost unele feature, istoria dvs. ar arăta după cum urmează după ce ați făcut un instantaneu.


Angajarea pe unele feature ramură

Noul CAP (marcată de comiterea evidențiată) există numai în unele feature ramură. Nu va apărea în jurnalul de ieșire din maestru, și nici modificările sale nu vor apărea în directorul de lucru după ce ați făcut check out maestru.

De fapt, puteți vedea noua ramură în baza de date internă prin deschiderea fișierului .git / ref / capete /. Fișierul conține ID-ul comitetului de referință și este singura definiție a unei sucursale Git. Acesta este motivul pentru care ramurile sunt atât de ușoare și ușor de gestionat.

Ștergerea sucursalelor

În cele din urmă, puteți șterge sucursalele prin -d steag:

 git branch -d 

Dar, dedicarea lui Git de a nu-ți pierde niciodată munca nu-l împiedică să înlăture ramurile cu comitete neschimbate. Pentru a forța ștergerea, utilizați -D în locul:

 git ramură -D 

Schimbările neschimbate vor fi pierdute, deci fii foarte atent cu această comandă.


Verificați filialele

Desigur, crearea ramurilor este inutilă fără capacitatea de a comuta între ele. Git numește această "verificare" a unei filiale:

 Git checkout 

După verificarea ramurii specificate, directorul dvs. de lucru este actualizat pentru a se potrivi cu comitetul specificat al ramurii. In plus CAP este actualizat pentru a indica noua ramificație și toate comitetele noi vor fi stocate pe noua ramură. Vă puteți gândi să verificați o sucursală ca trecerea la un nou dosar de proiect - cu excepția faptului că va fi mult mai ușor să trageți modificările înapoi în proiect.


Verificați diferite ramuri

Având în vedere acest lucru, este de obicei o idee bună să aveți a curat înainte de a verifica o ramură. Un director curat există atunci când nu există modificări neangajate. Dacă nu este cazul, Git checkout are potențialul de a vă suprascrie modificările.

Ca și în cazul unei revizuiri "sigure", sunteți liber să experimentați o nouă filială fără teama de a distruge funcționalitatea existentă. Dar, acum aveți o istorie dedicată cu care să lucrați, astfel încât să puteți înregistra progresul unui experiment folosind același lucru adăugați git și git comite comenzi de la mai devreme în carte.


Dezvoltarea în paralel a mai multor caracteristici

Această funcție va deveni și mai puternică odată ce vom învăța cum să îmbinam istoriile divergente înapoi în ramura "principală" (de ex., maestru). O să ajungem la asta într-un moment, dar mai întâi, există un caz de utilizare important Git checkout care trebuie să fie luate în considerare ...

Personalizate HEADs

Git vă permite, de asemenea, să utilizați Git checkout cu etichete și coduri de comitet, dar acest lucru vă pune într-un stare detașată HEAD. Aceasta înseamnă că nu mai sunteți pe o ramură - vizionați direct o comitet.


Verificarea unei comitete vechi

Puteți să vă uitați în jur și să adăugați comitete noi, ca de obicei, dar din moment ce nu există nici o sucursală care să indice adăugările, veți pierde toate lucrările dvs. de îndată ce reveniți la o filială reală. Din fericire, crearea unei noi sucursale într-o detașată CAP starea este destul de ușoară:

 git checkout -b 

Aceasta este o scurtătură pentru git ramură urmat de Git checkout . După care veți avea o nouă referință ramificată strălucitoare la fostul detașat CAP. Aceasta este o procedură foarte utilă pentru a elimina experimentele de la vechile revizuiri.


Îmbinarea filialelor

Îmbinarea este procesul de tragere a comitetelor de la o ramură la alta. Există multe modalități de combinare a sucursalelor, dar scopul este întotdeauna să împărtășiți informații între sucursale. Acest lucru face ca una dintre cele mai importante caracteristici ale Git să fie îmbinată. Cele două metode de îmbinare cele mai comune sunt:

  • Fluxul "rapid înainte" merge
  • Fluxul "3-way"

Ambele utilizează aceeași comandă, git merge, dar metoda este determinată automat pe baza structurii istoriei dvs. In fiecare caz, ramura în care doriți să fuzionați trebuie să fie verificată, iar ramura țintă va rămâne neschimbată. Următoarele două secțiuni prezintă două posibile scenarii de fuziune pentru următoarele comenzi:

 git checkout master git îmbină câteva funcții

Din nou, aceasta combină funcția unele feature ramură în maestru ramură, lăsându-l pe fostul neatins. De obicei, ați rula aceste comenzi după ce ați terminat o caracteristică și doriți să o integrați în proiectul stabil.

Derulare rapidă înainte

Primul scenariu arată astfel:


Înainte de îmbinarea rapidă înainte

Am creat o sucursală pentru a dezvolta o nouă caracteristică, a adăugat două comitete și acum este gata să fie integrată în baza de cod principală. În loc să rescrii cele două comitete care lipsesc de la maestru, Git poate să "avanseze rapid" maestru indicatorul sucursalei pentru a se potrivi locației unele feature.


După îmbinarea rapidă înainte

După fuzionare, maestru ramura conține toată istoria dorită, iar ramura de caracteristică poate fi ștearsă (dacă nu doriți să continuați să dezvoltați). Acesta este cel mai simplu tip de îmbinare.

Desigur, am fi putut face cele două comitete direct pe maestru ramură; totuși, folosirea unei ramuri de funcții dedicate ne-a oferit un mediu sigur pentru a experimenta codul nou. Dacă nu s-a dovedit a fi corect, am fi putut șterge pur și simplu ramificația (spre deosebire de resetare / revenire). Sau, dacă am adăugat o grămadă de comitete intermediare care conțineau cod rupt, am putea să-l curățăm înainte de a le uni maestru (vezi Rebasing below). Pe măsură ce proiectele devin mai complicate și dobândesc mai mulți colaboratori, acest tip de dezvoltare ramificată face Git un instrument organizațional fantastic.

3-Way merge

Dar nu toate situațiile sunt destul de simple pentru o comitere rapidă. Rețineți că principalul avantaj al ramurilor este capacitatea de a explora simultan multe linii independente de dezvoltare. În consecință, veți întâlni adesea un scenariu care arată după cum urmează:


Înainte de îmbinarea în trei direcții

Acest lucru a început ca o îmbinare rapidă înainte, dar am adăugat o comitet la maestru în timp ce noi eram încă în curs de dezvoltare unele feature. De exemplu, am fi putut să nu mai lucrăm la această caracteristică pentru a repara o eroare sensibilă la timp. Bineînțeles, bug-fix-ul ar trebui să fie adăugat la depozitul principal cât mai curând posibil, așa că vom rezista în scenariul prezentat mai sus.

Îmbinând suita de elemente în maestru în acest context rezultă o îmbinare cu 3 căi. Acest lucru este realizat folosind aceleași comenzi ca și fuzionarea rapidă din secțiunea anterioară.


După îmbinarea în trei direcții

Git nu poate răspunde rapid maestru pointer la unele feature fără a se retrage. În schimb, generează un nou îmbinare comite care reprezintă imaginea combinată a ambelor ramuri. Rețineți că această nouă comitet are Două părintele se angajează, oferindu-i acces la ambele istorii (într-adevăr, alergând git log după ce fuzionarea în trei direcții arată comitete de la ambele ramuri).

Numele acestui algoritm de îmbinare provine de la metoda internă utilizată pentru a crea comitetul de îmbinare. Git se uită la Trei se angajează să genereze starea finală a fuzionării.

Îmbunătățiți conflictele

Dacă încercați să combinați două ramuri care fac modificări diferite ale aceleiași porțiuni de cod, Git nu va ști ce versiune să utilizeze. Aceasta se numește a combinați conflictul. Evident, acest lucru nu se poate întâmpla niciodată în timpul unei fuziuni rapide. Când Git întâlnește un conflict de fuzionare, veți vedea următorul mesaj:

 Auto-fuziune index.html CONFLICT (conținut): Merge conflictul în  Amestecarea automată eșuată; remediați conflictele și apoi angajați rezultatul.

În loc să adăugați automat comitetul de fuziune, Git se oprește și vă întreabă ce să faceți. Alergare git status în această situație se va întoarce ceva de genul:

 # Pe maestru de ramură # Trasee dezmembrate: # # ambele modificate: 

Fiecare fișier cu un conflict este stocat în secțiunea "Căi neschimbate". Git adnotă aceste fișiere pentru a vă arăta conținutul din ambele versiuni:

 <<<<<<< HEAD This content is from the current branch. ======= This is a conflicting change from another branch. >>>>>>> ceva-caracteristică

Partea din fața instanței ======= este din maestru ramură, iar restul este din ramura pe care încercați să o integrați.

Pentru a rezolva conflictul, eliminați <<<<<<, =======, și >>>>>>> notație și modificați codul la ceea ce doriți să păstrați. Apoi, spune-i lui Git că ai terminat de rezolvat conflictul cu adăugați git comanda:

 adăugați git 

Asta e corect; tot ce trebuie să faceți este să așezați fișierul în conflict pentru ao marca ca rezolvată. În cele din urmă, finalizați îmbinarea în trei direcții generând comitetul de îmbinare:

 git comite

Mesajul jurnal este însămânțat cu o notificare de îmbinare împreună cu o listă de "conflicte", care poate fi utilă în special atunci când încercați să aflați unde a avut loc ceva în proiect.

Și asta e tot ce trebuie să fuzionăm în Git. Acum, că avem o înțelegere a mecanismelor din spatele ramurilor Git, putem analiza în profunzime modul în care utilizatorii veterani Git folosesc ramurile în fluxul lor de lucru de zi cu zi.


Fluxuri de lucru ramificate

Fluxurile de lucru prezentate în această secțiune reprezintă semnul distinctiv al controlului reviziilor bazate pe Git. Natura ușoară și ușor de îmbinat a implementării ramurii Git le face unul dintre cele mai productive instrumente din arsenalul de dezvoltare software.

Toate fluxurile de lucru ramificate se învârt în jurul valorii de git ramură, Git checkout, și git merge comenzile prezentate mai devreme în acest capitol.

Tipuri de sucursale

Adesea, este util să acordați o semnificație specială diferitelor ramuri pentru a organiza un proiect. Această secțiune prezintă cele mai frecvente tipuri de ramuri, dar rețineți că aceste distincții sunt pur superficiale - la Git, o ramură este o ramură.

Toate filialele pot fi clasificate ca fiind permanent ramuri sau subiecte ramase. Primul conține istoricul principal al unui proiect (de ex., maestru), în timp ce acestea din urmă sunt sucursale temporare folosite pentru implementarea unui anumit tip subiect, apoi aruncate (de ex., unele feature).

Sucursale permanente

Ramurile permanente sunt sângele vieții oricărui depozit. Acestea conțin fiecare punct important al unui proiect software. Majoritatea dezvoltatorilor folosesc maestru exclusiv pentru codul stabil. În aceste fluxuri de lucru, tu nu să se angajeze direct pe maestru-este doar o sucursală de integrare pentru caracteristici completate care au fost construite în ramuri de teme dedicate.

În plus, mulți utilizatori adaugă un al doilea strat de abstractizare într-o altă ramură de integrare (convențional numită dezvolta, deși orice nume va fi suficient). Acest lucru eliberează maestru ramură pentru într-adevăr codul stabil (de ex., angajamentele publice) și utilizările dezvolta ca ramură de integrare internă pentru a se pregăti pentru eliberarea publică. De exemplu, următoarea diagramă prezintă câteva caracteristici integrate în dezvolta, apoi o fuziune unică, finală maestru, care simbolizează o eliberare publică.


Utilizarea maestru ramură exclusiv pentru eliberarea publică

Subiecte ramase

Ramurile de subiecte se încadrează în general în două categorii: filiale și rapoarte de remediere rapidă. Ramurile de funcții sunt ramuri temporare care încorporează o nouă caracteristică sau un refactor, protejând proiectul principal de codul netestat. Ele provin de obicei dintr-o altă ramură de caracteristici sau dintr-o ramură de integrare, dar nu ramura "super stabilă".


Dezvoltarea unei trăsături într-o ramură izolată

Rapoartele cu replici rapide sunt similare în natură, dar provin din ramura publică de eliberare (de ex., maestru). În loc de a dezvolta noi caracteristici, acestea sunt pentru patching rapid linia principală de dezvoltare. De obicei, aceasta înseamnă remedierea erorilor și alte actualizări importante care nu pot aștepta până la următoarea lansare majoră.


patching maestru cu o ramură de remediere rapidă

Din nou, semnificațiile atribuite fiecăreia dintre aceste ramuri sunt pur convenționale - Git nu vede nicio diferență între maestru, dezvolta, caracteristici și remedierile rapide. În acest sens, nu vă fie frică să le adaptați la scopurile proprii. Frumusețea lui Git este flexibilitatea sa. Când înțelegeți mecanica din spatele ramurilor Git, este ușor să creați fluxuri de lucru noi care să se potrivească proiectului și personalității dvs..


Rebasing

Rebasing este procesul de mutare a unei sucursale la o nouă baza. Capacitățile de reabilitare ale Git fac ramurile mai flexibile, permițând utilizatorilor să-și organizeze manual sucursalele. Ca fuzionarea, git rebase cere ca ramura să fie verificată și ia noua bază ca argument:

 git checkout unele-caracteristica git rebase maestru

Aceasta mișcă întregul unele feature ramificați pe vârful lui maestru:


Rebasing unele feature pe maestru ramură

După refacere, ramura de caracteristică este a extensie liniară de maestru, care este o modalitate mult mai curată de a integra schimbările de la o ramură la alta. Comparați această istorie liniară cu o îmbinare de maestru în unele feature, care are ca rezultat exact aceeași bază de cod în imaginea finală:


integrarea maestru în unele feature cu o îmbinare cu 3 căi

Din moment ce istoria a diferit, Git trebuie să utilizeze o comitet de îmbinare suplimentară pentru a combina sucursalele. A face acest lucru de multe ori pe parcursul dezvoltării unei caracteristici de lungă durată poate duce la o istorie foarte murdară.

Aceste comitete suplimentare de fuziune sunt inutile - există doar pentru a trage schimbări maestru în unele feature. În mod tipic, veți dori ca fuzionarea să se angajeze însemna ceva, cum ar fi finalizarea unei noi caracteristici. Acesta este motivul pentru care mulți dezvoltatori aleg să facă schimbări cu git rebase, deoarece are ca rezultat o istorie complet liniară în ramura caracteristică.

Rebasing interactiv

Rebasingul interactiv merge cu un pas mai departe și vă permite Schimbare se angajează în timp ce le deplasați la noua bază. Puteți specifica o rebază interactivă cu -eu steag:

 git rebase -i master

Acest lucru cuprinde un editor de text, cu un rezumat al fiecărui comitet în ramura de caracteristici, împreună cu o comandă care determină Cum ar trebui transferat la noua bază. De exemplu, dacă aveți două comitete pe o sucursală de caracteristici, puteți specifica o rebază interactivă, după cum urmează:

 alege 58dec2a În primul rând se angajează pentru squash-ul de noi caracteristici 6ac8a9f Al doilea angajament pentru o nouă caracteristică

Valoarea implicită alege comanda mută prima comitere la noua bază ca și cea normală git rebase, dar apoi suc de fructe comanda îi spune lui Git să combine al doilea comitet cu cel precedent, astfel încât să încheiați cu un comitet care conține toate modificările:


Interactiv redeschiderea unele feature ramură

Git oferă mai multe comenzi de rebazare interactive, fiecare dintre acestea fiind rezumate în secțiunea de comentarii a listei de configurații. Punctul este rebasingul interactiv vă permite complet rescrieți istoricul unei sucursale la specificațiile dvs. exacte. Acest lucru înseamnă că puteți adăuga cât mai multe comenzi intermediare unei ramuri de funcții după cum aveți nevoie, apoi mergeți înapoi și fixați-le într-o progresie semnificativă după.

Alți dezvoltatori vor crede că sunteți un programator genial și știți exact cum să implementați întreaga caracteristică într-o singură lovitură. Acest tip de organizație este foarte important pentru a asigura că proiectele mari au o istorie navigabilă.

Rescrierea istoriei

Rebasingul este un instrument puternic, dar trebuie să fii politicos în rescrierea istoriei. Ambele tipuri de rebalizări nu sunt de fapt mișcare comitetele existente - acestea crea cele noi (marcate cu un asterisc în diagrama de mai sus). Dacă inspectați comitetele care au fost supuse unei rebate, veți observa că au coduri de identitate diferite, chiar dacă acestea reprezintă același conținut. Aceasta înseamnă rebasing distruge existente se angajează în procesul de "mișcare" a acestora.

Așa cum vă puteți imagina, acest lucru are consecințe dramatice pentru fluxurile de lucru colaborative. Distrugerea unei comitete publice (de ex maestru ramură) este ca și cum ar trebui să distrugem baza muncii tuturor celorlalți. Git nu va avea nici o idee cum să combine toate schimbările tuturor, și veți avea o mulțime de scuze de făcut. Vom analiza mai profund acest scenariu după ce vom învăța cum să comunicați cu depozitele de la distanță.

Deocamdată, respectați regula de aur a rebalizării: să nu renovați niciodată o ramură care a fost împinsă într-un depozit public.

Această lecție reprezintă un capitol din Git Succinct, o carte electronică gratuită de la echipa de la Syncfusion.

Cod