Prima parte a acestei serii a analizat funcționarea interioară a GIT și ți-a arătat cum să nu-ți fie frică să lucrezi cu Git.

Acum, că înțelegem cum funcționează Git, să intrăm în lucrurile cărnoase: cum să valorificăm ceea ce știm în proiectele noastre.

Conţinut

Combina

Combina fuzionează Codul tau.

Amintiți-vă cum am urmat bunele practici Git, având ramuri pentru diverse funcții la care lucram și nu totul master? Va veni un moment când ați terminat cu acea caracteristică și veți dori să o includeți în master. Aici e locul merge intră. Vrei combina ramura ta în stăpân.

Există 2 tipuri de fuziuni:

Combinare rapidă înainte

Revenind la exemplul nostru de ultima dată:

Acest lucru este la fel de simplu ca mutarea etichetei pentru master la the-ending. Git nu are nicio îndoială cu privire exact la ceea ce trebuie făcut – deoarece „arborele” nostru avea o singură listă legată de noduri.

$ git branch
  master
* the-ending
$ git checkout master
Switched to branch 'master'
$ git merge the-ending
Updating a39b9fd..b300387
Fast-forward
 byeworld | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 byeworld

Îmbinarea non-rapidă înainte

Acesta este genul de fuziune în care Git nu știe ce să facă. Există câteva modificări pe ramura de bază, iar altele pe ramura pe care dorim să le îmbinăm, rezultând astfel înfricoșător fuzionează conflicte!

Iată primul lucru pe care trebuie să-l știți despre conflictele de fuziune: dacă nu știți ce se întâmplă:

git merge --abort

Acest lucru vă va readuce la starea inițială, fără efecte secundare. Tocmai ai întrerupt mizeria pe care urmai să o faci.

Acum ca nu va mai este frica de GIT iata
Nu vrei să fii Brian?

Să trecem pas cu pas acum la modul de rezolvare a conflictelor de îmbinare.

$ git checkout -b the-middle
Switched to a new branch 'the-middle'

Continuând stilul nostru, să învățăm printr-un exemplu. Modific helloworld pe ramură the-middle.

$ git diff
diff --git a/helloworld b/helloworld
index a042389..e702052 100644
--- a/helloworld
+++ b/helloworld
@@ -1 +1,3 @@
 hello world!
+
+Middle World

Adăugați și comiteți the-middle.

Apoi, trec la master și modificați helloworld pe stăpân. Adăug următoarele:

$ git diff --cached
diff --git a/helloworld b/helloworld
index a042389..ac7a733 100644
--- a/helloworld
+++ b/helloworld
@@ -1 +1,3 @@
 hello world!
+
+Master World

Vezi de ce a trebuit să fac git diff --cached aici? Dacă nu, întreabă-mă mai jos!

Acum, este timpul să fuzionăm!

$ git merge the-middle
Auto-merging helloworld
CONFLICT (content): Merge conflict in helloworld
Automatic merge failed; fix conflicts and then commit the result.

Când un merge nu reușește, iată ce face git: modifică fișierul cu îmbinarea pentru a vă arăta exact ce nu poate decide.

$ cat helloworld hello world!
$ cat helloworld 
hello world!
<<<<<<< HEAD
Master World
=======
Middle World
>>>>>>> the-middle

Are vreun sens? <<<<< HEAD partea este a noastră (ramura de bază) și >>>>> the-middle part este theirs (ramura care fuzionează în ramura de bază).

Puteți pur și simplu să editați fișierul pentru a elimina lucrurile suplimentare adăugate de git și să alegeți în ce ar trebui să intre helloworld in cele din urma. Există câteva instrumente și integrări de editor pentru a face acest lucru mai ușor, dar cred că știind cum funcționează sub capotă vă oferă mai multă încredere atunci când nu aveți editorul preferat.

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)
Unmerged paths:
  (use "git add <file>..." to mark resolution)
both modified:   helloworld

Am decis să păstrez ambele biți.

$ cat helloworld 
hello world!
Master World
Middle World

Și iată-l:

$ git add helloworld 
$ git commit -m "resolve merge conflict"
[master c747e68] resolve merge conflict

Telecomandele

Deoarece o putere a controlului sursei versiunii este salvarea codului dvs. în caz de dezastre – telecomandele sunt aici pentru a vă ajuta. O telecomandă este o copie găzduită extern a depozitului dvs. git. Pentru a fi mai precis, o telecomandă este un depozit extern (nu neapărat din același cod pe care îl aveți). Prin extern, ar putea fi într-un folder diferit de pe sistemul dvs. sau din cloud.

Clonează

Clonează clone depozitul de la distanță în directorul dvs. curent de lucru. Aceasta este pur și simplu crearea unei copii a fișierului .git/ folder, care ne oferă întregul istoric și fișierele necesare pentru a completa directorul de lucru.

git clone <repository-url>

Dacă nu ați clonat, probabil că nu aveți telecomandă. Puteți crea o telecomandă astfel:

git remote add <name> <url>

Impinge si trage

Push and Pull sunt acțiuni aplicate pe remote.

Apăsați împinge modificările dvs. la telecomandă. Deci, trimitem Index și corespunzătoare Objects din magazinul de obiecte!

git push <name of remote> <name of branch>

Trage trage codul de pe telecomandă. Exact ca înainte, copiem Index și corespunzătoare Objects din magazinul de obiecte!

git pull origin master

origin este numele implicit al telecomenzii. Și de atunci master este ramura implicită, puteți vedea cum comanda se transformă în numele simplu pe care îl găsim peste tot: git pull origin master. Acum știi mai bine.

Resetați

Resetați resetează baza de cod la o versiune anterioară. Resetarea vine cu 3 steaguri:

--soft, --hard și --mixed.

Frumusețea reset, este capabil să schimbe istoria. Spuneți că faceți o greșeală cu un commit, și acum al tău git log totul este încurcat cu comiteri precum:

Bugfix

Final BugFix

Final Final BugFix

God why isn't this working last try bug fix

Dacă doriți să vă păstrați master istoric curat, doriți să curățați acest jurnal de comitere.

Dacă trimiteți o cerere de tragere unde nu există zdrobire, s-ar aștepta și la un istoric de comitere curat!

Acolo este reset vine în: Ai putea reset toate validările dvs. și convertiți-le într-o singură validare: got sh*t done!

(Vă rugăm să nu utilizați acest lucru ca mesaj de confirmare – urmați cele mai bune practici!)

Revenind la exemplul nostru, iată ce am făcut.

$ git log
commit 959781ec78c970d4797c5e938ec154de44d0151b (HEAD -> master)
Author: Neil Kakkar
Date:   Mon Nov 5 07:32:55 2018 +0000
God why isn't this working last final BugFix
commit affa90c0db78999d22c326fdbd6c1d5057228822
Author: Neil Kakkar
Date:   Mon Nov 5 07:32:19 2018 +0000
Final Final BugFix
commit 2e9570cffc0a8206132d75c402d68351eda450bd
Author: Neil Kakkar
Date:   Mon Nov 5 07:31:49 2018 +0000
Final BugFix
commit 4560fc0ec6305d0b7bcfb4be1901438fd126d6d1
Author: Neil Kakkar
Date:   Mon Nov 5 07:31:21 2018 +0000
BugFix
commit c747e6891af419119fd817dc69a2e122084aedae
Merge: 3d01508 fb8b2fc
Author: Neil Kakkar
Date:   Tue Oct 23 07:44:09 2018 +0100
resolve merge conflict

Acum, când bug-ul a fost remediat, vreau să-mi curăț istoricul înainte să mă apuc master. Și asta ar funcționa bine – când, să zicem, îmi dau seama mai târziu că am introdus o altă eroare și trebuie să revin la versiunea anterioară. În acest caz, c747e689 nu are cel mai bun mesaj de confirmare pentru a înțelege acest lucru.

$ git reset c747e6891af419119fd817dc69a2e122084aedae
$ git log
commit c747e6891af419119fd817dc69a2e122084aedae (HEAD -> master)
Merge: 3d01508 fb8b2fc
Author: Neil Kakkar
Date:   Tue Oct 23 07:44:09 2018 +0100
resolve merge conflict

Acolo, totul sortat?

$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
      clean.txt
nothing added to commit but untracked files present (use "git add" to track)

clean.txt este fișierul pe care l-am comis pentru remedierea erorilor. Acum, tot ce trebuie să fac este:

$ git add clean.txt 
$ git commit -m "fix bug: Unable to clean folder"
[master d8487ca] fix bug: Unable to clean folder
 1 file changed, 4 insertions(+)
 create mode 100644 clean.txt
$ git log
commit d8487ca8b9acfa9666bdf2c6b7fa27b3971bd957 (HEAD -> master)
Author: Neil Kakkar
Date:   Mon Nov 5 07:41:41 2018 +0000
fix bug: Unable to clean folder
commit c747e6891af419119fd817dc69a2e122084aedae
Merge: 3d01508 fb8b2fc
Author: Neil Kakkar
Date:   Tue Oct 23 07:44:09 2018 +0100
resolve merge conflict

Acolo, gata și prăfuită. Poți ghici acum, folosind indicii din log, reset sintaxa comenzii și simțul tehnic pentru a afla cum funcționează în culise?

Reset întrerupe arborele de commit la commit specificat. Toate etichetele pentru acea ramură – dacă sunt înainte – sunt mutate înapoi la validarea specificată. Fișierele existente rămân însă în depozitul de obiecte? Știi cum să verifici asta acum, Ace.

Fișierele sunt, de asemenea, eliminate din zona intermediară. Acum, aceasta ar putea fi o problemă dacă aveți o mulțime de fișiere netracked / modificate pe care nu doriți să le adăugați.

Cum faci asta?

Puteți prelua indiciul pe care l-am lăsat la începutul acestei secțiuni?

Steaguri de comportament!

--soft păstrează toate fișierele organizate.

$ git reset --soft c747e6891af419119fd817dc69a2e122084aedae
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
new file:   clean.txt

--mixed este valoarea implicită: elimină toate fișierele din zona intermediară.

--hard este hard-core. Șterge fișierele din depozitul de obiecte – și din director. Utilizați cu extremă precauție. Acolo merge remedierea erorilor mele *. Plecat.

$ git reset --hard c747e6891af419119fd817dc69a2e122084aedae
HEAD is now at c747e68 resolve merge conflict
$ git status
On branch master
nothing to commit, working tree clean

* Ei bine, nu complet. Git este uimitor. Ați auzit de meta-meta date? Un jurnal de redundanță cu ceea ce s-a întâmplat în depozit? Da, desigur git o păstrează!

$ git reflog
c747e68 (HEAD -> master) HEAD@{0}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae
efc6d21 HEAD@{1}: commit: soft reset
c747e68 (HEAD -> master) HEAD@{2}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae
d8487ca HEAD@{3}: commit: fix bug: Unable to clean folder
c747e68 (HEAD -> master) HEAD@{4}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae
959781e HEAD@{5}: commit: God why isn't this working last final BugFix
affa90c HEAD@{6}: commit: Final Final BugFix
2e9570c HEAD@{7}: commit: Final BugFix
4560fc0 HEAD@{8}: commit: BugFix
c747e68 (HEAD -> master) HEAD@{9}: commit (merge): resolve merge conflict
3d01508 HEAD@{10}: commit: add Master World
b300387 (the-ending) HEAD@{11}: checkout: moving from the-middle to master
fb8b2fc (the-middle) HEAD@{12}: commit: add Middle World
b300387 (the-ending) HEAD@{13}: checkout: moving from master to the-middle
b300387 (the-ending) HEAD@{14}: checkout: moving from the-middle to master
b300387 (the-ending) HEAD@{15}: checkout: moving from master to the-middle
b300387 (the-ending) HEAD@{16}: merge the-ending: Fast-forward
a39b9fd HEAD@{17}: checkout: moving from the-ending to master
b300387 (the-ending) HEAD@{18}: checkout: moving from master to the-ending
a39b9fd HEAD@{19}: checkout: moving from the-ending to master
b300387 (the-ending) HEAD@{20}: commit: add byeworld
a39b9fd HEAD@{21}: checkout: moving from master to the-ending
a39b9fd HEAD@{22}: commit (initial): Add helloworld

Aceasta este totul de la începutul exemplului din articolul anterior. Înseamnă asta că pot recupera lucrurile dacă am făcut o greșeală îngrozitoare?

$ git checkout d8487ca
Note: checking out 'd8487ca'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at d8487ca... fix bug: Unable to clean folder

$ ls
byeworld clean.txt  helloworld

Iată-l.

Felicitări, ești Git Ninja – Ucenic acum.

Mai ai ceva despre care ai vrea să știi? Ceva care te-a încurcat despre Git? Anunță-mă mai jos! Voi încerca să-l explic așa cum l-am învățat!

Ti-a placut asta? Nu ratați din nou o postare – abonați-vă la lista mea de e-mail!