Sådan forstås og løses konflikter i Git

Der er det ordet, som enhver udvikler hader at se: konflikt. ? Der er bare ingen vej rundt lejlighedsvis sammenfletningskonflikt, når du arbejder med Git (eller andre versionskontrolsystemer).

Men når jeg taler med udviklere, hører jeg ofte, at der er en følelse af angst eller ubehag omkring emnet fusionskonflikter.

Håndtering af konflikter forbliver ofte et mørkt, mystisk sted: en situation, hvor ting er hårdt brudt, og det er uklart, hvordan man kommer ud af det (uden at gøre tingene værre).

Selvom det er sandt, at fletningskonflikter er en uundgåelig del af en udviklers liv, er ubehaget i disse situationer helt valgfrit.

Min hensigt med denne artikel er at skabe klarhed over dette emne: hvordan og hvornår konflikter typisk opstår, hvad de faktisk er, og hvordan man løser - eller fortryder - dem.

Når du forstår disse ting korrekt, vil du være i stand til at håndtere fletkonflikter på en meget mere afslappet og selvsikker måde. ?

Hvordan og hvornår konflikter opstår

Navnet siger det allerede: "sammenfletningskonflikter" kan forekomme i processen med at integrere forpligtelser fra en anden kilde.

Husk dog, at "integration" ikke er begrænset til kun "sammenlægning af grene". Det kan også ske, når rebasing eller interaktiv rebasing, når du udfører en cherry-pick eller en pull, eller endda når du anvender en Stash igen.

Alle disse handlinger udfører en eller anden form for integration - og det er, når sammenlægningskonflikter kan ske.

Men selvfølgelig resulterer disse handlinger ikke i en fusionskonflikt hver gang (gudskelov!). Ideelt set bør du kun være sjældent i disse situationer. Men hvornår opstår der konflikter nøjagtigt?

Faktisk er Gits fusioneringsfunktioner en af ​​de største fordele: Fusionering af filialer fungerer ubesværet det meste af tiden, fordi Git normalt er i stand til at finde ud af tingene alene.

Men der er situationer, hvor der blev foretaget modstridende ændringer - og hvor teknologien simpelthen ikke kan bestemme, hvad der er rigtigt eller forkert. Disse situationer kræver simpelthen en beslutning fra et menneske.

Den ægte klassiker er, når nøjagtig samme linje kode blev ændret i to forpligtelser på to forskellige grene. Git har ingen måde at vide, hvilken ændring du foretrækker! ?

Der er nogle andre lignende situationer - for eksempel når en fil blev ændret i en gren og slettet i en anden - men de er lidt mindre almindelige.

Den "Tower" Git skrivebordet GUI , for eksempel, har en pæn måde at visualisere den slags situationer:

Hvordan man ved, hvornår en konflikt er opstået

Bare rolig: Git fortæller dig meget tydeligt, hvornår en konflikt er sket. ?  

For det første vil det fortælle dig straks i situationen , for eksempel når en fusion eller rebase mislykkes på grund af 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 ovenstående eksempel, da jeg forsøgte at udføre en fusion, oprettede jeg en fusionskonflikt - og Git kommunikerer problemet meget tydeligt og hurtigt:

  • Der opstod en konflikt i filen "index.html".
  • En anden konflikt i filen "error.html" opstod.
  • Og endelig mislykkedes fusionsoperationen på grund af konflikterne.

Dette er de situationer, hvor vi skal grave i koden og se, hvad der skal gøres.

I det usandsynlige tilfælde, at du har overset disse advarselsmeddelelser, da konflikten opstod, informerer Git dig desuden, når du løber 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: skal du ikke bekymre dig om ikke at lægge mærke til fusionskonflikter. Git sørger for, at du ikke kan overse dem.

Sådan fortrydes en konflikt i Git og starter forfra

Fusionskonflikter kommer med en vis hastende karakter. Og med rette: du bliver nødt til at håndtere dem, før du kan fortsætte med dit arbejde.

Men selvom det ikke er en mulighed at ignorere dem, betyder "håndtering af fusionskonflikter" ikke nødvendigvis, at du er nødt til at løse dem. Det er også muligt at fortryde dem!

Dette kan være værd at gentage: du har altid mulighed for at fortryde en fusionskonflikt og vende tilbage til staten før. Dette gælder, selv når du allerede er begyndt at løse de konfliktfiler og befinder dig i en blindgyde.

I disse situationer er det dejligt at huske på, at du altid kan starte forfra og vende tilbage til en ren tilstand, før konflikten endda skete.

Til dette formål kommer de fleste kommandoer med en --abortmulighed, for eksempel git merge --abortog git rebase --abort:

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

Dette skal give dig tillid til, at du virkelig ikke kan ødelægge. Du kan altid afbryde, vende tilbage til en ren tilstand og starte forfra.

Hvordan konflikter virkelig ser ud i Git

Lad os nu se, hvordan en konflikt virkelig ser ud under emhætten , sikker på at intet kan bryde . Dette vil afmystificere de små buggere og på samme tid hjælpe dig med at miste respekt for dem og få tillid til dig selv.

Lad os som et eksempel se på indholdet af filen (i øjeblikket modstridende) "index.html" i en editor:

Git var venlig nok til at markere problemområdet i filen og omslutte det i <<<<<<< HEADog >>>>>>> [other/branch/name]. Indholdet, der kommer efter den første markør, stammer fra vores nuværende arbejdsområde. Endelig =======adskiller en linje med tegn de to modstridende ændringer.

Sådan løses en konflikt i Git

Vores job som udviklere er nu at rydde op i disse linjer: Når vi er færdige, skal filen se nøjagtigt ud, som vi vil have den til at se ud.

Det kan være nødvendigt at tale med holdkammeraten, der skrev de "andre" ændringer og beslutte, hvilken kode der faktisk er korrekt. Måske er det vores, måske er det deres - eller måske en blanding mellem 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 for Tower, den populære Git desktop-klient, der hjælper mere end 100.000 udviklere over hele verden til at være mere produktive med Git.