Kaip išspręsti sujungimo konfliktus git

Ar yra geras būdas paaiškinti, kaip išspręsti sujungimo konfliktus git?

4274
02 окт. Spoike rinkinys 02 okt. 2008-10-02 14:31 '08 at 14:31 pm 2008-10-02 14:31
@ 37 atsakymai
  • 1
  • 2

Pabandykite: git mergetool

Jis atveria grafinę sąsają, kuri vyksta per kiekvieną konfliktą, ir galite pasirinkti, kaip derinti. Kartais tai reikalauja šiek tiek rankinio redagavimo, tačiau paprastai tai pakanka. Tai yra daug geriau nei viskas rankiniu būdu.

Pagal @JoshGlover komentarą:

Komanda nebūtinai atidaro GUI, jei ją neįdiegiate. Vykdant git mergetool man naudojosi vimdiff . Galite naudoti vieną iš šių įrankių, kad galėtumėte jį naudoti: meld , opendiff , kdiff3 , tkdiff , xxdiff , tortoisemerge , gvimdiff , ecmerge , p4merge , araxis , vimdiff , vimdiff , emerge .

Žemiau pateikiamas vimdiff panaudojimo procedūros sujungimo konfliktų sprendimo būdas. Pagal šią nuorodą

1 veiksmas : paleiskite šias terminalo komandas

 git config merge.tool vimdiff git config merge.conflictstyle diff3 git config mergetool.prompt false 

Tai nustatys vimdiff kaip numatytąjį suliejimo įrankį.

2 veiksmas : paleiskite šią komandą terminale

 git mergetool 

3 žingsnis : matysite vimdiff ekraną tokiu formatu.

  +----------------------+ | | | | |LOCAL |BASE |REMOTE | | | | | +----------------------+ | MERGED | | | +----------------------+ 

Šie 4 tipai

LOCAL yra failas iš dabartinio filialo.

BASE - bendras protėvis, kaip failas atrodė prieš abu pokyčius

REMOTE - failas, kurį sujungiate į savo filialą

MERGED - susijungimo rezultatas, kuris yra saugomas repo

Galite pereiti tarp šių vaizdų naudodami ctrl+w Galite tiesiogiai pereiti į MERGED vaizdą naudodami ctrl+w ir j .

Daugiau informacijos apie vimdiff navigaciją čia ir čia.

4 žingsnis Galite redaguoti MERGED taip:

Jei norite gauti pakeitimus iš REMOTE

 :diffg RE 

Jei norite gauti pakeitimus iš BASE

 :diffg BA 

Jei norite gauti pakeitimus iš LOCAL

 :diffg LO 

5 žingsnis Išsaugokite, išjunkite, užrakinkite ir išvalykite

:wqa išsaugoti ir išeiti iš vi

git commit -m "message"

git clean Ištrinkite nereikalingus failus (pvz., * .orig), kuriuos sukūrė „diff“ įrankis.

2535
02 окт. atsakymą pateikė Peter Burns 02 okt. 2008-10-02 20:50 '08 at 8:50 pm 2008-10-02 20:50

Čia yra tikėtinas precedentas, iš viršaus:

Jūs ketinate atlikti keletą pakeitimų, bet, deja, jūs nežinote:

 git fetch origin git pull origin master From ssh://gitosis@example.com:22/projectname * branch master -> FETCH_HEAD Updating a030c3a..ee25213 error: Entry 'filename.c' not uptodate. Cannot merge. 

Taigi, atnaujinate ir bandykite dar kartą, bet turite konfliktą:

 git add filename.c git commit -m "made some wild and crazy changes" git pull origin master From ssh://gitosis@example.com:22/projectname * branch master -> FETCH_HEAD Auto-merging filename.c CONFLICT (content): Merge conflict in filename.c Automatic merge failed; fix conflicts and then commit the result. 

Taigi nusprendėte pažvelgti į pakeitimus:

border=0
 git mergetool 

O, aš, oh, mano, prieš tai keičiau kai kuriuos dalykus, bet tiesiog naudoju savo pakeitimus ... ne ... jų pakeitimus ...

 git checkout --ours filename.c git checkout --theirs filename.c git add filename.c git commit -m "using theirs" 

Ir tada bandome paskutinį kartą.

 git pull origin master From ssh://gitosis@example.com:22/projectname * branch master -> FETCH_HEAD Already up-to-date. 

Ta-da!

1625 m
04 авг. atsakymą pateikė CoolAJ86 04 rug . 2010-08-04 20:04 '10, 08:04 PM 2010-08-04 20:04

Manau, kad sujungimo įrankiai retai padeda suprasti konfliktus ar rezoliucijas. Paprastai sėkmingiau žiūriu į teksto redaktoriaus konfliktų žymenis ir naudoju git žurnalą kaip priedą.

Štai keletas patarimų:

Taryba viena

Geriausia, kad aš naudoju susiliejimo konflikto 3 stilių:

git config merge.conflictstyle diff3

Tai sukuria tokius konfliktų žymenis:

 <<<<<<< Changes made on the branch that is being merged into. In most cases, this is the branch that I have currently checked out (ie HEAD). ||||||| The common ancestor version. ======= Changes made on the branch that is being merged in. This is often a feature/topic branch. >>>>>>> 

Vidurinė dalis yra tai, kaip atrodė bendras protėvis. Tai naudinga, nes galite ją palyginti su viršutinėmis ir apatinėmis versijomis, kad geriau suprastumėte, kas pasikeitė kiekvienoje šakoje, suteikiant jums geresnį supratimą apie kiekvieno pakeitimo tikslą.

Jei konfliktas susideda tik iš kelių eilučių, tai paprastai daro konfliktą akivaizdžiu. (Žinant, kaip išspręsti konfliktą, labai skiriasi: reikia žinoti, ką dirba kiti žmonės. Jei supainiotumėte, geriausia tiesiog paskambinti šiam asmeniui savo kambaryje, kad jie galėtų pamatyti, ko ieškote.)

Jei konfliktas yra ilgesnis, kiekvieną iš trijų skyrių supjaustysiu ir įklijuoju į tris atskiras rinkmenas, pvz., „Mano“, „bendras“ ir „jas“.

Tada galiu paleisti šias komandas, kad pamatytumėte dvi situacijas, dėl kurių kilo konfliktas:

 diff common mine diff common theirs 

Tai ne tas pats, kaip naudojant susiliejimo įrankį, nes sujungimo įrankis apims visus nesuderinamus „dif-hunks“. Manau, kad tai blaško.

Du patarimai

Kažkas tai jau paminėjo, tačiau kiekvieno žodžio „diff“ ketinimų supratimas paprastai yra naudingas suprasti, iš kur kilo konfliktas ir kaip jais elgtis.

 git log --merge -p <name of file> 

Tai rodo visus įsipareigojimus, susijusius su šiuo failu tarp bendrų protėvių ir dviejų galvučių, kuriuos jungiate. (Taigi, į jį neįtraukiami įsipareigojimai, kurie prieš jungiant jau egzistuoja abiejuose filialuose.) Tai padeda ignoruoti skirtumus, kurie akivaizdžiai nėra jūsų dabartinio konflikto veiksnys.

Patarimas trys

Patikrinkite pakeitimus naudodami automatinius įrankius.

Jei turite automatinius testus, paleiskite juos. Jei turite pūkų , paleiskite jį. Jei tai yra statybos projektas, jis turi būti pastatytas prieš jį užbaigiant ir tt Visais atvejais turite gauti nedidelį testą, kad įsitikintumėte, jog jūsų pakeitimai nėra pažeisti. („Heck“, net ir sujungus be konfliktų, galite nutraukti darbo kodą.)

Keturi patarimai

Planuokite į priekį; bendrauti su kolegomis.

Išankstinis planavimas ir supratimas, kad kiti dirba, gali padėti išvengti konfliktų dėl konfliktų ir (arba) padėti jas išspręsti anksčiau, o duomenys tebėra aktualūs.

Pvz., Jei žinote, kad jūs ir kitas asmuo dirba su skirtingais refactorings, kurie paveiks tą patį rinkinį, turėtumėte pasikalbėti vienas su kitu iš anksto ir geriau suprasti, kokie pakeitimai kiekvienas iš jūsų daro. Jūs galite sutaupyti daug laiko ir pastangų, jei atliksite planuojamus pakeitimus, o ne lygiagrečiai.

Dideliems rekonstrukcijoms, peržengiančioms didelį kodą, turėtumėte rimtai apsvarstyti darbą nuosekliai: kiekvienas nustoja dirbti šioje kodo srityje, o vienas asmuo atlieka pilną rekonstrukciją.

Jei negalite dirbti nuosekliai (galbūt dėl ​​laikino spaudimo), tada kalbant apie laukiamus sujungimo konfliktus bent jau padės išspręsti problemas anksčiau, o detalės vis dar yra šviežios. Pvz., Jei darbuotojas per savaitę daro destruktyvią įsipareigojimų seriją, šią savaitę galbūt norėsite sujungti / perpakuoti šį filialą vieną ar du kartus per dieną. Tokiu būdu, jei pastebėsite, kad konfliktai susilieja / nukreipiami, galite juos išspręsti greičiau nei tada, kai palaukite kelias savaites, kad viską sujungtumėte į vieną didelį kūrinį.

Penki patarimai

Jei nesate tikri dėl susijungimo, nesijunkite.

Susijungimas gali būti didžiulis, ypač kai yra daug prieštaringų failų, o konfliktų žymekliai apima šimtus linijų. Dažnai, vertinant programinės įrangos projektus, neįtraukiame pakankamai laiko papildomiems mokesčiams, pavyzdžiui, beprotiško susijungimo apdorojimui, todėl atrodo, kad realus pasipriešinimas praleisti kelias valandas analizuojant kiekvieną konfliktą.

Ilgainiui planavimas į priekį ir supratimas, kad kiti dirba, yra geriausios priemonės, leidžiančios prognozuoti susijungimo konfliktus ir pasirengti tinkamam sprendimui per trumpesnį laiką.

696
29 сент. Atsakymą pateikė Markas E. Haase 29 sep. 2011-09-29 00:08 '11 - 0:08 2011-09-29 00:08
  • Nustatykite, kurie failai yra prieštaringi („Git“ tai jums pasakys).

  • Atidarykite kiekvieną failą ir sužinokite skirtumus; Git juos riboja. Tikiuosi, kad bus aišku, kokia kiekvieno bloko versija bus išsaugota. Gali tekti tai aptarti su kitais kūrėjais, kurie užpildė kodą.

  • Išsprendus konfliktą git add the_file faile, git add the_file .

  • Kai tik išsprendžiate visus konfliktus, paleiskite „ git rebase --continue arba bet kurią komandą „Git“, kai jis baigė.

326
02 окт. atsakymas pateiktas davetron5000 02 okt. 2008-10-02 15:41 '08 at 3:41 pm 2008-10-02 15:41

Patikrinkite atsakymus į klausimą „ Atšaukti„ Git “atšaukimą , ypač„ Charles Bailey “atsakymą , kuriame parodoma, kaip peržiūrėti įvairias problemos failo versijas, pvz.

100
03 окт. Pat Notz atsakymas 03 d 2008-10-03 18:15 '08, 18:15 pm 2008-10-03 18:15

Konfliktų sujungimas įvyksta, kai tuo pačiu metu atliekami failo pakeitimai. Štai kaip tai išspręsti.

git CLI

Čia rasite paprastus veiksmus, kurių reikia imtis, kai esate konflikto būsenoje:

  • Atkreipkite dėmesį į prieštaraujančių failų sąrašą: git status (skyriuje Unmerged paths ).
  • Išspręskite konfliktus atskirai kiekvienam failui su vienu iš šių būdų:

    • Naudokite GUI, norėdami išspręsti konfliktus: git mergetool (paprasčiausias būdas).

    • Jei norite priimti nuotolinį / kitą variantą, naudokite: git checkout --theirs path/file . Tai atmes bet kokius vietinius pakeitimus, atliktus šiame faile.

    • Jei norite priimti vietinę / mūsų versiją, naudokite: git checkout --ours path/file

      Tačiau turite būti atsargūs, nes išbraukti pakeitimai dėl tam tikrų priežasčių buvo pašalinti.

      Susiję: Kas yra tiksli „mūsų“ ir „jų“ reikšmė gitoje?

    • Redaguokite prieštaraujančius failus rankiniu būdu ir suraskite kodo bloką tarp <<<<< / >>>>> , tada pasirinkite virš arba žemiau esančią versiją ===== . Žr., Kaip pateikiami konfliktai .

    • Kelias ir failo pavadinimo konfliktus galima išspręsti naudojant git add / git rm .

  • Galiausiai peržiūrėkite paruoštus failus, naudodami: git status .

    Jei vis dar turite failų, esančių „ Unmerged paths , ir jūs išsprendėte konfliktą rankiniu būdu, tada leiskite „Git“ žinoti, kad išsprendėte: git add path/file .

  • Jei visi konfliktai buvo išspręsti sėkmingai, nukopijuokite pakeitimus: git commit -a ir spustelėkite ištrintą, kaip įprasta.

Taip pat žr. „GitHub“ komandų eilutės sujungimo konflikto sprendimas

DiffMerge

Sėkmingai naudoju „ DiffMerge“ , kuri gali vizualiai palyginti ir sujungti failus Windows, MacOS ir Linux / Unix.

Jis grafiškai rodo pokyčius tarp 3 failų ir leidžia automatiškai sujungti (kai jis yra saugus) ir visiškai kontroliuoti gauto failo redagavimą.

2019

05 авг. atsakymas pateikiamas kenorb 05 rug . 2015-08-05 17:29 '15, 17:29, 2015-08-05 17:29

Jei dažnai atliekate mažus įsipareigojimus, pradėkite peržiūrėdami git log --merge komentarus su „ git log --merge . Tada git diff parodys konfliktus.

Dėl konfliktų, susijusių su keliomis eilutėmis, lengviau matyti, kas vyksta išoriniame GUI įrankyje. Man patinka opendiffas - „Git“ taip pat palaiko „vimdiff“, „gvimdiff“, „kdiff3“, „tkdiff“, „meld“, „xxdiff“, išeina iš dėžutės, ir jūs galite įdiegti kitus: git config merge.tool "your.tool" įdiegs jūsų pasirinktą įrankį, o po to nesėkmingai git mergetool sujungimas parodys skirtumus kontekste.

Kiekvieną kartą redaguodami failą, norint išspręsti konfliktą, „ git add filename atnaujina indeksą, o jūsų diferencialas nebebus rodomas. Kai visi konfliktai bus apdoroti ir jų failai yra git add , git commit užbaigs sujungimą.

75
02 окт. atsakymas duotas Paul 02 02. 2008-10-02 19:11 '08 at 7:11 pm 2008-10-02 19:11

Žr., Kaip pateikiami konfliktai arba „Git“, „ git merge dokumentai, kad suprastumėte, kas yra konfliktų konflikto žymekliai.

Be to, skyriuje „ Kaip išspręsti konfliktus“ paaiškinama, kaip išspręsti konfliktus:

Peržiūrėję konfliktą, galite padaryti du dalykus:

  • Nuspręskite nesijungti. Vieninteliai jums reikalingi valikliai yra reset indekso failas, skirtas HEAD nustatymui atvirkštiniam transformavimui 2. ir darbo kaimų pakeitimų, atliktų 2 ir 3, išvalymui; git merge --abort gali būti naudojamas „ git merge --abort .

  • Išspręskite konfliktus. „Git“ žymės konfliktus darbo medyje. Redaguokite formoje esančius failus ir git add juos prie indekso. Naudokite git commit užsandarinti sandorį.

Galite dirbti prieštaraujant kelioms priemonėms:

  • Naudokite mergetool. git mergetool paleisti grafinį mergetool, kuris veiks per susijungimą.

  • Pažvelkite į skirtumus. git diff rodo MERGE_HEAD diferenciją, išryškindama tiek HEAD tiek MERGE_HEAD .

  • Pažvelkite į kiekvienos šakos skirtumus. git log --merge -p <path> bus rodomas pirmiausia HEAD versijos ir tada MERGE_HEAD versijos MERGE_HEAD .

  • Pažvelkite į originalus. git show :1:filename rodo bendrą protėvį, git show :2:filename rodo HEAD versiją, o git show :3:filename rodo MERGE_HEAD versiją.

Taip pat galite perskaityti apie susijungimo konflikto markę ir kaip juos išspręsti „ Pro Git“ pagrindinio sujungimo konfliktų skiltyje.

43
14 июля '13 в 21:34 2013-07-14 21:34 atsakymą pateikė vartotojo456814 liepos 14 d. , 13:13, 2013-07-14 21:34

Emacs“ naudotojams, norintiems išspręsti pusiau rankinius sujungimo konfliktus:

 git diff --name-status --diff-filter=U 

Rodo visus failus, kuriems reikalingas konfliktų sprendimas.

Atidarykite kiekvieną iš šių failų po vieną arba visus iš karto:

 emacs $(git diff --name-only --diff-filter=U) 

Kai lankotės buferyje, kuriam reikia redaguoti „Emacs“, įveskite

 ALT+x vc-resolve-conflicts 

Tai atvers tris buferius (mano, jų ir išeigos buferį). Naršykite paspausdami „n“ (kita sritis), „p“ (prognozavimo sritis). Paspauskite „a“ ir „b“, kad nukopijuotumėte mano arba savo sritį atitinkamai į išvesties buferį. Ir / arba tiesiogiai redaguokite išvesties buferį.

Kai baigsite: paspauskite „q“. „Emacs“ klausia, ar norite išsaugoti šį buferį: taip. Kai buferis baigtas, pažymėkite jį kaip išspręstą paleidžiant iš ratuko:

 git add FILENAME 

Baigę dirbti su visų tipų buferiais

 git commit 

užbaigti sujungimą.

36
23 февр. atsakymas pateikiamas ekiu 23 vasaris. 2013-02-23 02:04 '13, 02:04 2013-02-23 02:04

Aš visiškai noriu savo versijos ar jų versijos arba noriu matyti individualius pakeitimus ir priimti sprendimą kiekvienam iš jų.

Visiškai priimti mano ar jų versiją :

Priimti mano versiją (vietinę, mūsų):

 git checkout --ours -- <filename> git add <filename> # Marks conflict as resolved git commit -m "merged bla bla" # An "empty" commit 

Priimti jų versiją (juos ištrinti):

 git checkout --theirs -- <filename> git add <filename> git commit -m "merged bla bla" 

Jei norite atlikti visus prieštaringus failus, paleiskite:

 git merge --strategy-option ours 

arba

 git merge --strategy-option theirs 

Peržiūrėkite visus pakeitimus ir priimti juos atskirai.

  1. git mergetool
  2. Peržiūrėkite pakeitimus ir priimkite bet kurią iš jų versiją.
  3. git add <filename>
  4. git commit -m "merged bla bla"

Pagal nutylėjimą, mergetool veikia komandų eilutėje . Kaip naudoti „mergetool“ komandinę eilutę turėtų būti atskiras klausimas.

Taip pat galite įdiegti vizualų įrankį , pvz., meld ir paleisti

 git mergetool -t meld 

Bus atidaryta vietinė (mūsų), „pagrindinė“ arba „vieninga“ versija (dabartinis sujungimo rezultatas) ir nuotolinio valdymo pultas. Išsaugokite susijungusią versiją, kai baigsite, paleiskite „ git mergetool -t meld kol gausite „Nereikia sujungti failus“, tada pereikite prie 3 ir 4 žingsnių.

28
29 сент. Atsakymą pateikė Noidea 29 sep . 2016-09-29 16:02 '16 at 16:02 2016-09-29 16:02

Atlikite šiuos veiksmus, kad išspręstumėte sujungimo konfliktus git:

  1. Patikrinkite „Git“ būseną : „ Git“ būsena

  2. Gaukite pleistrų rinkinį: „ git fetch“ (patikrinkite teisingą pleistrą iš „ git“ įsipareigojimo)

  3. Ištraukite vietinį filialą (mano pavyzdyje, temp1): git checkout -b temp1

  4. Ištraukite naujausią turinį iš šeimininko: git pull --rebase origin master

  5. Paleiskite mergetool, patikrinkite konfliktus ir juos taisykite ... ir patikrinkite nuotolinio filialo pakeitimus su savo dabartiniu filialu: git mergetool

  6. Dar kartą patikrinkite būseną: git status

  7. Ištrinkite nereikalingus failus, sukurtus vietoje su mergetool, paprastai mergetool sukuria papildomą failą su plėtiniu * .orig. Ištrinkite šį failą, nes jis yra tik dublikatas, pataisykite pakeitimus vietoje ir pridėkite teisingą failų versiją. git pridėti #your_changed_correct_files

  8. Dar kartą patikrinkite būseną: git status

  9. Padarykite pakeitimus tame pačiame identifikatoriuje (tai vengia naujo atskiro pataisų rinkinio): git įsipareigoja --amend

  10. Push to master filialas: „ git push“ („Git“ saugykla)

28
16 апр. Atsakymas pateikiamas Chhabilal 16 balandžio. 2015-04-16 10:02 '15 prie 10:02 2015-04-16 10:02

Paprasčiau tariant, jei gerai žinote, kad vieno iš saugyklų pakeitimai nėra svarbūs, ir norite leisti visus pakeitimus naudai kitam, naudokite:

 git checkout . --ours 

leisti pakeitimus savo saugyklos naudai, arba

 git checkout . --theirs 

leisti atlikti pakeitimus naudai kitai arba pagrindinei saugyklai .

Arba turėsite naudoti GUI sujungimo įrankį, norėdami pereiti per failus, pvz., p4merge sujungimo p4merge , arba parašyti bet kokį jau nustatytą vardą.

 git mergetool -t p4merge 

ir baigus failą, turėsite išsaugoti ir uždaryti, kad atidarytumėte kitą.

27
26 янв. Atsakė Mohamed Selim 26 d 2016-01-26 20:42 '16 at 8:42 pm 2016-01-26 20:42

Sujungimo konfliktus galite išspręsti keliais būdais, kaip kiti nurodė.

Manau, kad realus raktas yra žinoti, kaip keičiasi srautas su vietinėmis ir nuotolinėmis saugyklomis. Svarbiausia tai yra sekimo šakų supratimas. Radau, kad aš manau, kad sekimo filialas yra „trūkstama dalis viduryje“ tarp mano, mano vietinio, faktinio failų katalogo ir nuotolinio, apibrėžto kaip kilmė.

Aš asmeniškai pripratau prie dviejų dalykų, kad tai padėtų išvengti.

Vietoj:

 git add . git commit -m"some msg" 

Kas turi du trūkumus -

a) Pridedami visi nauji / modifikuoti failai ir jame gali būti nepageidaujamų pakeitimų.
b) Jūs negalite peržiūrėti failų sąrašo.

Taigi:

 git add file,file2,file3... git commit # Then type the files in the editor and save-quit. 

Tokiu būdu jūs sąmoningai diskutuojate, kokie failai yra pridėti, taip pat galite slinkti per sąrašą ir galvoti šiek tiek daugiau naudodami pranešimo redaktorių. Manau, kad jis taip pat pagerina mano prisiimtus pranešimus, kai naudoju viso ekrano redaktorių, o ne -m parinktį.

[Atnaujinti - kai praėjo laikas, perjungiau daugiau į:

 git status # Make sure I know whats going on git add . git commit # Then use the editor 

]

Taip pat (ir labiau tinkama jūsų situacijai) stengiuosi vengti:

 git pull 

arba

 git pull origin master.