Как да разрешим конфликти в сливания в git

Има ли добър начин да се обясни как да се разрешат конфликтите при сливането в git?

4274
02 окт. Комплект за спайк 02 окт. 2008-10-02 14:31 '08 в 14:31 2008-10-02 14:31
@ 37 отговора
  • 1
  • 2

Опитайте: git mergetool

Той отваря графичния интерфейс, който преминава през всеки конфликт, и можете да изберете как да комбинирате. Понякога това изисква малко ръчно редактиране след това, но обикновено е достатъчно само по себе си. Това е много по-добре, отколкото да правите всичко ръчно.

Според коментара на @JoshGlover:

Командата не е задължително да отваря GUI, ако не я инсталирате. Изпълнението на git mergetool за мен доведе до използването на vimdiff . Можете да инсталирате един от следните инструменти, за да го използвате вместо това: meld , opendiff , kdiff3 , tkdiff , xxdiff , tortoisemerge , gvimdiff , diffuse , ecmerge , p4merge , araxis , vimdiff .

По-долу е даден пример за процедурата за използване на vimdiff за разрешаване на конфликти на сливания. По тази връзка

Стъпка 1 : Изпълнете следните команди във вашия терминал

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

Това ще определи vimdiff като инструмент за сливане по подразбиране.

Стъпка 2 : Изпълнете следната команда в терминала

 git mergetool 

Стъпка 3 : Ще видите дисплей vimdiff в следния формат.

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

Тези 4 вида

LOCAL е файлът от текущия клон.

BASE - общ предшественик, как изглежда файлът преди двете промени

REMOTE - файл, който се слива с вашия клон

СЛУЧАВАНЕ - резултатът от сливането, това се съхранява в репо

Можете да се придвижвате между тези изгледи с помощта на ctrl+w директно да отидете на MERGED изгледа, използвайки ctrl+w и j .

Повече информация за vimdiff навигация тук и тук.

Стъпка 4 Можете да редактирате MERGED, както следва.

Ако искате да получавате промени от REMOTE

 :diffg RE 

Ако искате да получавате промени от BASE

 :diffg BA 

Ако искате да получавате промени от LOCAL

 :diffg LO 

Стъпка 5 Запазете, излезте, заключете и изчистете

:wqa запис и изход vi

git commit -m "message"

git clean Изтрийте ненужните файлове (например * .orig), създадени от инструмента diff.

2535
02 окт. отговор е даден от Питър Бърнс 02 окт. 2008-10-02 20:50 '08 в 20:50 2008-10-02 20:50

Ето един вероятен прецедент, отгоре:

Ще направите някои промени, но за съжаление не знаете:

 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. 

Затова актуализирате и опитайте отново, но имате конфликт:

 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. 

Затова решихте да разгледате промените:

border=0
 git mergetool 

О, аз, о, моят, нагоре по течението е променил някои неща, но само за да използвам промените си ... не ... техните промени ...

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

И тогава се опитваме за последен път.

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

Та-га!

1625
04 авг. отговорът се дава от CoolAJ86 04 авг. 2010-08-04 20:04 '10 в 20:04 ч. 2010-08-04 20:04

Смятам, че инструментите за обединяване рядко ми помагат да разбера конфликта или разрешаването. Обикновено по-успешно разглеждам маркери за конфликти в текстов редактор и използвам git log като допълнение.

Ето някои съвети:

Съвет

Най-доброто, което открих, е да използвам стила diff3 на конфликта за сливане:

git config merge.conflictstyle diff3

Той създава маркери за конфликти като този:

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

Средната част е как изглеждаше общият предшественик. Това е полезно, защото можете да го сравните с горните и долните версии, за да разберете по-добре какво е променено във всеки клон, като ви дава по-добра представа за целта на всяка промяна.

Ако конфликтът се състои само от няколко реда, това, като правило, прави конфликта много очевиден. (Знаейки как да разрешите конфликта е много различно: трябва да знаете върху какво работят другите хора. Ако сте объркани, най-добре е просто да повикате този човек в стаята си, за да могат да видят това, което търсите.)

Ако конфликтът е по-дълъг, изрязвам и поставям всеки от трите раздела в три отделни файла, като „мое“, „общо“ и „тях“.

След това мога да изпълня следните команди, за да видя две ситуации, които са довели до конфликта:

 diff common mine diff common theirs 

Това не е същото като използването на инструмента за сливане, тъй като инструментът за сливане ще включва всички несъгласуващи се разлики. Намирам го разсейващо.

Съвет два

Някой вече е споменал това, но разбирането на намерението зад всяка дума diff обикновено е полезно за разбирането откъде произлиза конфликта и как да се справя с него.

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

Това показва всички коммити, които засягат този файл между общ предшественик и две глави, които сливате. (По този начин тя не включва ангажиментите, които вече съществуват в двата клона преди сливането.) Това помага да се игнорират различията, които очевидно не са фактор в настоящия ви конфликт.

Съвет три

Проверете промените си с автоматизирани инструменти.

Ако имате автоматизирани тестове, изпълнете ги. Ако имате мъх , пуснете го. Ако това е строителен проект, то той трябва да бъде построен преди да го завършите и т.н. Във всички случаи трябва да направите малко тестване, за да се уверите, че промените ви не са нарушени. (По дяволите, дори сливането без конфликти може да наруши работния код.)

Съвет четири

Планирайте предварително; общуват с колеги.

Предстоящото планиране и осъзнаването, че другите работят, може да помогне за предотвратяване на конфликти на сливания и / или за по-ранно разрешаване на тях, докато подробностите са все още актуални.

Например, ако знаете, че вие ​​и друг човек работите по различни рефактори, които ще се отразят на един и същи набор от файлове, трябва да говорите помежду си много по-рано и да разберете по-добре какви промени правите всеки от вас. Можете да спестите много време и усилия, ако извършите планираните промени на свой ред, а не паралелно.

За големите рефактори, които пресичат голяма част от кода, трябва сериозно да помислите за работа последователно: всеки спира да работи в тази област от код и един човек извършва пълен рефакторинг.

Ако не можете да работите последователно (вероятно поради временен натиск), тогава разговорите за очаквани конфликти за сливане поне ще ви помогнат да решите проблемите по-рано, докато подробностите са все още свежи. Например, ако един служител извърши деструктивна поредица от ангажименти в рамките на една седмица, може би ще искате да слеете / препакетирате този клон веднъж или два пъти на ден тази седмица. По този начин, ако намерите конфликти за сливане / пренасочване, можете да ги решите по-бързо, отколкото ако изчакате няколко седмици, за да обедините всичко в едно голямо парче.

Съвет пет

Ако не сте сигурни за сливането, не го насилвайте.

Обединяването може да бъде огромно, особено когато има много конфликтни файлове и маркерите за конфликти обхващат стотици линии. Често, когато оценяваме софтуерни проекти, ние не включваме достатъчно време за допълнителни такси, като например обработка на лудо сливане, така че се чувстваме като истинска съпротива да прекараме няколко часа, анализирайки всеки конфликт.

В дългосрочен план планирането и осъзнаването, че другите работят, са най-добрите инструменти за прогнозиране на конфликтите при сливанията и подготовка за правилното решение за по-малко време.

696
29 сент. Отговорът е даден от Марк Е. Хаас 29 сеп. 2011-09-29 00:08 '11 в 0:08 2011-09-29 00:08
  • Определете кои файлове са в конфликт (Git трябва да ви каже това).

  • Отворете всеки файл и научете разликите; Git ги обозначава. Надявам се, че ще бъде очевидно коя версия на всеки блок да запази. Може да се наложи да обсъдите това с други разработчици, които са завършили кода.

  • След като разрешите конфликта в git add the_file файла, git add the_file файла git add the_file .

  • Веднага след като разрешите всички конфликти, стартирайте git rebase --continue или някоя друга команда, която Git е казала, когато приключите.

326
02 окт. отговорът се дава davetron5000 02 окт. 2008-10-02 15:41 '08 в 15:41 2008-10-02 15:41

Проверете отговорите в въпроса за прекратяване на отхвърлянето на Git , особено отговора на Charles Bailey , който показва как да преглеждате различни версии на проблемния файл, например

100
03 окт. Отговор, даден от Пат Нот на 03 октомври 2008-10-03 18:15 '08 в 18:15 2008-10-03 18:15

При сливането на конфликти се извършват промени в даден файл едновременно. Ето как да го разрешите.

git CLI

Това са простите стъпки, които трябва да предприемете, когато сте в състояние на конфликт:

  • Обърнете внимание на списъка с конфликтни файлове: git status (в секцията Unmerged paths ).
  • Разрешаване на конфликти отделно за всеки файл с един от следните подходи:

    • Използвайте GUI за разрешаване на конфликти: git mergetool (най-лесният начин).

    • За да приемете отдалечена / друга версия, използвайте: git checkout --theirs path/file . Това ще отхвърли всички местни промени, които сте направили в този файл.

    • За да приемете локалната / нашата версия, използвайте: git checkout --ours path/file

      Трябва обаче да внимавате, защото изтритите промени са елиминирани по някаква причина.

      Свързани: Какво е точното значение на "нашите" и "тях" в git?

    • Редактирайте конфликтните файлове ръчно и намерете кодовия блок между <<<<< / >>>>> , след което изберете версията по-горе или по-долу ===== . Вижте: Как се представят конфликтите .

    • Конфликтите на пътеките и имената на файлове могат да бъдат разрешени с git add / git rm .

  • И накрая, прегледайте файловете, готови за ангажиране, като използвате: git status .

    Ако все още имате файлове под Unmerged paths и сте разрешили конфликта ръчно, тогава дайте на Git да знаете, че сте го разрешили: git add path/file .

  • Ако всички конфликти са били разрешени успешно, копирайте промените: git commit -a и кликнете върху изтрития, както обикновено.

Вижте също: Разрешаване на конфликт на сливане от командния ред в GitHub

DiffMerge

Успешно използвах DiffMerge , който визуално може да сравнява и обединява файлове в Windows, MacOS и Linux / Unix.

Той графично показва промените между 3 файла и позволява автоматично сливане (когато е безопасно) и пълен контрол върху редактирането на получения файл.

2019

05 авг. отговорът е даден kenorb 05 aug. 2015-08-05 17:29 '15 в 17:29 2015-08-05 17:29

Ако често правите малки корекции, започнете с преглеждане на коментарите с git log --merge . Тогава git diff ще ви покаже конфликти.

За конфликти, които включват няколко реда, е по-лесно да се види какво се случва във външния GUI инструмент. Харесва ми opendiff - Git също поддържа vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, излиза от кутията и можете да инсталирате други: git config merge.tool "your.tool" инсталира избрания от вас инструмент и след това git mergetool след неуспешен обединяването ще ви покаже разлики в контекста.

Всеки път, когато редактирате файл, за да разрешите конфликт, git add filename актуализира индекса и вашият diff няма повече да го показва. Когато всички конфликти са обработени и техните файлове са git add към git commit , git commit ще завърши сливането.

75
02 окт. отговорът е даден Павел 02 окт. 2008-10-02 19:11 '08 в 19:11 2008-10-02 19:11

Вижте как са представени конфликтите или в Git, документацията за git merge , за да разберете какво са маркери за конфликтни конфликти.

Освен това в раздела Как се разрешават конфликти се обяснява как да разрешите конфликти:

След като прегледате конфликта, можете да направите две неща:

  • Решете да не се слива. Единствените почистващи средства, от които се нуждаете, са индексиращ файл за нулиране за фиксиране на HEAD за обратното преобразуване 2. и за изчистване на промените в работното селище, направени в 2. и 3; git merge --abort може да се използва за това.

  • Разрешаване на конфликти. Git ще маркира конфликти в работното дърво. Редактирайте файловете във формата и ги git add към индекса. Използвайте git commit да запечатате сделка.

Можете да работите в конфликт с няколко инструмента:

  • Използвайте mergetool. git mergetool да стартира графичен mergetool, който ще работи чрез сливане.

  • Вижте разликите. git diff показва тристранно различие, като подчертава промените от MERGE_HEAD HEAD и MERGE_HEAD .

  • Вижте разликите между всеки клон. git log --merge -p <path> ще покаже diff първо за версията HEAD и след това за версията MERGE_HEAD .

  • Вижте оригиналите. git show :1:filename показва общия прародител, git show :2:filename показва версията на HEAD , а git show :3:filename показва версията на MERGE_HEAD .

Можете също така да прочетете за марката на конфликта за сливане и как да ги разрешите в раздела Pro Git за основните обединения.

43
14 июля '13 в 21:34 2013-07-14 21:34 отговорът е даден от user456814 14 юли '13 в 21:34 2013-07-14 21:34

За Emacs, потребители, които искат да разрешат полу-ръчни конфликти за сливане:

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

Показва всички файлове, които изискват разрешаване на конфликти.

Отворете всеки един от тези файлове един по един или всички наведнъж:

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

Когато посещавате буфер, който изисква редактиране в Emacs, въведете

 ALT+x vc-resolve-conflicts 

Това ще отвори трите буфера (моите, тях и изходния буфер). Навигирайте с натискане на "n" (следващата област), "p" (зона за предсказване). Натиснете "a" и "b", за да копирате съответно моята или вашата област в изходния буфер. И / или редактирайте директно изходния буфер.

Когато приключите: натиснете "q". Emacs ви пита дали искате да запазите този буфер: да. Когато буферът е завършен, маркирайте го като разрешен при стартиране от кастера:

 git add FILENAME 

След като приключите работа с всички видове буфери

 git commit 

за да завършите сливането.

36
23 февр. отговорът е даден eci 23 Feb. 2013-02-23 02:04 '13 в 2:04 2013-02-23 02:04

Аз или искам версията си или версията им напълно, или искам да видя индивидуалните промени и да взема решение за всяка от тях.

Напълно приемам моята или тяхната версия :

Приемете моята версия (местна, нашата):

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

Приемете версията им (изтрити):

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

Ако искате да правите за всички конфликтни файлове, изпълнете:

 git merge --strategy-option ours 

или

 git merge --strategy-option theirs 

Прегледайте всички промени и ги приемете поотделно.

  1. git mergetool
  2. Прегледайте промените и приемете всяка версия за всяка от тях.
  3. git add <filename>
  4. git commit -m "merged bla bla"

По подразбиране mergetool работи в командния ред . Как да използвате командния ред mergetool трябва да бъде отделен въпрос.

Можете също така да инсталирате визуален инструмент за това, например, да се meld и стартирате

 git mergetool -t meld 

Местната (нашата), "основна" или "унифицирана" версия (текущия резултат от сливането) и дистанционното управление ще бъдат отворени. Запазете слятата версия, когато сте готови, изпълнете git mergetool -t meld докато не получите "Няма нужда да обединявате файлове", след това преминете към Стъпка 3 и 4.

28
29 сент. Отговорът е даден от Noidea 29 сеп . 2016-09-29 16:02 '16 в 16:02 2016-09-29 16:02

Моля, изпълнете следните стъпки, за да коригирате конфликтите на сливания в git:

  1. Проверете състоянието на Git: Git Status

  2. Изтеглете набора от корекции: git fetch (проверете правилната корекция от вашия git ангажимент)

  3. Извличане на локален клон (в моя пример, temp1): git checkout -b temp1

  4. Извличане на последно съдържание от майстор: git pull - master начало на произхода

  5. Стартирайте mergetool, проверете конфликтите и ги поправете ... и проверете промените в отдалечения клон с текущия си клон: git mergetool

  6. Проверете отново състоянието: git status

  7. Изтрийте ненужните файлове, създадени локално с mergetool, обикновено mergetool създава допълнителен файл с разширение * .orig. Моля, изтрийте този файл, тъй като той е само дубликат, коригирайте локално промените и добавете правилната версия на файловете си. git добави #your_changed_correct_files

  8. Проверете отново състоянието: git status

  9. Завършете промените в същия идентификатор (това избягва нов отделен набор от поправки): git commit --amend

  10. Натиснете към главния клон: git push (в хранилището на Git)

28
16 апр. Отговорът е даден Chhabilal 16 апр. 2015-04-16 10:02 '15 в 10:02 2015-04-16 10:02

Казано по-просто, ако знаете, че промените в един от хранилищата не са важни и искате да разрешите всички промени в полза на другия, използвайте:

 git checkout . --ours 

разреши промени в полза на хранилището ви или

 git checkout . --theirs 

позволяват промени в полза на друго или основно хранилище .

Или ще трябва да използвате инструмента за сливане на GUI, за да преминете през файловете, да речем, p4merge сливане p4merge , или да напишете всяко име, което вече сте задали.

 git mergetool -t p4merge 

и след завършване на файла ще трябва да запазите и да затворите следващия.

27
26 янв. Отговорено от Мохамед Селим на 26 януари 2016-01-26 20:42 '16 в 20:42 часа 2016-01-26 20:42

Конфликтите за сливане можете да коригирате по няколко начина, както са описани други.

Мисля, че истинският ключ е да знаем как се движат промените с локални и отдалечени хранилища. Ключът към това е разбирането на клоновете за проследяване. Открих, че мисля за клона за проследяване като "липсващата част в средата" между мен, моята локална, действителната директория на файла и отдалеченото, определено като начало.

Аз лично свикнах с две неща, за да избегна това.

Вместо:

 git add . git commit -m"some msg" 

Какво има два недостатъка -

а) Всички нови / модифицирани файлове се добавят и могат да съдържат някои нежелани промени.
b) Не можете първо да прегледате списъка с файлове.

Така че вместо това:

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

По този начин вие по-съзнателно обсъждате кои файлове се добавят и можете също да прегледате списъка и да помислите малко повече, като използвате редактора на съобщението. Намирам, че също така подобрява съобщенията ми за залагане, когато използвам пълния екран, а не опцията -m .

[Актуализация - с течение на времето преминах повече към:

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

]

Също така (и по-подходящо за вашата ситуация) се опитвам да избягвам:

 git pull 

или

 git pull origin master.