Kako razumeti in rešiti konflikte v Gitu

Tu je beseda, ki jo vsak razvijalec sovraži: konflikt. The Pri delu z Gitom (ali drugimi sistemi za nadzor različic) preprosto ni mogoče obiti občasnega spoja med spajanjem.

Ko pa se pogovarjam z razvijalci, pogosto slišim, da je okoli teme spojev združitev občutek tesnobe ali nelagodja .

Reševanje konfliktov pogosto ostaja temno, skrivnostno mesto: situacija, ko se stvari močno zlomijo in ni jasno, kako se iz njih rešiti (ne da bi stvari še poslabšale).

Res je, da so konflikti pri združevanju neizogiben del življenja razvijalca, vendar je nelagodje v teh situacijah povsem neobvezno.

Moj namen s tem člankom je pojasniti to temo: kako in kdaj se običajno pojavijo konflikti, kakšni so dejansko in kako jih rešiti - ali razveljaviti.

Ko boste pravilno razumeli te stvari, se boste lahko spopadov spojev spopadali na veliko bolj sproščen in samozavesten način. ?

Kako in kdaj pride do konfliktov

Že ime pove: v konfliktnem združevanju lahko pride do integracije prevzema iz drugega vira.

Upoštevajte pa, da "integracija" ni omejena le na "združevanje vej". To se lahko zgodi tudi pri ponovnem podstavku ali interaktivnem ponovnem podstavku, pri nabiranju češenj ali vlečenju ali celo pri ponovnem nanašanju zaloge.

Vsa ta dejanja izvedejo nekakšno integracijo - in takrat se lahko zgodijo konflikti med spajanjem.

Seveda pa ta dejanja ne povzročijo vsakič konflikta med spajanjem (hvala bogu!) Idealno bi bilo, da bi se v teh situacijah znašli le redko. Kdaj pa točno pride do konfliktov?

Pravzaprav so Gitove zmožnosti združevanja ena največjih prednosti: združevanje vej večino časa deluje brez napora, saj Git običajno lahko sam ugotovi stvari.

Vendar obstajajo situacije, ko so se zgodile nasprotujoče si spremembe - in ko tehnologija preprosto ne more odločiti, kaj je prav ali ne. Te situacije preprosto zahtevajo odločitev človeka.

Prava klasika je, ko je bila popolnoma ista vrstica kode spremenjena v dveh zavezah, v dveh različnih vejah. Git nikakor ne more vedeti, katera sprememba vam je ljubša! ?

Obstajajo še nekatere druge podobne situacije - na primer, ko je bila datoteka spremenjena v eni veji in izbrisana v drugi, vendar so nekoliko manj pogoste.

"Tower" Git desktop GUI , na primer, ima lep način vizualizacije tovrstnih primerih:

Kako vedeti, kdaj je prišlo do konflikta

Ne skrbite: Git vam bo zelo jasno povedal, kdaj je prišlo do konflikta. ?  

Najprej vas bo takoj obvestil v situaciji , na primer, če združitev ali ponovna zbirka podatkov ne uspe zaradi konflikta:

$ 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.

Kot lahko vidite iz zgornjega primera, ko sem poskušal izvesti združitev, sem ustvaril konflikt združevanja - in Git težavo sporoči zelo jasno in hitro:

  • Prišlo je do konflikta v datoteki "index.html".
  • Pojavil se je še en spor v datoteki "error.html".
  • In končno, zaradi sporov operacija združitve ni uspela.

To so situacije, ko moramo kopati v kodo in videti, kaj je treba storiti.

V malo verjetnem primeru, da ste spregledali ta opozorilna sporočila, ko se je konflikt zgodil, vas Git ob vsakem zagonu tudi obvesti 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

Z drugimi besedami: ne skrbite, če ne boste opazili konfliktov med spajanjem. Git poskrbi, da jih ne boste mogli spregledati.

Kako razveljaviti konflikt v Gitu in začeti znova

Konflikti pri združitvi prihajajo z določeno nujnostjo. In upravičeno: z njimi se boste morali spoprijeti, preden lahko nadaljujete z delom.

A čeprav njihovo ignoriranje ni mogoče, "spopadanje s konflikti združevanja" ne pomeni nujno, da jih morate rešiti. Možno jih je tudi razveljaviti !

To bi bilo vredno ponoviti: vedno imate možnost razveljaviti konflikt združevanja in se prej vrniti v stanje. To velja tudi, ko ste že začeli reševati sporne datoteke in se znajdete v slepi ulici.

V teh situacijah je dobro vedeti, da lahko vedno začnete znova in se vrnete v čisto stanje, še preden se je konflikt sploh zgodil.

For this purpose, most commands come with an --abort option, for example git merge --abort and git rebase --abort:

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

This should give you the confidence that you really cannot mess up. You can always abort, return to a clean state, and start over.

What Conflicts Really Look Like in Git

Now, safe in the knowledge that nothing can break, let's see what a conflict really looks like under the hood. This will demystify those little buggers and, at the same time, help you lose respect for them and gain confidence in yourself.

As an example, let's look at the contents of the (currently conflicted) "index.html" file in an editor:

Git was kind enough to mark the problem area in the file, enclosing it in <<<<<<< HEAD and >>>>>>> [other/branch/name]. The content that comes after the first marker originates from our current working branch. Finally, a line with ======= characters separates the two conflicting changes.

How to Solve a Conflict in Git

Our job as developers now is to clean up these lines: after we're finished, the file has to look exactly as we want it to look.

It might be necessary to talk to the teammate who wrote the "other" changes and decide which code is actually correct. Maybe it's ours, maybe it's theirs - or maybe a mixture between the two.

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 je izvršni direktor podjetja Tower, priljubljenega namiznega odjemalca Git, ki pomaga več kot 100.000 razvijalcem po vsem svetu, da so z Gitom bolj produktivni.