Eto, riječ koju svaki programer mrzi vidjeti: sukob. Just Jednostavno nema načina zaobići povremeni sukob spajanja kada radite s Gitom (ili drugim sustavima za kontrolu verzija).
Ali kad razgovaram s programerima, često čujem da oko teme spajanja spojeva postoji osjećaj tjeskobe ili nelagode .
Rješavanje sukoba često ostaje mračno, tajanstveno mjesto: situacija u kojoj su stvari jako slomljene i nejasno je kako se iz toga izaći (a da se stvari ne pogoršaju).
Iako je istina da su sukobi spajanja nezaobilazan dio života programera, nelagoda u tim situacijama potpuno je neobavezna.
Namjera mi je ovim člankom unijeti malo jasnosti u ovu temu: kako i kada se sukobi obično javljaju, što su zapravo i kako ih riješiti - ili poništiti.
Kad pravilno razumijete ove stvari, moći ćete se nositi s sukobima stapanja na mnogo opušteniji i sigurniji način. ?
Kako i kada se javljaju sukobi
Ime već govori: "sukobi spajanja" mogu se dogoditi u procesu integriranja predavanja iz drugog izvora.
Ipak, imajte na umu da "integracija" nije ograničena samo na "spajanje grana". To se također može dogoditi prilikom ponovnog podnošenja baze ili interaktivnog ponovnog podnošenja, prilikom izvođenja trke ili povlačenja ili čak prilikom ponovnog nanošenja Stash-a.
Sve ove radnje izvode neku vrstu integracije - i tada se mogu dogoditi sukobi spajanja.

Ali naravno, ove radnje ne rezultiraju sukobom spajanja svaki put (hvala Bogu!). Idealno bi bilo da se u tim situacijama nađete rijetko. Ali kada se točno događaju sukobi?
Zapravo, Gitove mogućnosti spajanja jedna su od njegovih najvećih prednosti: spajanje grana većinu vremena radi bez napora, jer Git obično može sam shvatiti stvari.
Ali postoje situacije u kojima su napravljene kontradiktorne promjene - i kada tehnologija jednostavno ne može odlučiti što je ispravno ili ne. Te situacije jednostavno zahtijevaju odluku od čovjeka.
Pravi klasik je kada je potpuno isti redak koda promijenjen u dva predavanja, u dvije različite grane. Git nikako ne može znati koju promjenu više volite! ?
Postoje i neke druge slične situacije - na primjer kada je datoteka izmijenjena u jednoj grani, a izbrisana u drugoj, ali one su nešto rjeđe.
Na primjer, "Tower" Git GUI za radnu površinu ima lijep način vizualizacije takvih situacija:

Kako znati kada je došlo do sukoba
Ne brinite: Git će vam vrlo jasno reći kada se sukob dogodio. ?
Prvo će vas odmah obavijestiti o situaciji , na primjer kada spajanje ili ponovna baza ne uspije zbog sukoba:
$ 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.
Kao što možete vidjeti iz gornjeg primjera, kada sam pokušao izvršiti spajanje, stvorio sam sukob spajanja - i Git vrlo jasno i brzo komunicira s problemom:
- Došlo je do sukoba u datoteci "index.html".
- Dogodio se još jedan sukob u datoteci "error.html".
- I na kraju, zbog sukoba, operacija spajanja nije uspjela.
To su situacije u kojima moramo zakopati u kod i vidjeti što treba učiniti.
U malo vjerojatnom slučaju da ste previdjeli ove poruke upozorenja kad se sukob dogodio, Git vas dodatno obavještava kad god pokrenete 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
Drugim riječima: ne brinite se ako nećete primijetiti sukobe spajanja. Git se brine da ih ne možete previdjeti.
Kako poništiti sukob u Gitu i započeti ispočetka
Sukobi oko spajanja dolaze s određenom hitnošću. I s pravom: morat ćete se nositi s njima prije nego što nastavite s poslom.
No iako njihovo ignoriranje nije opcija, "rješavanje sukoba spajanja" ne znači nužno da ih morate riješiti. Njihovo poništavanje je također moguće!
Ovo bi možda vrijedilo ponoviti: uvijek uvijek imate mogućnost poništiti sukob spajanja i vratiti se u stanje prije. To je istina čak i kad ste već započeli rješavanje sukobljenih datoteka i našli se u slijepoj ulici.
U tim je situacijama sjajno imati na umu da uvijek možete početi ispočetka i vratiti se u čisto stanje prije nego što se sukob uopće dogodio.
U tu svrhu većina naredbi dolazi s --abort
opcijom, na primjer git merge --abort
i git rebase --abort
:
$ git merge --abort $ git status On branch main nothing to commit, working tree clean
To bi vam trebalo dati samopouzdanje da zaista ne možete zabrljati. Uvijek možete prekinuti, vratiti se u čisto stanje i početi ispočetka.
Kako doista izgledaju sukobi u Gitu
Sigurni u spoznaju da se ništa ne može slomiti, pogledajmo kako doista izgleda sukob ispod haube. To će demistificirati te male napasnike i istodobno će vam pomoći da izgubite poštovanje prema njima i steknete povjerenje u sebe.
Kao primjer, pogledajmo sadržaj (trenutno sukobljene) datoteke "index.html" u uređivaču:

Git je bio dovoljno ljubazan da označi problematično područje u datoteci, zatvorivši ga u <<<<<<< HEAD
i >>>>>>> [other/branch/name]
. Sadržaj koji dolazi nakon prvog markera potječe iz naše trenutne radne grane. Konačno, redak sa =======
znakovima razdvaja dvije sukobljene promjene.
Kako riješiti sukob u Gitu
Naš posao programera sada je očistiti ove redove: nakon što završimo, datoteka mora izgledati točno onako kako mi želimo.
Možda će biti potrebno razgovarati sa suigračem koji je napisao "ostale" promjene i odlučiti koji je kôd zapravo točan. Možda je naše, možda je njihovo - ili možda mješavina između njih dvoje.
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
Tobias Günther is the CEO of Tower, the popular Git desktop client that helps more than 100,000 developers around the world to be more productive with Git.