Hvordan forstå og løse konflikter i Git

Der er det ordet som hver utvikler hater å se: konflikt. ? Det er bare ingen vei rundt en og annen sammenslåingskonflikt når du arbeider med Git (eller andre versjonskontrollsystemer).

Men når jeg snakker med utviklere, hører jeg ofte at det er en følelse av angst eller ubehag rundt emnet sammenslåingskonflikter.

Håndtering av konflikter forblir ofte et mørkt, mystisk sted: en situasjon der ting er hardt ødelagte og det er uklart hvordan man kommer ut av det (uten å gjøre ting verre).

Selv om det er sant at sammenslåingskonflikter er en uunngåelig del av en utviklers liv, er ubehaget i disse situasjonene helt valgfritt.

Min intensjon med denne artikkelen er å bringe litt klarhet i dette emnet: hvordan og når konflikter vanligvis oppstår, hva de faktisk er, og hvordan man kan løse - eller angre dem.

Når du forstår disse tingene riktig, vil du kunne håndtere sammenslåingskonflikter på en mye mer avslappet og trygg måte. ?

Hvordan og når konflikter oppstår

Navnet sier det allerede: "flette konflikter" kan oppstå i prosessen med å integrere forpliktelser fra en annen kilde.

Husk imidlertid at "integrering" ikke er begrenset til bare "sammenslåing av grener". Det kan også skje ved rebasing eller interaktiv rebasing, når du utfører en cherry-pick eller en pull, eller til og med når du bruker en Stash på nytt.

Alle disse handlingene utfører en slags integrasjon - og det er da sammenslåingskonflikter kan skje.

Men selvfølgelig resulterer ikke disse handlingene i en sammenslåingskonflikt hver gang (takk Gud!). Ideelt sett bør du bare komme sjelden i disse situasjonene. Men når oppstår det konflikter?

Egentlig er Gits sammenslåingskapasitet en av de største fordelene: å slå sammen filialer fungerer uanstrengt det meste av tiden, fordi Git vanligvis er i stand til å finne ut av ting alene.

Men det er situasjoner der det ble gjort motstridende endringer - og hvor teknologien rett og slett ikke kan bestemme hva som er riktig eller galt. Disse situasjonene krever ganske enkelt en beslutning fra et menneske.

Den virkelige klassikeren er når nøyaktig samme kodelinje ble endret i to forpliktelser, på to forskjellige grener. Git har ingen måte å vite hvilken endring du foretrekker! ?

Det er noen andre, lignende situasjoner - for eksempel når en fil ble endret i en gren og slettet i en annen - men de er litt mindre vanlige.

Den "Tower" Git desktop GUI , for eksempel, har en fin måte å visualisere slike situasjoner:

Hvordan vite når en konflikt har oppstått

Ikke bekymre deg: Git vil fortelle deg veldig tydelig når en konflikt har skjedd. ?  

Først vil den fortelle deg umiddelbart i situasjonen , for eksempel når en sammenslåing eller rebase mislykkes på grunn av en konflikt:

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

Som du kan se fra eksemplet ovenfor, da jeg prøvde å utføre en sammenslåing, opprettet jeg en sammenslåingskonflikt - og Git kommuniserer problemet veldig tydelig og raskt:

  • Det oppstod en konflikt i filen "index.html".
  • En annen konflikt i filen "error.html" oppstod.
  • Og til slutt mislyktes fusjonen på grunn av konfliktene.

Dette er situasjonene der vi må grave i koden og se hva som må gjøres.

I det usannsynlige tilfellet at du har oversett disse advarslene når konflikten skjedde, informerer Git deg i tillegg når du løper 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

Med andre ord: ikke bekymre deg for ikke å legge merke til sammenslåingskonflikter. Git sørger for at du ikke kan overse dem.

Hvordan angre en konflikt i Git og starte på nytt

Sammenslåingskonflikter kommer med en viss hast. Og med rette: du må håndtere dem før du kan fortsette arbeidet ditt.

Men selv om å ignorere dem ikke er et alternativ, betyr ikke "å håndtere sammenslåingskonflikter" nødvendigvis at du må løse dem. Å angre dem er også mulig!

Dette kan være verdt å gjenta: du har alltid muligheten til å angre en sammenslåingskonflikt og komme tilbake til staten før. Dette gjelder selv når du allerede har begynt å løse de konfliktfylte filene og befinner deg i en blindvei.

I disse situasjonene er det flott å huske på at du alltid kan starte på nytt og gå tilbake til en ren tilstand før konflikten til og med skjedde.

For dette formålet har de fleste kommandoer et --abortalternativ, for eksempel git merge --abortog git rebase --abort:

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

Dette skal gi deg selvtilliten til at du virkelig ikke kan rote. Du kan alltid avbryte, gå tilbake til en ren tilstand og starte på nytt.

Hvordan konflikter virkelig ser ut i Git

Nå, trygg i kunnskapen om at ingenting kan bryte, la oss se hvordan en konflikt virkelig ser ut under panseret. Dette vil avmystifisere de små buggere og samtidig hjelpe deg med å miste respekt for dem og få tillit til deg selv.

Som et eksempel, la oss se på innholdet i (for tiden motstridende) "index.html" -fil i en redaktør:

Git var snill nok til å markere problemområdet i filen, vedlegge den i <<<<<<< HEADog >>>>>>> [other/branch/name]. Innholdet som kommer etter den første markøren stammer fra vår nåværende arbeidsgren. Til slutt =======skiller en linje med tegn de to motstridende endringene.

Hvordan løse en konflikt i Git

Vår jobb som utviklere nå er å rydde opp i disse linjene: Når vi er ferdige, må filen se ut akkurat slik vi vil at den skal se ut.

Det kan være nødvendig å snakke med lagkameraten som skrev de "andre" endringene og bestemme hvilken kode som faktisk er riktig. Kanskje det er vårt, kanskje det er deres - eller kanskje en blanding mellom de to.

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 er administrerende direktør i Tower, den populære Git desktop-klienten som hjelper mer enn 100.000 utviklere over hele verden til å være mer produktive med Git.