Kaip suprasti ir išspręsti Gito konfliktus

Čia yra žodis, kurio nekenčia matyti kiekvienas kūrėjas: konfliktas. ? Darbo su „Git“ (ar kitomis versijų valdymo sistemomis) atsitiktinių konfliktų nėra.

Bet kalbėdamas su kūrėjais dažnai girdžiu, kad susijungusių konfliktų tema jaučiamas nerimas ar diskomfortas .

Konfliktų tvarkymas dažnai lieka tamsi, paslaptinga vieta: situacija, kai viskas yra labai sugadinta ir neaišku, kaip iš jos išeiti (nepabloginant dalykų).

Nors tiesa, kad susijungimo konfliktai yra neišvengiama kūrėjo gyvenimo dalis, diskomfortas šiose situacijose yra visiškai neprivalomas.

Šiuo straipsniu aš ketinu paaiškinti šią temą: kaip ir kada paprastai kyla konfliktai, kokie jie iš tikrųjų yra ir kaip juos išspręsti ar panaikinti.

Tinkamai supratę šiuos dalykus, galėsite daug lengviau ir užtikrintiau spręsti sujungtus konfliktus. ?

Kaip ir kada vyksta konfliktai

Pavadinimas jau sako: „sujungiant konfliktus“ gali atsirasti integruojant įsipareigojimus iš kito šaltinio.

Nepamirškite, kad „integracija“ neapsiriboja vien „šakų sujungimu“. Tai taip pat gali atsitikti pakartotinai arba interaktyviai, atliekant vyšnių rinkimą ar traukimą ar net pakartotinai naudojant „Stash“.

Visi šie veiksmai atlieka tam tikrą integraciją - tada gali įvykti susijungimo konfliktai.

Bet, žinoma, šie veiksmai nesukelia kaskart susiliejančio konflikto (ačiū Dievui!). Geriausia, jei tokiose situacijose turėtumėte atsidurti tik retai. Bet kada tiksliai kyla konfliktai?

Tiesą sakant, „Git“ sujungimo galimybės yra vienas iš didžiausių jos privalumų: šakų sujungimas dažniausiai veikia be vargo, nes „Git“ paprastai sugeba viską išsiaiškinti pats.

Tačiau yra situacijų, kai buvo atlikti prieštaringi pakeitimai - ir kai technologijos paprasčiausiai negali nuspręsti, kas teisinga ar ne. Šioms situacijoms tiesiog reikia žmogaus sprendimo.

Tikra klasika yra ta, kai ta pati kodo eilutė buvo pakeista dviem vykdymais, dviem skirtingomis šakomis. „Git“ niekaip negali žinoti, kuriam pokyčiui labiau patinka! ?

Yra keletas kitų, panašių situacijų, pavyzdžiui, kai failas buvo modifikuotas viename filiale ir ištrintas kitame, tačiau jie yra šiek tiek rečiau.

Pavyzdžiui, „Tower“ Git darbalaukio GUI yra puikus būdas vizualizuoti tokio pobūdžio situacijas:

Kaip žinoti, kada įvyko konfliktas

Nesijaudinkite: Gitas jums labai aiškiai pasakys, kai įvyko konfliktas. ?  

Pirma, ji iš karto informuos jus apie situaciją , pavyzdžiui, kai susijungimas ar perkrovimas nepavyksta dėl konflikto:

$ git merge develop Auto-merging index.html CONFLICT (content): Merge conflict in index.html CONFLICT (modify/delete): error.html deleted in HEAD and modified in develop. Version develop of error.html left in tree. Automatic merge failed; fix conflicts and then commit the result.

Kaip matote iš aukščiau pateikto pavyzdžio, bandydamas atlikti sujungimą, sukūriau susijungimo konfliktą, o „Git“ labai aiškiai ir greitai praneša apie problemą:

  • Įvyko konfliktas faile „index.html“.
  • Įvyko dar vienas failo „error.html“ konfliktas.
  • Ir galiausiai dėl konfliktų susijungimo operacija nepavyko.

Tai situacijos, kai turime įsigilinti į kodą ir pamatyti, ką reikia padaryti.

Mažai tikėtina, kad įvykio konflikto metu nepastebėjote šių įspėjamųjų pranešimų, „Git“ papildomai informuoja jus, kai paleidžiate git status:

$ git status On branch main You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm ..." as appropriate to mark resolution) deleted by us: error.html both modified: index.html

Kitaip tariant: nesijaudinkite nepastebėję sujungtų konfliktų. Gitas užtikrina, kad negalite jų nepastebėti.

Kaip panaikinti „Git“ konfliktą ir pradėti iš naujo

Sujungimo konfliktai kyla dėl tam tikros skubos. Ir teisingai: prieš pradėdami dirbti, turėsite su jais susidurti.

Nors jų ignoravimas nėra išeitis, „susitvarkyti sujungti konfliktus“ nebūtinai reiškia, kad jūs turite juos išspręsti. Atsukus juos taip pat įmanoma!

Tai gali būti verta pakartoti: visada galite atšaukti sujungimo konfliktą ir grįžti į būseną anksčiau. Tai galioja net tada, kai jau pradėjote spręsti nesuderinamus failus ir atsidūrėte aklavietėje.

Šiose situacijose puiku nepamiršti, kad visada galite pradėti iš naujo ir grįžti į švarią būseną, kol konfliktas dar neįvyko.

Šiuo tikslu, dauguma komandos ateiti su --abortgalimybe, pavyzdžiui, git merge --abortir git rebase --abort:

$ git merge --abort $ git status On branch main nothing to commit, working tree clean

Tai turėtų suteikti jums pasitikėjimo, kad tikrai negalite sujaukti. Visada galite nutraukti, grįžti į švarią būseną ir pradėti iš naujo.

Kaip iš tikrųjų atrodo „Git“ konfliktai

Dabar, saugiai žinodami, kad niekas negali sulūžti, pažiūrėkime, kaip iš tikrųjų atrodo konfliktas po gaubtu. Tai demistifikuos tuos mažus klaidžiotojus ir tuo pačiu padės jums prarasti pagarbą jiems ir įgyti pasitikėjimo savimi.

Pažvelkime į (šiuo metu nesuderinamą) failo „index.html“ turinį redaktoriuje:

Git buvo malonus pažymėti probleminę sritį faile, pridėdamas ją <<<<<<< HEADir >>>>>>> [other/branch/name]. Turinys, atsirandantis po pirmojo žymeklio, kilęs iš mūsų dabartinės darbo šakos. Galiausiai eilutė su =======simboliais skiria du prieštaringus pakeitimus.

Kaip išspręsti Git konfliktą

Mūsų, kaip kūrėjų, darbas dabar yra išvalyti šias eilutes: kai baigsime, failas turi atrodyti tiksliai taip, kaip norime.

Gali tekti pasikalbėti su komandos draugu, kuris parašė „kitus“ pakeitimus, ir nuspręsti, kuris kodas iš tikrųjų teisingas. Gal tai mūsų, gal jų - o gal jųdviejų mišinys.

This process - cleaning up the file and making sure it contains what we actually want - doesn't have to involve any magic. You can do this simply by opening your text editor or IDE and starting to making your changes.

Often, however, you'll find that this is not the most efficient way. That's when dedicated tools can save time and effort:

  • Git GUI Tools: Some of the graphical user interfaces for Git can be helpful when solving conflicts. The Tower Git GUI, for example, offers a dedicated "Conflict Wizard" that helps visualize and solve the situation:
  • Dedicated Merge Tools: For more complicated conflicts, it can be great to have a dedicated "Diff & Merge Tool" at hand. You can configure your tool of choice using the "git config" command. (Consult your tool's documentation for detailed instructions.) Then, in case of a conflict, you can invoke it by simply typing git mergetool. As an example, here's a screenshot of "Kaleidoscope" on macOS:

After cleaning up the file - either manually or in a Git GUI or Merge Tool - we have to commit this like any other change:

  • By using git add on the (previously) conflicted file, we inform Git that the conflict has been solved.
  • When all conflicts have been solved and added to the Staging Area, you need to complete the resolution by creating a regular commit.

How to Become More Confident and Productive

Many years ago, when I started using version control, merge conflicts regularly freaked me out: I was afraid that, finally, I had managed to break things for good. ?

Only when I took the time to truly understand what was going on under the hood was I able to deal with conflicts confidently and efficiently.

The same was true, for example, when dealing with mistakes: only once I learned how to undo mistakes with Git was I able to become more confident and productive in my work.

I highly recommend taking a look at the free "First Aid Kit for Git", a collection of short videos about how to undo and recover from mistakes with Git.

Have fun becoming a better programmer!

About the Author

Tobiasas Güntheris yra „Tower“, populiaraus „Git“ darbalaukio kliento, kuris padeda daugiau nei 100 000 kūrėjų visame pasaulyje būti „Git“ produktyvesnis, generalinis direktorius.