Kako riješiti spojeve u git-u

Postoji li dobar način da se objasni kako riješiti sukobe spajanja u git-u?

4274
02 окт. Spoike set 02 okt. 2008-10-02 14:31 '08 u 14:31 2008-10-02 14:31
@ 37 odgovora
  • 1
  • 2

Pokušajte: git mergetool

Otvara se grafičko sučelje koje se provlači kroz svaki sukob i možete odabrati kako ćete ga kombinirati. Ponekad je za to potrebno malo ručno uređivanje, ali obično je dovoljno. To je mnogo bolje nego raditi sve ručno.

Prema @JoshGlover komentaru:

Naredba ne mora nužno otvoriti GUI ako ga ne instalirate. Trčanje git mergetool za mene dovelo je do upotrebe vimdiff . Umjesto toga možete instalirati jedan od sljedećih alata: meld , opendiff , kdiff3 , tkdiff , xxdiff , tortoisemerge , gvimdiff , diffuse , ecmerge , p4merge , araxis , vimdiff .

U nastavku je primjer postupka za korištenje vimdiff za rješavanje vimdiff spajanja. Putem ove veze

Korak 1 : Pokrenite sljedeće naredbe u svom terminalu

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

To će postaviti vimdiff kao zadani alat za spajanje.

Korak 2 : Izvedite sljedeću naredbu u terminalu

 git mergetool 

Korak 3 : Vidjet ćete vimdiff zaslon u sljedećem formatu.

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

Ove 4 vrste

LOCAL je datoteka iz trenutne grane.

BASE - zajednički predak, kako je datoteka izgledala prije obje promjene

REMOTE - datoteka koju spojite u svoju granu

MERGED - rezultat spajanja, to je ono što se pohranjuje u repo

Možete se kretati između tih prikaza pomoću ctrl+w Možete izravno otići na MERGED prikaz pomoću ctrl+w i j .

Više informacija o vimdiff navigaciji ovdje i ovdje.

Korak 4 Možete urediti MERGED na sljedeći način.

Ako želite primati promjene od REMOTE

 :diffg RE 

Ako želite primati promjene od BASE

 :diffg BA 

Ako želite primati promjene od LOCAL

 :diffg LO 

Korak 5 Spremanje, izlaz, zaključavanje i brisanje

:wqa spremanje i izlaz vi

git commit -m "message"

git clean Izbrišite nepotrebne datoteke (na primjer, * .orig) koje je stvorio alat diff.

2535
02 окт. odgovor je dao Peter Burns 02. listopada. 2008-10-02 20:50 '08 u 20:50 2008-10-02 20:50

Evo vjerojatnog presedana, odozgo:

Napravit ćete neke promjene, ali nažalost ne znate:

 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. 

Dakle, ažurirajte i pokušajte ponovno, ali imate sukob:

 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. 

Stoga ste odlučili pogledati promjene:

border=0
 git mergetool 

Oh, ja, oh, moj, uzvodno je promijenio neke stvari, ali samo da koristim moje promjene ... ne ... njihove promjene ...

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

I onda pokušamo posljednji put.

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

Evo ga!

1625
04 авг. odgovor je dao CoolAJ86 04 aug. 2010-08-04 20:04 '10 u 20:04 2010-08-04 20:04

Smatram da mi alati za spajanje rijetko pomažu razumjeti sukob ili rješavanje. Obično više uspješno gledam u oznakama sukoba u uređivaču teksta i upotrebljavam git log kao dodatak.

Evo nekoliko savjeta:

Vijeće

Najviše što sam pronašao je da koristim diff3 stil sukoba spajanja:

git config merge.conflictstyle diff3

Stvara oznaÄ markavanje sukoba ovako:

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

Srednji je dio izgledao kao zajednički predak. To je korisno jer ga možete usporediti s gornjom i donjom verzijom kako biste bolje razumjeli što je promijenjeno u svakoj grani, dajući vam bolju ideju o tome koja je svrha svake promjene.

Ako se sukob sastoji od samo nekoliko redaka, to, u pravilu, čini sukob vrlo očiglednim. (Znati kako riješiti sukob je vrlo različito: morate znati na čemu rade drugi ljudi. Ako ste zbunjeni, najbolje je nazvati tu osobu u svoju sobu kako bi mogli vidjeti što tražite.)

Ako je sukob duži, izrežem i zalijepite svaki od tri dijela u tri odvojene datoteke, kao što su „moja“, „zajednički“ i „njih“.

Zatim mogu pokrenuti sljedeće naredbe da bih vidio dvije situacije koje su uzrokovale sukob:

 diff common mine diff common theirs 

To nije isto kao korištenje alata za spajanje, jer će alat za spajanje uključivati ​​sve nesukladne probleme. Mislim da to ometa.

Savjet dva

Netko je to već spomenuo, ali razumijevanje namjere iza svake riječi diff je obično korisno za razumijevanje odakle je došlo do sukoba i kako se njime nositi.

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

Prikazuju se sve urezivanja koja se odnose na ovu datoteku između zajedničkog pretka i dvije glave koje spojite. (Dakle, ne uključuje urezivanja koja već postoje u obje grane prije spajanja.) To pomaže ignorirati razlike koje očito nisu čimbenik u vašem trenutnom sukobu.

Savjet tri

Provjerite izmjene pomoću automatskih alata.

Ako imate automatizirane testove, pokrenite ih. Ako imate vlakna , pokrenite ga. Ako se radi o građevinskom projektu, onda ga morate izgraditi prije nego ga dovršite, itd. U svim slučajevima potrebno je malo testiranja kako biste bili sigurni da vaše promjene nisu prekinute. (Heck, čak i spajanje bez sukoba može razbiti radni kôd.)

Savjet četiri

Planirajte unaprijed; komunicirati s kolegama.

Planiranje unaprijed i spoznaja da drugi rade mogu spriječiti sukobe spajanja i / ili pomoći pri njihovom rješavanju ranije - dok su detalji još uvijek relevantni.

Na primjer, ako znate da vi i druga osoba radite na različitim preradama koje će utjecati na isti skup datoteka, trebali biste međusobno razgovarati unaprijed i bolje razumjeti koje vrste promjena radite. Možete uštedjeti puno vremena i truda ako planirane promjene izvršite redom, a ne paralelno.

Za velike preradbe koje prelaze veliki dio koda, trebali biste ozbiljno razmisliti o tome da radite sekvencijalno: svatko prestaje raditi na tom području koda, a jedna osoba obavlja puni refactoring.

Ako ne možete dosljedno raditi (možda zbog privremenog pritiska), onda će vam govor o očekivanim sukobima spajanja barem pomoći pri rješavanju problema ranije, dok su detalji još uvijek svježi. Na primjer, ako zaposlenik napravi destruktivni niz obveza unutar jednog tjedna, možda ćete željeti spojiti / prepakirati ovu granu jedanput ili dvaput dnevno ovaj tjedan. Na taj način, ako nađete sukobe spajanja / preusmjeravanja, možete ih riješiti brže nego ako čekate nekoliko tjedana da biste sve spojili u jedan veliki komad.

Savjet pet

Ako niste sigurni u spajanje, nemojte ga prisiljavati.

Spajanje može biti zapanjujuće, pogotovo ako postoji mnogo proturječnih datoteka, a markeri sukoba obuhvaćaju stotine redaka. Često, kada ocjenjujemo softverske projekte, ne uključujemo dovoljno vremena za dodatne troškove, kao što je obrada ludog spajanja, pa se čini kao pravi otpor potrošiti nekoliko sati analizirajući svaki sukob.

Dugoročno gledano, planiranje unaprijed i spoznaja da drugi rade su najbolji alati za predviđanje sukoba spajanja i pripremu za pravo rješenje u kraćem vremenu.

696
29 сент. Odgovor je dao E. E. Haase 29 sep. 2011-09-29 00:08 '11 u 0:08 2011-09-29 00:08
  • Odredite koje su datoteke u sukobu (Git bi vam to trebao reći).

  • Otvorite svaku datoteku i saznajte razlike; Git ih označava. Nadam se da će biti očito koju verziju svakog bloka zadržati. Možda ćete o tome morati razgovarati s drugim programerima koji su dovršili kod.

  • Nakon što ste riješili sukob u datoteci git add the_file datoteku.

  • Čim riješite sve sukobe, pokrenite git rebase --continue ili bilo koju naredbu koju je Git rekao kad završite.

326
02 окт. odgovor je danvetron5000 02 okt. 2008-10-02 15:41 '08 u 15:41 2008-10-02 15:41

Provjerite odgovore u odgovoru na pitanje o odustajanju od otvaranja Git-a , posebice u odgovoru Charlesa Baileyja , koji pokazuje kako pregledati različite verzije problematične datoteke, na primjer

100
03 окт. Odgovor dao Pat Notz dana 03. listopada 2008-10-03 18:15 '08 u 18:15 2008-10-03 18:15

Do spajanja sukoba dolazi kada se promjene u datoteci vrše istovremeno. Evo kako to riješiti.

git CLI

Evo jednostavnih koraka koje morate poduzeti kada ste u stanju sukoba:

  • Primijetite popis konfliktnih datoteka: git status (u odjeljku Unmerged paths ).
  • Rješavanje sukoba zasebno za svaku datoteku s jednim od sljedećih pristupa:

    • Koristite GUI za rješavanje sukoba: git mergetool (najlakši način).

    • Da biste prihvatili udaljenu / drugu verziju, koristite: git checkout --theirs path/file . Time ćete odbiti sve lokalne promjene koje ste napravili u ovoj datoteci.

    • Da biste prihvatili lokalnu / našu verziju, koristite: git checkout --ours path/file

      Međutim, morate biti oprezni jer su izbrisane promjene iz nekog razloga uklonjene.

      Povezano: Koje je točno značenje "naših" i "njih" u git-u?

    • Ručno uredite sukobljene datoteke i pronađite blok koda između <<<<< / >>>>> , zatim odaberite verziju iznad ili ispod ===== . Vidi: Kako su prikazani sukobi .

    • Konflikti naziva putanje i datoteke mogu se riješiti pomoću git add / git rm .

  • Konačno, pregledajte datoteke spremne za predaju pomoću: git status .

    Ako još uvijek imate datoteke pod Unmerged paths , a konflikt ste riješili ručno, onda neka Git sazna da ste ga riješili: git add path/file .

  • Ako su svi sukobi uspješno riješeni, kopirajte promjene: git commit -a i kliknite na obrisano kao i obično.

Vidi također: Rješavanje konflikta spajanja iz naredbenog retka u GitHubu

DiffMerge

Uspješno sam koristio DiffMerge , koji može vizualno usporediti i spojiti datoteke u sustavima Windows, MacOS i Linux / Unix.

To grafički prikazuje promjene između 3 datoteke i omogućuje automatsko spajanje (kada je sigurno) i potpunu kontrolu nad uređivanjem rezultirajuće datoteke.

2019

05 авг. odgovor je dan kenorb 05 aug. 2015-08-05 17:29 '15 u 17:29 2015-08-05 17:29

Ako često git log --merge , počnite gledati komentare git log --merge pomoću git log --merge . Tada će vam git diff prikazati sukobe.

Za konflikte koji uključuju više linija lakše je vidjeti što se događa u vanjskom GUI alatu. Sviđa mi se opendiff - Git također podržava vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, izlazi iz okvira, a možete instalirati i druge: git config merge.tool "your.tool" instalirati odabrani alat, a zatim git mergetool nakon neuspjeha spajanje će vam pokazati razlike u kontekstu.

Svaki put kada uređujete datoteku da biste riješili sukob, git add filename ažurira indeks, a vaš diff više ga neće prikazivati. Kada su svi sukobi obrađeni, a njihove datoteke git add -ed, git commit će završiti spajanje.

75
02 окт. odgovor je dao Pavao 2. listopada 2008-10-02 19:11 '08 u 19:11 2008-10-02 19:11

Pogledajte Kako su predstavljeni sukobi ili u Git-u, git merge dokumentaciju, kako biste razumjeli što su markeri sukoba sukoba.

Nadalje, odjeljak Kako riješiti sukobe objašnjava kako riješiti sukobe:

Nakon pregledavanja sukoba možete napraviti dvije stvari:

  • Odlučite se ne spajati. Jedina sredstva za čišćenje koja su vam potrebna su reset datoteka indeksa za fiksiranje HEAD za inverznu transformaciju 2. i za brisanje promjena u radnom selu u 2. i 3; git merge --abort se može koristiti za to.

  • Rješavanje sukoba. Git će označiti sukobe u radnom stablu. Uredite datoteke u obrascu i git add ih u indeks. Upotrijebi git commit da zaključiš posao.

Možete raditi u sukobu s nekoliko alata:

  • Koristite mergetool. git mergetool pokrenuti grafički mergetool koji će raditi kroz spajanje.

  • Pogledajte razlike. git diff prikazuje trostrani diff, ističući promjene iz MERGE_HEAD HEAD i MERGE_HEAD .

  • Pogledajte razlike između svake grane. git log --merge -p <path> najprije prikazuje diff za HEAD verziju, a zatim za verziju MERGE_HEAD .

  • Pogledajte izvornike. git show :1:filename prikazuje zajedničkog pretka, git show :2:filename prikazuje verziju HEAD , a git show :3:filename prikazuje verziju MERGE_HEAD .

Također možete pročitati o brandu konflikta spajanja i kako ih riješiti u odjeljku Pro Git Glavni spojevi spajanja.

43
14 июля '13 в 21:34 2013-07-14 21:34 odgovor je dao korisnik456814 14. srpnja '13. u 21:34 2013-07-14 21:34

Za Emacs, korisnike koji žele riješiti polu-ručne sukobe spajanja:

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

Prikazuje sve datoteke koje zahtijevaju rješavanje sukoba.

Otvorite svaku od ovih datoteka jednu po jednu ili sve odjednom:

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

Kada posjećujete spremnik koji zahtijeva uređivanje u Emacsu, unesite

 ALT+x vc-resolve-conflicts 

To će otvoriti tri međuspremnika (moja, njih i izlazni međuspremnik). Krećite se pritiskom na "n" (sljedeće područje), "p" (područje predviđanja). Pritisnite "a" i "b" da biste kopirali moje ili vaše područje u izlazni međuspremnik. I / ili izravno uredite izlazni međuspremnik.

Kada završite: pritisnite "q". Emacs vas pita želite li spremiti taj me uspremnik: da. Kada je spremnik završen, označite ga kao riješeno pri pokretanju iz kotača:

 git add FILENAME 

Nakon završetka rada sa svim vrstama odbojnika

 git commit 

da biste dovršili spajanje.

36
23 февр. odgovor je dan eci 23. veljače. 2013-02-23 02:04 '13 u 2:04 2013-02-23 02:04

Ili želim svoju verziju ili njihovu verziju u potpunosti, ili želim vidjeti pojedinačne promjene i donijeti odluku za svaku od njih.

Potpuno prihvatite moju ili njihovu verziju :

Prihvatite moju verziju (lokalno, naše):

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

Prihvatite njihovu verziju (izbrisane):

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

Ako želite raditi za sve sukobljene datoteke, pokrenite:

 git merge --strategy-option ours 

ili

 git merge --strategy-option theirs 

Pregledajte sve promjene i prihvatite ih pojedinačno.

  1. git mergetool
  2. Pregledajte promjene i prihvatite bilo koju verziju za svaku od njih.
  3. git add <filename>
  4. git commit -m "merged bla bla"

Prema zadanim postavkama, mergetool radi na naredbenom retku . Kako koristiti mergetool naredbenog retka bi trebao biti zasebna tema.

Također možete instalirati vizualni alat za to, na primjer, meld i pokrenuti

 git mergetool -t meld 

Lokalna (naša), "osnovna" ili "objedinjena" verzija (trenutni rezultat spajanja) i daljinski upravljač (i) bit će otvoreni. Spremite spojenu verziju kada završite, pokrenite git mergetool -t meld dok ne dobijete "Nema potrebe za spajanjem datoteka", a zatim idite na 3. i 4. korak.

28
29 сент. Odgovor daje Noidea 29 sep . 2016-09-29 16:02 '16 u 16:02 2016-09-29 16:02

Izvedite sljedeće korake kako biste riješili sukobe spajanja u git-u:

  1. Provjerite status Git : status Git

  2. Nabavite skup zakrpe: git fetch (provjerite ispravnu zakrpu u svom git obvezu)

  3. Ekstrakt lokalne grane (u mom primjeru, temp1): git checkout -b temp1

  4. Izvadite najnovije sadržaje iz mastera: git pull - master izvor porijekla

  5. Pokrenite mergetool, provjerite sukobe i popravite ih ... i provjerite promjene u udaljenoj grani trenutnom granom: git mergetool

  6. Ponovno provjerite status: status git

  7. Izbrišite nepotrebne datoteke kreirane lokalno s mergetoolom, obično mergetool stvara dodatnu datoteku s ekstenzijom * .orig. Izbrišite ovu datoteku jer je to samo duplikat, ispravite promjene lokalno i dodajte ispravnu verziju svojih datoteka. git dodajte #your_changed_correct_files

  8. Ponovno provjerite status: status git

  9. Obavite promjene na istom identifikatoru (to izbjegava novi odvojeni skup popravaka): git commit --amend

  10. Pritisni za glavnu granu: git push (u Git repozitorij)

28
16 апр. Odgovor je dat Chhabilal 16 apr. 2015-04-16 10:02 '15 u 10:02 2015-04-16 10:02

Jednostavno rečeno, ako dobro znate da promjene u jednom od spremišta nisu važne, a želite dopustiti sve promjene u korist drugih, upotrijebite:

 git checkout . --ours 

dopustite promjene u korist svog spremišta ili

 git checkout . --theirs 

dopustiti promjene u korist drugog ili glavnog repozitorija .

Ili ćete morati koristiti alat za spajanje grafičkog korisničkog sučelja da biste prošli kroz datoteke, recimo, p4merge spajanje, ili napisati bilo koje ime koje ste već postavili.

 git mergetool -t p4merge 

i nakon dovršenja datoteke morat ćete spremiti i zatvoriti otvoriti sljedeću.

27
26 янв. Odgovorio ga je Mohamed Selim 26. siječnja 2016-01-26 20:42 '16 u 20:42 2016-01-26 20:42

Sukobi spajanja možete popraviti na nekoliko načina, kao što su drugi detaljno opisali.

Mislim da je pravi ključ znati kako teče promjena s lokalnim i udaljenim spremištima. Ključ toga je razumijevanje grana za praćenje. Otkrio sam da promatranje grane kao "nedostajućeg dijela u sredini" između mene, moga lokalnog, stvarnog direktorija datoteka i daljinskog, definiran kao izvor.

Osobno sam se navikao na dvije stvari koje mogu pomoći da se to izbjegne.

Umjesto:

 git add . git commit -m"some msg" 

Što ima dva nedostatka -

a) Sve nove / izmijenjene datoteke se dodaju i mogu sadržavati neke neželjene promjene.
b) Ne možete najprije pregledati popis datoteka.

Umjesto toga:

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

Na taj način vi namjerno raspravljate o tome koje se datoteke dodaju, a također možete pregledavati popis i razmisliti malo više pomoću urednika poruke. Smatram da ona također poboljšava moje urezivanje poruka kada koristim uređivač preko cijelog zaslona, ​​umjesto opcije -m .

[Ažuriranje - kako je vrijeme prolazilo, više sam se prebacio na:

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

]

Također (i za vašu situaciju prikladnije) pokušavam izbjeći:

 git pull 

ili

 git pull origin master.