Când învățați să codificați, mai devreme sau mai târziu veți afla și despre sistemele de control al versiunilor. Și, deși există multe instrumente concurente în acest spațiu, unul dintre ele este standardul de facto utilizat de aproape toată lumea din industrie. Este atât de popular încât există companii care își folosesc numele în branding. Vorbim despre Git, desigur.

În timp ce Git este un instrument puternic, puterea sa este bine ascunsă. Există câteva concepte esențiale pe care trebuie să le înțelegeți pentru a deveni foarte competenți cu Git. Vestea bună este că, odată ce le veți învăța, cu greu veți întâlni vreodată probleme din care nu puteți scăpa.

Fluxul de lucru tipic

Într-un flux de lucru tipic Git, veți utiliza un depozit local, un depozit la distanță și una sau mai multe ramuri. Depozitele stochează toate informațiile despre proiect, inclusiv întregul său istoric și toate sucursalele. O ramură este practic o colecție de modificări care duc de la un proiect gol la starea actuală.

După clonarea unui depozit, lucrați la copia locală și introduceți noi modificări. Până când împingeți modificările locale în depozitul la distanță, toată munca dvs. este disponibilă numai pe mașina dvs.

Când terminați o sarcină, este timpul să vă sincronizați cu depozitul la distanță. Doriți să trageți modificările la distanță pentru a ține pasul cu progresul proiectului și doriți să împingeți modificările locale pentru a vă împărtăși munca cu alții.

Modificări locale

Totul este bine atunci când tu și restul echipei dvs. lucrați la fișiere complet separate. Orice s-ar întâmpla, nu veți păși pe picioarele celuilalt.

Cu toate acestea, există momente în care tu și colegii de echipă introduceți simultan schimbări în același loc. Și de aici încep problemele.

Ai executat vreodată git pull doar pentru a vedea pe cei temuți error: Your local changes to the following files would be overwritten by merge:? Mai devreme sau mai târziu, toată lumea se confruntă cu această problemă.

Ceea ce este mai confuz aici este că nu doriți să îmbinați nimic, doar trageți, nu? De fapt, pull este puțin mai complicat decât ai fi crezut.

Cum funcționează exact Git Pull?

Pull nu este o singură operație. Acesta constă în preluarea datelor de pe serverul de la distanță și apoi îmbinarea modificărilor cu depozitul local. Aceste două operații pot fi efectuate manual dacă doriți:

git fetch
git merge origin/$CURRENT_BRANCH

origin/$CURRENT_BRANCH partea înseamnă că:

  • Git va îmbina modificările din depozitul la distanță numit origin (cel din care ai clonat)
  • care au fost adăugate la $CURRENT_BRANCH
  • care nu sunt deja prezente în filiala locală verificată

Deoarece Git efectuează fuziuni numai atunci când nu există modificări necomandate, de fiecare dată când rulați git pull cu modificări neangajate te-ar putea pune în probleme. Din fericire, există modalități de a ieși dintr-o singură bucată!

Suntem o familie
Fotografie de Sneaky Elbow / Unsplash

Abordări diferite

Când aveți modificări locale neangajate și doriți totuși să extrageți o nouă versiune de pe serverul la distanță, cazul dvs. de utilizare se încadrează de obicei în unul dintre următoarele scenarii. Fie:

  • nu vă pasă de schimbările locale și doriți să le suprascrieți,
  • îți pasă foarte mult de modificări și ai vrea să le aplici după modificările la distanță,
  • doriți să descărcați modificările de la distanță, dar să nu le aplicați încă

Fiecare dintre abordări necesită o soluție diferită.

Nu vă pasă de modificările locale

În acest caz, doriți doar să renunțați la toate modificările locale neangajate. Poate că ați modificat un fișier pentru a experimenta, dar nu mai aveți nevoie de modificare. Tot ce îți pasă este să fii la curent cu amonte.

Aceasta înseamnă că mai adăugați un pas între preluarea modificărilor la distanță și îmbinarea acestora. Acest pas va reseta ramura la starea sa nemodificată, permițând astfel git merge a munci.

git fetch
git reset --hard HEAD
git merge origin/$CURRENT_BRANCH

Dacă nu doriți să tastați numele sucursalei de fiecare dată când executați această comandă, Git are o scurtătură frumoasă care indică ramura din amonte: @{u}. O ramură în amonte este ramura din depozitul la distanță pe care apăsați și de la care o preluați.

Așa ar arăta comenzile de mai sus cu comanda rapidă:

git fetch
git reset --hard HEAD
git merge '@{u}'

Cităm comanda rapidă din exemplu pentru a împiedica interpretarea shell-ului.

Îți pasă foarte mult de schimbările locale

Atunci când modificările dvs. neangajate sunt semnificative pentru dvs., există două opțiuni. Puteți să le comiteți și apoi să efectuați git pull, sau le puteți ascunde.

Stashing înseamnă a pune schimbările pentru o clipă pentru a le aduce înapoi mai târziu. Pentru a fi mai precis, git stash creează un commit care nu este vizibil în filiala dvs. curentă, dar este încă accesibil de Git.

Pentru a readuce modificările salvate în ultima memorie, utilizați git stash pop comanda. După aplicarea cu succes a modificărilor stashed, această comandă elimină și commit-ul stash, deoarece nu mai este necesar.

Fluxul de lucru ar putea arăta astfel:

git fetch
git stash
git merge '@{u}'
git stash pop

În mod implicit, modificările din stash vor deveni etapizate. Dacă doriți să le dezinstalați, utilizați comanda git restore --staged (dacă utilizați Git mai recent de 2.25.0).

Vrei doar să descarci modificările la distanță

Ultimul scenariu este puțin diferit de cel anterior. Să spunem că vă aflați în mijlocul unei refaceri foarte dezordonate. Nici pierderea modificărilor, nici ascunderea acestora nu este o opțiune. Totuși, doriți în continuare să aveți disponibile modificările la distanță pentru a rula git diff impotriva lor.

Așa cum probabil v-ați dat seama, descărcarea modificărilor la distanță nu necesită git pull deloc! git fetch este suficient.

Un lucru de reținut este că, în mod implicit, git fetch vă va aduce doar modificări din ramura curentă. Pentru a obține toate modificările din toate ramurile, utilizați git fetch --all. Și dacă doriți să curățați unele dintre ramurile care nu mai există în depozitul la distanță, git fetch --all --prune va face curățenia!

1611708006 340 Git Pull Force Cum sa suprascrieti modificarile locale
Fotografie de Lenin Estrada / Unsplash

Unele automatizări

Ai auzit de Git Config? Este un fișier în care Git stochează toate setările configurate de utilizator. Acesta se află în directorul dvs. de acasă: fie ca ~/.gitconfig sau ~/.config/git/config. Puteți să-l editați pentru a adăuga câteva aliasuri personalizate care vor fi înțelese ca comenzi Git.

De exemplu, pentru a avea o comandă rapidă echivalentă cu git diff --cached (care arată diferența dintre ramura curentă și fișierele etapizate), ați adăuga următoarea secțiune:

[alias]
  dc = diff --cached

După aceea, puteți fugi git dc ori de câte ori doriți să examinați modificările. În acest fel, putem configura câteva aliasuri legate de cazurile de utilizare anterioare.

[alias]
  pull_force = !"git fetch --all; git reset --hard HEAD; git merge @{u}"
  pf = pull_force
  pull_stash = !"git fetch --all; git stash; git merge @{u}; git stash pop"

În acest fel, alergând git pull_force va suprascrie modificările locale, în timp ce git pull_stash le va păstra.

Cealaltă forță de tracțiune Git

Mintile curioase ar fi putut descoperi deja că există așa ceva git pull --force. Cu toate acestea, aceasta este o bestie foarte diferită de ceea ce este prezentat în acest articol.

Poate suna ca ceva care ne-ar ajuta să suprascriem schimbările locale. În schimb, ne permite să preluăm modificările de la o ramură la distanță la o ramură locală diferită. git pull --force modifică doar comportamentul părții de preluare. Prin urmare, este echivalent cu git fetch --force.

Ca git push, git fetch ne permite să specificăm pe ce ramură locală și la distanță dorim să operăm. git fetch origin/feature-1:my-feature va însemna că modificările din feature-1 ramura din depozitul la distanță va ajunge vizibilă pe ramura locală my-feature. Când o astfel de operațiune modifică istoricul existent, Git nu este permisă fără o explicație explicită --force parametru.

La fel ca git push --force permite suprascrierea ramurilor la distanță, git fetch --force (sau git pull --force) permite suprascrierea sucursalelor locale. Este întotdeauna utilizat cu ramuri sursă și destinație menționate ca parametri. O abordare alternativă la suprascrierea modificărilor locale folosind git --pull force ar putea fi git pull --force "@{u}:HEAD".

Concluzie

Lumea Git este vastă. Acest articol acoperea doar una dintre fațetele întreținerii depozitului: încorporarea modificărilor la distanță într-un depozit local. Chiar și acest scenariu de zi cu zi ne-a impus să analizăm puțin mai în profunzime mecanismele interne ale instrumentului de control al versiunilor.

Învățarea cazurilor de utilizare reală vă ajută să înțelegeți mai bine cum funcționează Git sub capotă. Acest lucru, la rândul său, vă va face să vă simțiți împuterniciți ori de câte ori vă puneți în necazuri. Cu toții facem asta din când în când.