Git - dezvăluirea reinițializării misterelor

Dezvăluirea de mistere

Trei copaci

Depășirea comenzilor de resetare și checkout va fi mai ușoară dacă presupuneți că Git gestionează conținutul a trei copaci diferiți. Aici, prin "copac" se înțelege un "set de fișiere", și nu o structură specială de date. (În unele cazuri, indicele se comportă nu ca un copac, dar pentru scopurile noastre actuale este mai ușor să o reprezentăm exact așa.)







În operațiunile sale normale, Git gestionează trei copaci:

HEAD este un indicator al ramurii actuale, care, la rândul său, este un indicator al ultimului angajament făcut în această ramură. Aceasta înseamnă că HEAD va fi părintele comisiei următoare create. De regulă, cel mai simplu lucru pe care trebuie să-l luați în considerare este imaginea HEAD a ultimului dvs. angajament.

De fapt, este destul de ușor să vezi cum arată această imagine. Următoarea este un exemplu de obținere a conținutului directorului și a sumelor de control pentru fiecare fișier din HEAD:

Comenzile de pisică și ls-copac sunt comenzi "sanitare" care sunt folosite intern și nu sunt necesare pentru munca zilnică, dar ne ajută să înțelegem ce se întâmplă cu adevărat.

Indicele este următoarea comisie programată. Am menționat, de asemenea, acest concept ca fiind "zona de schimbări pregătite" Git - ce caută Git când executați git commit.

Git umple indexul cu o listă a conținutului original al tuturor fișierelor care au fost descărcate ultima dată în directorul dvs. de lucru. Apoi înlocuiți unele dintre aceste fișiere cu noile lor versiuni și comanda "git commit" convertește modificările la arborele pentru noul comitet.

Din nou, aici folosim ls-fișierele de comandă de serviciu. care vă arată ce arată indexul dvs. acum.

Din punct de vedere tehnic, indicele nu este o structură de copac, de fapt, este pus în aplicare ca un manifest aplatizat - dar pentru scopurile noastre această reprezentare va fi suficientă.

Director de lucru

În sfârșit, aveți un director de lucru. Alți doi copaci își păstrează conținutul într-un mod eficient, dar incomod, în interiorul directorului .git. Directorul de lucru le despachetează în fișiere reale, ceea ce vă ușurează să le editați. Citiți catalogul de lucru ca o cutie de nisip. unde puteți încerca modificările înainte de a se angaja la index (zona modificărilor pregătite) și apoi în istoric.

Proces tehnologic

Scopul principal al Git este de a salva instantanee ale statelor care îmbunătățesc în mod constant proiectul dvs., gestionând acești trei copaci.

Git - dezvăluirea reinițializării misterelor

Git - dezvăluirea reinițializării misterelor

În acest stadiu numai arborele director conține date.

Acum, dorim să se angajeze acest fișier, așa că folosim git add pentru a copia conținutul directorului de lucru la index.

Git - dezvăluirea reinițializării misterelor

Apoi, executam comanda git commit. care salvează conținutul indexului ca un instantaneu nemodificat, creează un obiect de comitere care indică acest instantaneu și actualizează comandantul, astfel încât să indice și această comitere.

Git - dezvăluirea reinițializării misterelor

Dacă acum executați statutul de git. atunci nu vom vedea modificări, deoarece toți cei trei copaci sunt aceiași.

Acum vrem să facem modificări în dosar și să îl încurcăm. Vom trece prin aceeași procedură; mai întâi vom edita fișierul în directorul nostru de lucru. Să numim această versiune a fișierului v2 și să o numim roșie.

Git - dezvăluirea reinițializării misterelor

Dacă acum vom executa statutul de git. atunci vom vedea că fișierul este evidențiat în roșu în secțiunea "Modificări nepregătite pentru comitet", deoarece reprezentările sale în index și în directorul de lucru sunt diferite. Apoi vom rula git add pentru acest fișier pentru al pune în Index.

Git - dezvăluirea reinițializării misterelor

Dacă acum vom executa statutul de git. putem vedea că fișierul este evidențiat în verde în „Modificările aduse fie zakommicheny“ ca indice și HEAD sunt diferite - adică, următoarea programată nostru comite este acum diferit de la ultima noastră comite. În cele din urmă, vom rula git commit. pentru a face o comitere.

Git - dezvăluirea reinițializării misterelor

Acum, comanda de stare git nu arată nimic, deoarece din nou toți cei trei copaci sunt aceiași.

Comutarea ramurilor și clonarea trec printr-un proces similar. Când comutați (checkout) la o filială, HEAD începe de asemenea să indice o nouă filială, indexul dvs. este înlocuit cu un snapshot de comitet al acestei sucursale, iar conținutul Index este copiat în directorul dvs. de lucru.

Resetarea scopului

Comanda de resetare devine mai ușor de înțeles dacă o consideri în lumina celor de mai sus.

În exemplele următoare, să presupunem că am modificat din nou fișierul file.txt și l-am angajat a treia oară. Deci povestea noastră arată acum:

Git - dezvăluirea reinițializării misterelor

Să analizăm acum cu atenție ce se întâmplă exact atunci când este chemată o resetare. Această comandă gestionează trei copaci care există în Git într-un mod simplu și previzibil. Ea efectuează trei operațiuni de bază.

Pasul 1: Deplasarea HEAD

Primul lucru pe care o resetare o va face este să mutați la ce indică HEAD. Rețineți că HEAD în sine nu se modifică (ceea ce se întâmplă atunci când se execută comanda de control); resetare se mișcă ramura indicată de HEAD. Astfel, în cazul în care punctele de cap la maestru ramură (adică, lucrați cu o ramură de master), punerea în aplicare a echipei 9e5e6a4 de resetare Git se va asigura că maestrul va indica 9e5e6a4.

Git - dezvăluirea reinițializării misterelor

Nu contează opțiunile pe care le-ați numit comanda de resetare cu o comitere (resetarea poate fi apelată și cu o cale), aceasta va încerca întotdeauna să facă primul pas. Când reset -soft este apelat, comanda se va opri și se va executa.







Acum, uitați-vă la diagramă și încercați să aflați ce sa întâmplat: ultima comandă git commit a fost anulată. Când executați comanda git. Git creează o nouă comitere și mișcă ramura indicată de HEAD. Dacă efectuați o resetare pe HEAD

(HEAD-ul părinte), apoi mutați sucursala acolo unde a fost înainte, fără a schimba nici indexul, nici directorul de lucru. Puteți actualiza indexul și rulați din nou git commit. făcând același lucru pe care îl face comanda git commit -amend (consultați Modificarea ultimei comenzi).

Pasul 2: Actualizarea indexului (- mixt)

Observați că dacă rulați acum statutul de git. veți vedea schimbările verde între index și noul HEAD.

Următorul lucru pe care îl va face este să resetați. va actualiza indexul cu conținutul imaginii pe care o indică HEAD.

Git - dezvăluirea reinițializării misterelor

Dacă ați specificat opțiunea - mixtă. execuția resetării se va opri la acest pas. Acest comportament este, de asemenea, utilizat în mod implicit, deci dacă nu ați specificat nicio opțiune la toate (în cazul nostru, git reset HEAD

), executarea comenzii se va opri și la acest pas.

Uitați-vă din nou la diagrama și încercați să aflați ce sa întâmplat: nu numai că ultimul dvs. comitet a fost anulat. dar și adăugarea tuturor fișierelor în index. Ați redirecționat înapoi până când au fost executate comenzile git și au fost executate comenzi git.

Pasul 3: Actualizați directorul de lucru (--hard)

Al treilea lucru pe care îl face o resetare este aducerea directorului dvs. de lucru la același tip ca indexul. Dacă utilizați opțiunea --hard. executarea comenzii va fi continuată până la această etapă.

Git - dezvăluirea reinițializării misterelor

Să vedem ce sa întâmplat acum. Ați anulat ultima dvs. comitere, rezultatele comenzilor git add și git commit. precum și toate modificările pe care le-ați făcut în directorul de lucru.

Este important să rețineți că numai specificarea acestui pavilion (- hard) face comanda de resetare periculoasă, acesta fiind unul dintre puținele cazuri în care Git șterge efectiv datele. Toate celelalte apeluri de resetare pot fi ușor anulate, dar când este specificată opțiunea --hard, comanda suprascrie forțat fișierele din directorul de lucru. În acest caz special, versiunea v3 a fișierului nostru este încă în comitetul din cadrul bazei de date Git și îl putem returna uitându-ne la reflogul nostru. Dar dacă nu ați comis această versiune, Git va suprascrie fișierul și nu poate fi restabilită.

Comanda de resetare într-o ordine predeterminată suprascrie cei trei arbori Git, oprindu-se când îi spui:

Mută ​​sucursala indicată de HEAD (oprește această opțiune dacă este specificată opțiunea -soft)

Efectuează indexul la fel ca HEAD (oprește dacă această opțiune nu este specificată)

Efectuează un director de lucru la fel ca Index.

Resetați cu cale

Forma de bază a comenzii de resetare (fără opțiunile --soft și - hard) puteți trece și calea cu care va funcționa. În acest caz, resetarea va sări peste primul pas, iar pe celelalte va funcționa numai cu fișierul sau cu setul de fișiere specificat. Primul pas este sărit peste măsură, deoarece HEAD este un indicator și nu se poate referi în parte la un comitet, și parțial la altul. Dar indexul și directorul de lucru pot fi parțial modificate, deci resetarea face pașii 2 și 3.

Deci, să presupunem că executați comanda git reset file.txt. Această formă de scriere (din moment ce nu a specificat nici comitere SHA-1, sau o sucursală sau opțiuni --soft sau --hard) este o abreviere pentru git reset HEAD fisier.txt --mixed. că:

Mută ​​ramura indicată de HEAD (va fi omisă)

Face indexul la fel ca HEAD (se va opri aici)

De fapt, acesta copiază fișierul file.txt de la HEAD la index.

Git - dezvăluirea reinițializării misterelor

Aceasta creează efectul de a anula indexarea fișierului. Dacă vă uitați la diagramele acestei comenzi și la comanda git add. veți vedea că acțiunile lor sunt exact opusul.

Git - dezvăluirea reinițializării misterelor

De aceea, în starea de ieșire git este sugerat să utilizați această comandă pentru a anula indexarea fișierului. (Consultați detaliile din Pregătirea fișierului Anulare.)

Putem cu ușurință să obținem Git să "ia date nu de la HEAD" prin specificarea comiterii de la care să obțină versiunea acestui fișier. Pentru a face acest lucru, trebuie să efectuăm următorul git reset eb43bf file.txt.

Git - dezvăluirea reinițializării misterelor

Putem presupune că, de fapt, am returnat conținutul fișierului la v1 din directorul de lucru. realizate pentru asta. și apoi a returnat conținutul înapoi la versiunea v3 (de fapt, toți acești pași nu sunt executați). Dacă acum vom executa comanda git. atunci vor fi salvate modificările care returnează fișierul la versiunea v1. dar fișierul din directorul de lucru nu a revenit niciodată la această versiune.

Rețineți că, ca și comanda git add. resetați, puteți specifica opțiunea --patch pentru a anula indexarea unei porțiuni din conținut. În acest fel, puteți anula în mod selectiv indexarea sau modificările înapoi.

Merge comitete

Să vedem cum, folosind cele de mai sus, să facem ceva interesant - să fuzăm comitetele.

Să presupunem că aveți o serie de angajamente cu mesaje precum "sus", "la serviciu" și "ați uitat acest fișier". Puteți utiliza resetați pentru a le îmbina pur și simplu într-una singură. (Există un alt mod de a face același lucru în remedierile Combine, dar în acest exemplu este mai ușor de utilizat resetarea.)

Să presupunem că aveți un proiect în care primul comitet conține un fișier, al doilea comitet adaugă un fișier nou și modifică primul și cel de-al treilea comitează primul fișier din nou. Cea de-a doua comisie a fost făcută în timpul operei și doriți să o îmbinați cu următoarele.

Git - dezvăluirea reinițializării misterelor

Puteți rula git reset --soft HEAD

2. Pentru a returna ramura HEAD la una din comitetele anterioare (pentru prima comitere pe care doriți să o plecați):

Git - dezvăluirea reinițializării misterelor

Apoi rulați git comite din nou:

Git - dezvăluirea reinițializării misterelor

Acum puteți vedea că povestea dvs. "realizabilă" (povestea pe care o trimiteți ulterior serverului) arată acum - aveți primul comitet cu fișierul-a.txt versiunea v1. iar al doilea, care modifică fișierul-a.txt la v3 și adaugă fișier-b.txt. Comanda care conținea fișierul versiunii v2 nu a rămas în istoric.

Comparație cu checkout

În cele din urmă, s-ar putea să vă întrebați ce este diferența între checkout și resetare. Pe lângă resetare. comanda de control comandă trei arbori Git și, de asemenea, comportamentul său depinde de faptul dacă ați specificat calea către fișier sau nu.

Fără cale

Comanda de comandă [branch] a git este foarte asemănătoare cu git reset --hard [branch]. în cursul executării lor, toți cei trei copaci se schimbă pentru a arăta ca [ramură]. Dar între aceste echipe există două diferențe importante.

În primul rând, spre deosebire de restabilirea. comanda checkout are grijă de directorul de lucru și verifică faptul că nu atinge fișierele care au modificări. De fapt, această comandă este puțin mai inteligentă - încearcă să efectueze îmbinări simple în directorul de lucru, astfel încât toate fișierele pe care nu le-ați modificat să fie actualizate. Pe de altă parte, comanda de resetare înlocuiește pur și simplu totul, fără a efectua verificări.

A doua diferență importantă este modul în care aceste comenzi actualizează HEAD. În timpul resetării se deplasează ramificația indicată de HEAD, comanda de verificare se mișcă HEAD în sine pentru a indica o altă ramificație.

De exemplu, să-l avem pe stăpân și să dezvoltăm ramuri. care indică comitete diferite și suntem acum pe ramura dezvoltării (adică HEAD indică acest lucru). Dacă executăm git reset master. dezvoltarea ramurii se va referi la aceeași comitere ca și comandantul. Dacă executăm comandantul de verificare GIT. apoi dezvoltarea nu se va schimba, dar HEAD se va schimba. Va îndrepta spre maestru.

Deci, în ambele cazuri, mutăm HEAD pentru a comite A, dar diferența importantă este modul în care o facem. Comanda de resetare va deplasa, de asemenea, sucursala indicată de HEAD, iar checkout-ul mișcă numai HEAD în sine.

Git - dezvăluirea reinițializării misterelor

Cu calea

O altă modalitate de a efectua o verificare este să specificați calea spre fișier. În acest caz, ca și în cazul comenzii de resetare. HEAD nu se mișcă. Această comandă, ca fișierul git reset [branch], actualizează fișierul din index cu versiunea din comitet, dar în plus actualizează fișierul din directorul de lucru. Același lucru se va face și prin comanda git reset --hard [branch] (dacă resetarea ar putea fi rulată în acest fel) - nu este sigură pentru directorul de lucru și nu se mișcă HEAD.

La fel ca git reset și adăugați git. comanda de verificare acceptă opțiunea --patch pentru a vă permite selecționarea selectivă a conținutului fișierului în părți.

concluzie

Sper că înțelegeți comanda de resetare și o puteți folosi în siguranță. Dar poate ești încă puțin confuză despre cum diferă de la checkout. și nu am amintit toate regulile utilizate în diferite opțiuni de apel.







Articole similare

Trimiteți-le prietenilor: