1. Un ghid detaliat pentru Git pentru începători

Astăzi vom vorbi despre un sistem de control al versiunilor și anume Git.

Chiar nu poți fi un programator cu drepturi depline fără să cunoști și să înțelegi acest instrument. Desigur, nu trebuie să păstrați toate comenzile și funcțiile Git în cap pentru a fi angajat continuu. Trebuie să cunoașteți un set de comenzi care vă vor ajuta să înțelegeți tot ce se întâmplă.

Bazele Git

Git este un sistem distribuit de control al versiunilor pentru codul nostru. De ce avem nevoie de ea? Echipele au nevoie de un fel de sistem pentru a-și gestiona munca. Este necesar să urmăriți schimbările care apar în timp.

Adică, trebuie să putem vedea pas cu pas ce fișiere s-au schimbat și cum. Acest lucru este deosebit de important atunci când investigați ce sa schimbat în contextul unei singure sarcini, făcând posibilă anularea modificărilor.

Să ne imaginăm următoarea situație: avem cod de lucru, totul în el este bun, dar apoi decidem să îmbunătățim sau să modificăm ceva. Nu e mare lucru, dar „îmbunătățirea” noastră a spart jumătate din caracteristicile programului și a făcut imposibilă funcționarea. Si acum ce? Fără Git, ar trebui să stai și să te gândești ore în șir, încercând să-ți amintești cum a fost totul inițial. Dar cu Git, pur și simplu derulăm înapoi comiterea - și asta este tot.

Sau ce se întâmplă dacă există doi dezvoltatori care își fac propriile modificări de cod în același timp? Fără Git, ei copiază fișierele de cod originale și le modifică separat. Vine un moment când ambii doresc să adauge modificările lor în directorul principal. Ce faci in acest caz?

Nu vor exista astfel de probleme dacă utilizați Git.

Instalarea Git

Să instalăm Java pe computer. Acest proces diferă ușor pentru diferite sisteme de operare.

Instalare pe Windows

Ca de obicei, trebuie să descărcați și să rulați un fișier exe. Totul este simplu aici: faceți clic pe primul link Google , efectuați instalarea și gata. Pentru a face acest lucru, vom folosi consola bash furnizată de Windows.

Pe Windows, trebuie să rulați Git Bash. Iată cum arată în meniul Start:

Acum, acesta este un prompt de comandă cu care puteți lucra.

Pentru a evita de fiecare dată să mergeți în folderul cu proiectul pentru a putea deschide Git acolo, puteți deschide promptul de comandă din folderul proiectului cu butonul din dreapta al mouse-ului cu calea de care avem nevoie:

Instalare pe Linux

De obicei, Git face parte din distribuțiile Linux și este deja instalat, deoarece este un instrument care a fost scris inițial pentru dezvoltarea nucleului Linux. Dar sunt situații când nu este. Pentru a verifica, trebuie să deschideți un terminal și să scrieți: git --version. Dacă obțineți un răspuns inteligibil, atunci nu trebuie instalat nimic.

Deschideți un terminal și instalați. Pentru Ubuntu, trebuie să scrieți: sudo apt-get install git. Și gata: acum poți folosi Git în orice terminal.

Instalare pe macOS

Și aici, mai întâi trebuie să verificați dacă Git este deja acolo (vezi mai sus, la fel ca și pe Linux).

Dacă nu îl aveți, cel mai simplu mod de a-l obține este să descărcați cea mai recentă versiune . Dacă Xcode este instalat, atunci Git va fi cu siguranță instalat automat.

Setări Git

Git are setări de utilizator pentru utilizatorul care va trimite lucrări. Acest lucru are sens și este necesar, deoarece Git preia aceste informații pentru câmpul Autor atunci când este creat un commit.

Configurați un nume de utilizator și o parolă pentru toate proiectele dvs. rulând următoarele comenzi:

git config --global user.name "Ivan Ivanov" git config --global user.email ivan.ivanov@gmail.com

Dacă trebuie să schimbați autorul pentru un anumit proiect (pentru un proiect personal, de exemplu), puteți elimina „--global”. Acest lucru ne va oferi următoarele:

git config user.name "Ivan Ivanov" git config user.email ivan.ivanov@gmail.com

Un pic de teorie

Pentru a vă scufunda în subiect, ar trebui să vă prezentăm câteva cuvinte și acțiuni noi... În caz contrar, nu va mai fi nimic de vorbit. Desigur, acesta este jargon care ne vine din engleză, așa că voi adăuga traduceri între paranteze.

Ce cuvinte și acțiuni?

  • depozitul git
  • comite
  • ramură
  • combina
  • conflicte
  • Trage
  • Apăsaţi
  • cum să ignori unele fișiere (.gitignore)

Și așa mai departe.

Stări în Git

Git are mai multe statui care trebuie înțelese și reținute:

  • neurmată
  • modificat
  • pus în scenă
  • comise

Cum ar trebui să înțelegi asta?

Acestea sunt stări care se aplică fișierelor care conțin codul nostru. Cu alte cuvinte, ciclul lor de viață arată de obicei astfel:

  • Un fișier care a fost creat, dar care nu este încă adăugat în depozit are starea „ne urmărit”.
  • Când facem modificări la fișierele care au fost deja adăugate în depozitul Git, atunci starea lor este „modificată”.
  • Dintre fișierele pe care le-am schimbat, le selectăm pe cele de care avem nevoie (de exemplu, nu avem nevoie de clase compilate), iar aceste clase sunt modificate în starea „în etape”.
  • O comitere este creată din fișiere pregătite în starea în etapă și intră în depozitul Git. După aceea, nu există fișiere cu starea „în etapă”. Dar pot exista în continuare fișiere a căror stare este „modificată”.

Așa arată:

Ce este un commit?

Un commit este evenimentul principal atunci când vine vorba de controlul versiunilor. Conține toate modificările făcute de la începutul comiterii. Commit-urile sunt legate între ele ca o listă unică.

Mai exact, există un prim commit. Când este creat al doilea commit, acesta (al doilea) știe ce urmează după primul. Și în acest mod, informațiile pot fi urmărite.

Un commit are, de asemenea, propriile informații, așa-numitele metadate:

  • identificatorul unic al comiterii, care poate fi folosit pentru a-l găsi
  • numele autorului comisiei, care a creat-o
  • data la care a fost creat commit-ul
  • un comentariu care descrie ceea ce s-a făcut în timpul comiterii

Iată cum arată:

Ce este o ramură?

O ramură este un indicator către o comitere. Deoarece un commit știe care commit îl precede, atunci când o ramură indică un commit, toate acele comitere anterioare se aplică și ei.

În consecință, am putea spune că puteți avea atâtea ramuri câte doriți, indicând același commit.

Lucrarea are loc în ramuri, așa că atunci când este creat un nou commit, ramura își mută indicatorul spre commit-ul mai recent.

Începeți cu Git

Puteți lucra atât cu un depozit local, cât și cu unul la distanță.

Pentru a exersa comenzile necesare, vă puteți limita la depozitul local. Stochează doar local toate informațiile proiectului în folderul .git.

Dacă vorbim despre depozitul de la distanță, atunci toate informațiile sunt stocate undeva pe serverul de la distanță: doar o copie a proiectului este stocată local. Modificările aduse copiei dvs. locale pot fi trimise (git push) în depozitul de la distanță.

În discuția noastră de aici și de mai jos, vorbim despre lucrul cu Git în consolă. Desigur, puteți utiliza un fel de soluție bazată pe GUI (de exemplu, IntelliJ IDEA), dar mai întâi ar trebui să vă dați seama ce comenzi sunt executate și ce înseamnă acestea.

Lucrul cu Git într-un depozit local

Pentru a crea un depozit local, trebuie să scrieți:

git init

Acest lucru va crea un folder .git ascuns în directorul curent al consolei.

Dosarul .git stochează toate informațiile despre depozitul Git. Nu-l șterge ;)

Apoi, fișierele sunt adăugate la proiect și li se atribuie starea „Ne urmărit”. Pentru a verifica starea actuală a lucrării dvs., scrieți asta:

starea git

Suntem în ramura master, și aici vom rămâne până când trecem la o altă ramură.

Aceasta arată ce fișiere s-au modificat, dar nu au fost încă adăugate la starea „în etape”. Pentru a le adăuga la starea „în scenă”, trebuie să scrieți „git add”. Avem aici câteva opțiuni, de exemplu:

  • git add -A — adaugă toate fișierele la starea „în scenă”.
  • git add . — adăugați toate fișierele din acest folder și toate subfolderele. În esență la fel ca și precedentul;
  • git add <file name> — adaugă un anumit fișier. Aici puteți folosi expresii regulate pentru a adăuga fișiere conform unui model. De exemplu, git add *.java: Aceasta înseamnă că doriți doar să adăugați fișiere cu extensia java.

Primele două opțiuni sunt clar simple. Lucrurile devin mai interesante cu cea mai recentă adăugare, așa că hai să scriem:

git add *.txt

Pentru a verifica starea, folosim comanda deja cunoscută nouă:

starea git

Aici puteți vedea că expresia regulată a funcționat corect: test_resource.txt are acum starea „în etape”.

Și, în sfârșit, ultima etapă pentru lucrul cu un depozit local (mai există unul când lucrezi cu depozitul de la distanță ;)) - crearea unui nou commit:

git commit -m „toate fișierele txt au fost adăugate la proiect”

Următorul este o comandă grozavă pentru a vedea istoricul comitării pe o ramură. Să folosim de el:

git log

Aici puteți vedea că am creat primul nostru commit și include textul pe care l-am furnizat pe linia de comandă. Este foarte important de înțeles că acest text ar trebui să explice cât mai exact posibil ceea ce s-a făcut în timpul acestui comit. Acest lucru ne va ajuta de multe ori în viitor.

Un cititor curios care nu a adormit încă s-ar putea să se întrebe ce s-a întâmplat cu fișierul GitTest.java. Să aflăm chiar acum. Pentru a face acest lucru, folosim:

starea git

După cum puteți vedea, este încă „netrasă” și așteaptă în aripi. Dar dacă nu vrem deloc să-l adăugăm la proiect? Uneori se întâmplă asta.

Pentru a face lucrurile mai interesante, acum să încercăm să schimbăm fișierul test_resource.txt. Să adăugăm ceva text acolo și să verificăm starea:

starea git

Aici puteți vedea clar diferența dintre stările „ne urmărit” și „modificat”.

GitTest.java este „ne urmărit”, în timp ce test_resource.txt este „modificat”.

Acum că avem fișiere în starea modificată, putem examina modificările aduse acestora. Acest lucru se poate face folosind următoarea comandă:

git diff

Adică puteți vedea clar aici ce am adăugat la fișierul nostru text: hello world!

Să adăugăm modificările noastre la fișierul text și să creăm un commit:

git add test_resource.txt
git commit -m „a adăugat cuvântul salut! la test_resource.txt”

Pentru a vedea toate commit-urile, scrieți:

git log

După cum puteți vedea, acum avem două comisii.

Vom adăuga GitTest.java în același mod. Fără comentarii aici, doar comenzi:

git add GitTest.java
git commit -m „a adăugat GitTest.java”
starea git

Lucrul cu .gitignore

În mod clar, vrem doar să păstrăm codul sursă singur, și nimic altceva, în depozit. Deci ce altceva ar putea fi? Cel puțin, clase compilate și/sau fișiere generate de mediile de dezvoltare.

Pentru a-i spune lui Git să le ignore, trebuie să creăm un fișier special. Faceți acest lucru: creați un fișier numit .gitignore în rădăcina proiectului. Fiecare linie din acest fișier reprezintă un model de ignorat.

În acest exemplu, fișierul .gitignore va arăta astfel:

*.class
target/
*.iml
.idea/

Hai să aruncăm o privire:

  • Prima linie este să ignorați toate fișierele cu extensia .class
  • A doua linie este să ignori folderul „țintă” și tot ceea ce conține
  • A treia linie este să ignorați toate fișierele cu extensia .iml
  • A patra linie este să ignorați folderul .idea

Să încercăm să folosim un exemplu. Pentru a vedea cum funcționează, să adăugăm GitTest.class compilat la proiect și să verificăm starea proiectului:

starea git

În mod clar, nu vrem să adăugăm în mod accidental clasa compilată în proiect (folosind git add -A). Pentru a face acest lucru, creați un fișier .gitignore și adăugați tot ce a fost descris mai devreme:

Acum să folosim un commit pentru a adăuga fișierul .gitignore la proiect:

git add .gitignore
git commit -m „fișierul .gitignore adăugat”

Și acum este momentul adevărului: avem o clasă compilată GitTest.class care este „untracked”, pe care nu am vrut să o adăugăm la depozitul Git.

Acum ar trebui să vedem efectele fișierului .gitignore:

starea git

Perfect! .gitignore +1 :)

Lucrul cu ramurile

Desigur, lucrul într-o singură ramură este incomod pentru dezvoltatorii solitari și este imposibil atunci când există mai multe persoane într-o echipă. De aceea avem filiale.

O ramură este doar un pointer mobil către comitere.

În această parte, vom explora lucrul în diferite ramuri: cum să îmbinați modificările de la o ramură în alta, ce conflicte pot apărea și multe altele.

Pentru a vedea o listă cu toate ramurile din depozit și pentru a înțelege în care dintre ramuri vă aflați, trebuie să scrieți:

git branch -a

Puteți vedea că avem doar o ramură principală. Asteriscul din fața lui indică faptul că suntem în el. Apropo, puteți folosi și comanda „git status” pentru a afla în ce ramură ne aflăm.

Apoi există mai multe opțiuni pentru a crea ramuri (pot fi mai multe - acestea sunt cele pe care le folosesc):

  • creați o nouă filială pe baza celei în care ne aflăm (99% din cazuri)
  • creați o ramură pe baza unui anumit commit (1% din cazuri)

Să creăm o ramură bazată pe un anumit commit

Ne vom baza pe identificatorul unic al comiterii. Pentru a-l găsi, scriem:

git log

Am evidențiat commit-ul cu comentariul „adăugat salut lume...” Identificatorul său unic este 6c44e53d06228f888f2f454d3cb8c1c976dd73f8. Dorim să creăm o ramură de „dezvoltare” care să plece de la acest commit. Pentru a face acest lucru, scriem:

git checkout -b dezvoltare 6c44e53d06228f888f2f454d3cb8c1c976dd73f8

O ramură este creată doar cu primele două comite din ramura principală. Pentru a verifica acest lucru, mai întâi ne asigurăm că comutăm la o altă ramură și ne uităm la numărul de comiteri de acolo:

starea git
git log

Și așa cum era de așteptat, avem două comisii. Apropo, iată un punct interesant: nu există încă niciun fișier .gitignore în această ramură, așa că fișierul nostru compilat (GitTest.class) este acum evidențiat cu starea „ne urmărit”.

Acum ne putem revizui din nou filialele scriind asta:

git branch -a

Puteți observa că există două ramuri: „master” și „dezvoltare”. În prezent suntem în dezvoltare.

Să creăm o ramură bazată pe cea actuală

A doua modalitate de a crea o ramură este să o creezi din alta. Vrem să creăm o ramură bazată pe ramura principală. În primul rând, trebuie să trecem la el, iar următorul pas este să creăm unul nou. Hai să aruncăm o privire:

  • git checkout master — comută la ramura principală
  • git status — verificați dacă suntem de fapt în ramura principală

Aici puteți vedea că am trecut la ramura master, fișierul .gitignore este în vigoare, iar clasa compilată nu mai este evidențiată ca „untracked”.

Acum creăm o nouă ramură bazată pe ramura principală:

git checkout -b feature/update-txt-files

Dacă nu sunteți sigur dacă această ramură este aceeași cu „master”, puteți verifica cu ușurință executând „git log” și uitându-vă la toate commit-urile. Ar trebui să fie patru.

Rezolvarea conflictului

Înainte de a explora ce este un conflict, trebuie să vorbim despre îmbinarea unei ramuri în alta.

Această imagine ilustrează procesul de îmbinare a unei ramuri în alta:

Aici avem o ramură principală. La un moment dat, o ramură secundară este creată din ramura principală și apoi modificată. Odată ce lucrarea este terminată, trebuie să unim o ramură în cealaltă.

În exemplul nostru, am creat ramura feature/update-txt-files. După cum indică numele sucursalei, actualizăm textul.

Acum trebuie să creăm un nou commit pentru această lucrare:

git add *.txt
git commit -m „fișiere txt actualizate”
git log

Acum, dacă vrem să îmbinăm ramificația caracteristică/update-txt-files în master, trebuie să mergem la master și să scriem „git merge feature/update-txt-files”:

git checkout master
git merge feature/update-txt-files
git log

Drept urmare, ramura principală include acum și commit-ul care a fost adăugat la fișierele feature/update-txt.

Această funcționalitate a fost adăugată, astfel încât să puteți șterge o ramură de caracteristică. Pentru a face acest lucru, scriem:

git branch -D feature/update-txt-files

Să complicăm situația: acum să spunem că trebuie să schimbi din nou fișierul txt. Dar acum acest fișier va fi modificat și în ramura principală. Cu alte cuvinte, se va schimba în paralel. Git nu va putea să-și dea seama ce să facă atunci când dorim să îmbinăm noul nostru cod în ramura principală.

Vom crea o nouă ramură bazată pe master, vom face modificări la text_resource.txt și vom crea un commit pentru această lucrare:

git checkout -b feature/add-header

... facem modificări la fișier

git add *.txt
git commit -m „a adăugat antet la txt”

Accesați ramura principală și, de asemenea, actualizați acest fișier text pe aceeași linie ca și în ramura caracteristică:

git checkout master

… am actualizat test_resource.txt

git add test_resource.txt
git commit -m „a adăugat antetul principal la txt”

Și acum cel mai interesant punct: trebuie să îmbinăm modificările de la ramura caracteristică/adăugare antet la master. Suntem în ramura master, așa că trebuie doar să scriem:

funcția de îmbinare git/adăugare antet

Dar rezultatul va fi un conflict în fișierul test_resource.txt:

Aici putem vedea că Git nu a putut decide singur cum să îmbine acest cod. Ne spune că trebuie să rezolvăm mai întâi conflictul și abia apoi să executăm comiterea.

BINE. Deschidem fișierul cu conflictul într-un editor de text și vedem:

Pentru a înțelege ce a făcut Git aici, trebuie să ne amintim ce modificări am făcut și unde, apoi să comparăm:

  1. Modificările care au fost pe această linie în ramura master se regăsesc între „<<<<<<< HEAD” și „=======".
  2. Modificările care au fost în ramura feature/add-header se găsesc între „=======" și „>>>>>>> feature/add-header”.

Acesta este modul în care Git ne spune că nu și-a dat seama cum să efectueze îmbinarea în această locație din fișier. A împărțit această secțiune în două părți din diferite ramuri și ne invită să rezolvăm singuri conflictul de fuziune.

Destul de corect. Mă hotărăsc cu îndrăzneală să elimin totul, lăsând doar cuvântul „antet”:

Să ne uităm la starea modificărilor. Descrierea va fi ușor diferită. Mai degrabă decât un statut „modificat”, am „necontopit”. Deci am fi putut menționa un al cincilea statut? Nu cred că acest lucru este necesar. Să vedem:

starea git

Ne putem convinge că acesta este un caz special, neobișnuit. Hai sa continuăm:

git add *.txt

Este posibil să observați că descrierea sugerează să scrieți doar „git commit”. Să încercăm să scriem asta:

git commit

Și tocmai așa, am făcut-o - am rezolvat conflictul în consolă.

Desigur, acest lucru se poate face puțin mai ușor în mediile de dezvoltare integrate. De exemplu, în IntelliJ IDEA, totul este configurat atât de bine încât puteți efectua toate acțiunile necesare chiar în cadrul acestuia. Dar IDE-urile fac o mulțime de lucruri „sub capotă” și adesea nu înțelegem ce se întâmplă exact acolo. Și când nu există înțelegere, pot apărea probleme.

Lucrul cu depozite de la distanță

Ultimul pas este să descoperi câteva comenzi suplimentare care sunt necesare pentru a lucra cu depozitul de la distanță.

După cum am spus, un depozit la distanță este un loc în care depozitul este stocat și din care îl puteți clona.

Ce fel de depozite la distanță există? Exemple:

  • GitHub este cea mai mare platformă de stocare pentru depozite și dezvoltare colaborativă.
  • GitLab este un instrument bazat pe web pentru ciclul de viață DevOps cu sursă deschisă. Este un sistem bazat pe Git pentru gestionarea depozitelor de cod cu propriul wiki, sistem de urmărire a erorilor, conductă CI/CD și alte funcții.
  • BitBucket este un serviciu web pentru găzduirea proiectelor și dezvoltarea colaborativă bazat pe sistemele de control al versiunilor Mercurial și Git. La un moment dat, avea un mare avantaj față de GitHub prin faptul că oferea depozite private gratuite. Anul trecut, GitHub a introdus, de asemenea, această capacitate pentru toată lumea gratuit.
  • Și așa mai departe…

Când lucrați cu un depozit de la distanță, primul lucru de făcut este să clonați proiectul în depozitul dvs. local.

Pentru aceasta, am exportat proiectul pe care l-am realizat local. Acum toată lumea îl poate clona singur scriind:

git clone https://github.com/romankh3/git-demo

Există acum o copie locală completă a proiectului. Pentru a vă asigura că copia locală a proiectului este cea mai recentă, trebuie să extrageți proiectul scriind:

git pull

În cazul nostru, nimic din depozitul de la distanță nu s-a schimbat în prezent, așa că răspunsul este: Deja actualizat.

Dar dacă facem modificări în depozitul de la distanță, cel local este actualizat după ce le extragem.

Și, în sfârșit, ultima comandă este de a împinge datele în depozitul de la distanță. Când am făcut ceva local și dorim să-l trimitem la depozitul de la distanță, trebuie mai întâi să creăm un nou commit local. Pentru a demonstra acest lucru, să adăugăm altceva în fișierul text:

Acum ceva destul de comun pentru noi - creăm un commit pentru această lucrare:

git add test_resource.txt
git commit -m „txt pregătit pentru împingere”

Comanda pentru a trimite acest lucru în depozitul de la distanță este:

git push

Atât deocamdată!

Link-uri utile

2. Cum să lucrați cu Git în IntelliJ IDEA

În această parte, veți învăța cum să lucrați cu Git în IntelliJ IDEA.

Intrări necesare:

  1. Citiți, urmăriți și înțelegeți partea anterioară. Acest lucru vă va ajuta să vă asigurați că totul este configurat și gata de funcționare.
  2. Instalați IntelliJ IDEA. Totul ar trebui să fie în ordine aici :)
  3. Alocați o oră pentru a obține o stăpânire completă.

Să lucrăm cu proiectul demonstrativ pe care l-am folosit pentru articolul despre Git.

Clonează proiectul la nivel local

Există două opțiuni aici:

  1. Dacă aveți deja un cont GitHub și doriți să împingeți ceva mai târziu, este mai bine să forkați proiectul și să vă clonați propria copie. Puteți citi despre cum să creați o furcă într-un alt articol sub titlul Un exemplu de flux de lucru de bifurcație .
  2. Clonează depozitul și face totul local, fără a putea împinge totul pe server.

Pentru a clona un proiect din GitHub, trebuie să copiați linkul proiectului și să îl transmiteți către IntelliJ IDEA:

  1. Copiați adresa proiectului:

  2. Deschideți IntelliJ IDEA și selectați „Obțineți de la Controlul versiunii”:

  3. Copiați și lipiți adresa proiectului:

  4. Vi se va solicita să creați un proiect IntelliJ IDEA. Acceptați oferta:

  5. Deoarece nu există un sistem de construcție, selectăm „Creează proiect din surse existente”:

  6. În continuare veți vedea acest ecran frumos:

Acum că ne-am dat seama de clonare, puteți arunca o privire în jur.

Prima vedere la IntelliJ IDEA ca interfață de utilizare Git

Aruncați o privire mai atentă la proiectul clonat: puteți obține deja o mulțime de informații despre sistemul de control al versiunilor.

În primul rând, avem panoul Control versiuni în colțul din stânga jos. Aici puteți găsi toate modificările locale și puteți obține o listă de commit-uri (analog cu „git log”).

Să trecem la o discuție despre Log. Există o anumită vizualizare care ne ajută să înțelegem exact cum a decurs dezvoltarea. De exemplu, puteți vedea că o nouă ramură a fost creată cu un antet adăugat la txt commit, care a fost apoi îmbinat în ramura principală. Dacă dați clic pe un commit, puteți vedea în colțul din dreapta toate informațiile despre commit: toate modificările și metadatele acestuia.

Mai mult, puteți vedea modificările reale. Vedem și că acolo s-a rezolvat un conflict. IDEA prezintă și acest lucru foarte bine.

Dacă faceți dublu clic pe fișierul care a fost modificat în timpul acestei comiteri, vom vedea cum a fost rezolvat conflictul:

Remarcăm că în stânga și în dreapta avem cele două versiuni ale aceluiași fișier care trebuiau îmbinate într-una singură. Și la mijloc, avem rezultatul final fuzionat.

Când un proiect are multe ramuri, comite-uri și utilizatori, trebuie să căutați separat după ramură, utilizator și dată:

Înainte de a începe, merită de asemenea să explicăm cum să înțelegem în ce ramură ne aflăm.

În colțul din dreapta jos, există un buton etichetat „Git: master”. Orice urmează „Git:” este ramura curentă. Dacă faceți clic pe butonul, puteți face o mulțime de lucruri utile: treceți la o altă ramură, creați una nouă, redenumiți una existentă și așa mai departe.

Lucrul cu un depozit

Taste rapide utile

Pentru lucrări viitoare, trebuie să vă amintiți câteva taste rapide foarte utile:

  1. CTRL+T — Obțineți cele mai recente modificări din depozitul de la distanță (git pull).
  2. CTRL+K — Creați un commit / vedeți toate modificările curente. Aceasta include atât fișierele neurmărite, cât și cele modificate (git commit).
  3. CTRL+SHIFT+K — Aceasta este comanda pentru introducerea modificărilor în depozitul de la distanță. Toate commit-urile create local și care nu sunt încă în depozitul de la distanță vor fi împins (git push).
  4. ALT+CTRL+Z — Rollback modificările dintr-un anumit fișier la starea ultimei comitere create în depozitul local. Dacă selectați întregul proiect în colțul din stânga sus, puteți anula modificările din toate fișierele.

Ce vrem noi?

Pentru a finaliza munca, trebuie să stăpânim un scenariu de bază care este folosit peste tot.

Obiectivul este de a implementa o nouă funcționalitate într-o ramură separată și apoi de a o împinge într-un depozit de la distanță (atunci trebuie să creați și o cerere de extragere în ramura principală, dar asta depășește scopul acestei lecții).

Ce este necesar pentru a face asta?

  1. Obțineți toate modificările curente în ramura principală (de exemplu, „master”).

  2. Din această ramură principală, creați o ramură separată pentru munca dvs.

  3. Implementați noua funcționalitate.

  4. Mergeți la filiala principală și verificați dacă au existat modificări noi în timp ce lucram. Dacă nu, atunci totul este în regulă. Dar dacă au existat modificări, atunci facem următoarele: mergeți la ramura de lucru și rebazați modificările de la ramura principală la a noastră. Dacă totul merge bine, atunci grozav. Dar este cu totul posibil să apară conflicte. După cum se întâmplă, pot fi rezolvate în avans, fără a pierde timp în depozitul de la distanță.

    Te întrebi de ce ar trebui să faci asta? Sunt bune maniere și previne apariția conflictelor după ce vă împingeți ramura către depozitul local (există, desigur, posibilitatea ca conflictele să apară în continuare, dar devine mult mai mică ).

  5. Introduceți modificările în depozitul de la distanță.

Cum să obțineți modificări de la serverul de la distanță?

Am adăugat o descriere la README cu un nou commit și dorim să obținem aceste modificări. Dacă s-au făcut modificări atât în ​​depozitul local, cât și în cel la distanță, atunci suntem invitați să alegem între o îmbinare și o rebase. Alegem să unim.

Introduceți CTRL+T :

Acum puteți vedea cum s-a schimbat README, adică au fost introduse modificările din depozitul de la distanță, iar în colțul din dreapta jos puteți vedea toate detaliile modificărilor care au venit de la server.

Creați o nouă ramură bazată pe master

Totul este simplu aici.

Mergeți în colțul din dreapta jos și faceți clic pe Git: master . Selectați + Filială nouă .

Lăsați caseta de selectare Checkout branch selectată și introduceți numele noii filiale. În cazul nostru: acesta va fi readme-improver .

Git: master se va schimba apoi în Git: readme-improver .

Să simulăm lucrul paralel

Pentru ca conflictele să apară, cineva trebuie să le creeze.

Vom edita README cu un nou commit prin browser, simulând astfel lucrul paralel. Este ca și cum cineva a făcut modificări în același fișier în timp ce lucram la el. Rezultatul va fi un conflict. Vom elimina cuvântul „fully” din rândul 10.

Implementați funcționalitatea noastră

Sarcina noastră este să schimbăm README și să adăugăm o descriere noului articol. Adică, munca în Git trece prin IntelliJ IDEA. Adaugă asta:

Modificările sunt făcute. Acum putem crea un commit. Apăsați CTRL+K , ceea ce ne oferă:

Înainte de a crea un commit, trebuie să aruncăm o privire atentă la ceea ce oferă această fereastră.

În secțiunea Commit Message , scriem text asociat cu commit-ul. Apoi, pentru a-l crea, trebuie să facem clic pe Commit .

Scriem că README s-a schimbat și creăm commit-ul. În colțul din stânga jos apare o alertă cu numele comiterii:

Verificați dacă ramura principală s-a schimbat

Ne-am îndeplinit sarcina. Funcționează. Am scris teste. Totul e bine. Dar înainte de a apăsa pe server, trebuie să verificăm dacă au existat modificări în ramura principală între timp. Cum s-ar putea întâmpla asta? Destul de ușor: cineva primește o sarcină după tine și acel cineva o termină mai repede decât îți termini tu sarcina.

Deci trebuie să mergem la filiala principală. Pentru a face acest lucru, trebuie să facem ceea ce este afișat în colțul din dreapta jos în captura de ecran de mai jos:

În ramura principală, apăsați CTRL+T pentru a obține cele mai recente modificări de la serverul de la distanță. Privind care sunt modificările, puteți vedea cu ușurință ce s-a întâmplat:

Cuvântul „fully” a fost eliminat. Poate cineva de la marketing a decis că nu trebuie scris așa și a dat dezvoltatorilor sarcina de a-l actualiza.

Acum avem o copie locală a celei mai recente versiuni a ramului principal. Reveniți la readme-improver .

Acum trebuie să rebazăm modificările de la ramura principală la a noastră. Facem asta:

Dacă ați făcut totul corect și ați urmat împreună cu mine, rezultatul ar trebui să arate un conflict în fișierul README:

Aici avem și o mulțime de informații de înțeles și de absorbit. Afișată aici este o listă de fișiere (în cazul nostru, un fișier) care au conflicte. Putem alege dintre trei variante:

  1. accept-l pe al tău — acceptă numai modificările din readme-improver.
  2. acceptă-le pe ale lor — acceptă doar schimbările de la stăpân.
  3. îmbinare — alege-te ce vrei să păstrezi și ce să renunți.

Nu este clar ce s-a schimbat. Dacă există modificări sunt ramura principală, ele trebuie să fie necesare acolo, așa că nu putem să ne acceptăm pur și simplu modificările. În consecință, selectăm îmbinare :

Aici putem vedea că există trei părți:

  1. Acestea sunt modificările de la readme-improver.
  2. Rezultatul îmbinat. Deocamdată, este ceea ce exista înainte de schimbări.
  3. Schimbările din ramura master.

Trebuie să producem un rezultat îmbinat care să mulțumească pe toată lumea. Analizând ceea ce a fost schimbat ÎNAINTE de modificările noastre, ne dăm seama că pur și simplu au eliminat cuvântul „fully”. Bine nici o problema! Asta înseamnă că îl vom elimina și din rezultatul îmbinat și apoi vom adăuga modificările noastre. Odată ce corectăm rezultatul îmbinat, putem face clic pe Aplicare .

Apoi va apărea o notificare, care ne spune că rebazarea a avut succes:

Acolo! Am rezolvat primul nostru conflict prin IntelliJ IDEA.

Împingeți modificările către serverul de la distanță

Următorul pas este să împingeți modificările către serverul de la distanță și să creați o cerere de extragere. Pentru a face acest lucru, apăsați pur și simplu CTRL+SHIFT+K . Atunci obținem:

În stânga, va apărea o listă de comiteri care nu au fost trimise în depozitul de la distanță. În dreapta vor fi toate fișierele care s-au schimbat. Si asta e! Apăsați Push și veți experimenta fericirea :)

Dacă împingerea are succes, veți vedea o notificare ca aceasta în colțul din dreapta jos:

Bonus: crearea unei cereri de tragere

Să mergem la un depozit GitHub și vedem că GitHub știe deja ce vrem:

Faceți clic pe Comparați și extrageți cererea . Apoi faceți clic pe Creare cerere de extragere . Deoarece am rezolvat conflictele în avans, acum, când creăm o cerere de extragere, o putem îmbina imediat:

Atât deocamdată!