Як дазволіць канфлікты зліцця ў Git

Ці ёсць добры спосаб растлумачыць, як вырашаць канфлікты зліцця ў Git?

4274
02 окт. зададзены Spoike 02 каст. 2008-10-02 14:31 '08 у 14:31 2008-10-02 14:31
@ 37 адказаў
  • 1
  • 2

Паспрабуйце: git mergetool

Ён адкрывае графічны інтэрфейс, які праходзіць праз кожны канфлікт, і вы можаце выбраць, як аб'яднаць. Часам гэта патрабуе крыху ручнога рэдагавання пасля, але звычайна гэтага дастаткова само па сабе. Гэта значна лепш, чым рабіць усё ўручную.

Згодна з каментарыю @JoshGlover:

Каманда не абавязкова адкрывае графічны інтэрфейс, калі вы яго не ўсталюеце. Запуск git mergetool для мяне прывёў да выкарыстання vimdiff . Вы можаце ўсталяваць наступныя віды інструментаў, каб выкарыстоўваць яго замест таго, каб: meld , opendiff , kdiff3 , tkdiff , xxdiff , tortoisemerge , gvimdiff , diffuse , ecmerge , p4merge , araxis , vimdiff , emerge .

Ніжэй прыведзены прыклад працэдуры выкарыстання 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 - файл, які вы аб'ядноўваеце у сваю галінку

MERGED - вынік зліцця, гэта тое, што захоўваецца ў РЭПО

Вы можаце перамяшчацца паміж гэтымі ўяўленнямі, выкарыстоўваючы 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 окт. адказ дадзены Peter Burns 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 часопіс у якасці дадатку.

Вось некалькі саветаў:

рада адзін

Самае лепшае, што я знайшоў, гэта выкарыстоўваць стыль канфлікту зліцця "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. >>>>>>> merged into <<<<<<< 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. >>>>>>> checked out <<<<<<< 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. >>>>>>> merged in <<<<<<< 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-Ханка. Я лічу, што гэта адцягвае.

Савет два

Хтосьці ўжо згадаў пра гэта, але разуменне намеры за кожным словам diff звычайна карысна для разумення таго, адкуль паўстаў канфлікт і як яго апрацоўваць.

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

Гэта паказвае ўсе камітаў, якія тычыліся гэтага файла паміж агульным продкам і двума галовамі, якія вы аб'ядноўваеце. (Такім чынам, ён не ўключае ў сябе камітаў, якія ўжо існуюць у абедзвюх галінах да зліцця.) Гэта дапамагае ігнараваць адрозненні, якія відавочна не з'яўляюцца фактарам у вашым канфлікту.

Савет тры

Праверце свае змены з дапамогай аўтаматызаваных інструментаў.

Калі ў вас ёсць аўтаматычныя тэсты, запусціце іх. Калі ў вас ёсць lint , запусціце яго. Калі гэта будаўнічы праект, тады яго неабходна пабудаваць да таго, як вы здзейсніце і г.д. Ва ўсіх выпадках вам трэба трохі прайсці тэставанне, каб пераканацца, што вашыя змены нічога не зламалі. (Чорт, нават зліццё без канфліктаў можа парушыць працоўны код.)

Савет чатыры

Плануйце загадзя; мець зносіны з калегамі.

Планаванне наперад і ўсведамленне таго, што працуюць іншыя, можа дапамагчы прадухіліць канфлікты зліцця і / або дапамагчы вырашыць іх раней - у той час як дэталі ўсё яшчэ актуальныя.

Напрыклад, калі вы ведаеце, што вы і іншы чалавек працуюць над рознымі рэфактарынгу, якія будуць уплываць на адзін і той жа набор файлаў, вам варта пагаварыць адзін з адным загадзя і лепш зразумець, якія тыпы змяненняў кожны з вас робіць. Вы можаце зэканоміць нямала часу і намаганняў, калі праводзіць запланаваныя змены па чарзе, а не паралельна.

Для буйных рэфактарынгу, якія перасякаюць вялікі фрагмент кода, вы павінны сур'ёзна разгледзець магчымасць працы паслядоўна: кожны перастае працаваць над гэтай вобласцю кода, а адзін чалавек выконвае поўны рэфактарынг.

Калі вы не можаце працаваць паслядоўна (з-за часовага ціску, магчыма), то зносіны аб чаканых канфліктах зліцця, па меншай меры, дапаможа вам вырашыць праблемы раней, пакуль дэталі яшчэ свежыя. Напрыклад, калі супрацоўнік здзяйсняе разбуральную серыю камітаў на працягу аднаго тыдня, вы можаце захацець аб'яднаць / переупаковать гэтую галінку адзін ці два разы на дзень на гэтым тыдні. Такім чынам, калі вы знойдзеце канфлікты зліцця / пераадрасацыі, вы можаце вырашыць іх хутчэй, чым калі вы пачакаеце некалькі тыдняў, каб аб'яднаць усе разам у адзін вялікі кавалак.

Савет пяць

Калі вы не ўпэўненыя ў зліцці, ня прымушайце яго.

Зліццё можа адчувацца пераважнай, асабліва калі ёсць шмат канфліктуючых файлаў, а маркеры канфліктаў ахопліваюць сотні радкоў. Часта пры ацэнцы праграмных праектаў мы не ўключаем дастаткова часу для надбавак, такіх як апрацоўка вар'ята зліцця, таму ён адчувае сябе як рэальнае супраціў, каб выдаткаваць некалькі гадзін на аналіз кожнага канфлікту.

У доўгатэрміновай перспектыве планаванне наперад і ўсведамленне таго, што працуюць іншыя, з'яўляюцца лепшымі прыладамі для прагназавання канфліктаў зліцця і падрыхтоўкі да правільнага іх вырашэнню за меншы час.

696
29 сент. адказ дадзены Mark E. Haase 29 сент. 2011-09-29 00:08 '11 у 0:08 2011-09-29 00:08
  • Вызначце, якія файлы знаходзяцца ў канфлікце (Git павінен сказаць вам гэта).

  • Адкрыйце кожны файл і вывучыце адрозненні; Git демаркирует іх. Спадзяюся, будзе відавочна, якую версію кожнага блока захаваць. Магчыма, вам прыйдзецца абмеркаваць гэта з іншымі распрацоўшчыкамі, якія здзейснілі код.

  • Як толькі вы дазволілі канфлікт у файле git add the_file .

  • Як толькі вы дазволіце канфлікты all, выканайце git rebase --continue або любую каманду Git сказаў, калі скончыце.

326
02 окт. адказ дадзены davetron5000 02 каст. 2008-10-02 15:41 '08 у 15:41 2008-10-02 15:41

Праверце адказы ў пытанні Адмена зліцця ў Git , асабліва Адказ Чарльза Бейлі , які паказвае, як праглядаць розныя версіі файла з праблемамі, напрыклад

100
03 окт. адказ дадзены Pat Notz 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

      Аднак вы павінны быць асцярожныя, паколькі аддаленыя змены па нейкіх прычынах былі ліквідаваны.

      Звязана: Якое дакладнае значэнне "ours" і "іх" у 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 жнів. 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, emerge з скрынкі, і вы можаце ўсталяваць іншыя: git config merge.tool "your.tool" ўсталюе ваш абраны інструмент, а затым git mergetool пасля няўдалага зліцця пакажа вам адрозненні ў кантэксце.

Кожны раз, калі вы рэдагуеце файл для дазволу канфлікту, git add filename абнаўляе індэкс, і ваш diff больш не будзе яго паказваць. Калі ўсе канфлікты апрацоўваюцца і іх файлы былі git add -ed, git commit завершыць зліццё.

75
02 окт. адказ дадзены Paul 02 каст. 2008-10-02 19:11 '08 у 19:11 2008-10-02 19:11

См. Як канфлікты прадстаўлены або ў Git, дакументацыі git merge , каб зразумець, што такое маркеры канфліктаў зліцця.

Акрамя таго, у раздзеле Як дазволіць канфлікты тлумачыцца, як вырашаць канфлікты:

Пасля прагляду канфлікту вы можаце зрабіць дзве рэчы:

  • Вырашыце ня злівацца. Адзіныя ачышчальнікі, якія вам патрэбныя, - гэта reset індэксны файл для фіксацыі HEAD для зваротнага пераўтварэння 2. і для ачысткі працоўных вясковых змяненняў, зробленых у 2. і 3; git merge --abort можна выкарыстоўваць для гэтага.

  • Дазволіць канфлікты. Git будзе адзначаць канфлікты ў працоўным дрэве. Адрэдагуйце файлы ў форме і git add іх у індэкс. Выкарыстоўвайце git commit , каб запячатаць здзелку.

Вы можаце працаваць у канфлікце з дапамогай некалькіх інструментаў:

  • Выкарыстоўвайце mergetool. git mergetool , каб запусціць графічны mergetool, які будзе працаваць праз зліццё.

  • Паглядзіце на адрозненні. git diff адлюстроўвае трохбаковы diff, вылучаючы змены як з версій 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 февр. 2013-02-23 02:04 '13 у 02: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

  2. Атрымаеце набор патчаў: git fetch (праверце правільны патч з вашага камітаў Git)

  3. Выняць лакальную галінку (у маім прыкладзе гэта temp1): git checkout -b temp1

  4. Дастаньце нядаўняе змесціва з master: git pull --rebase origin master

  5. Запусціце mergetool, праверце канфлікты і выпраўце іх ... і праверце змены ў выдаленай галінцы з вашай бягучай галінкай: git mergetool

  6. Праверце статус зноў: git status

  7. Выдаліце ​​непатрэбныя файлы, лакальна створаныя з дапамогай mergetool, звычайна mergetool стварае дадатковы файл з пашырэннем * .orig. Калі ласка, выдаліце ​​гэты файл, таму што гэта проста дублікат, выпраўце змены лакальна і дадайце правільную версію вашых файлаў. git add #your_changed_correct_files

  8. Праверце статус зноў: git status

  9. Зафіксуйце змены ў адным і тым жа ідэнтыфікатары (гэта дазваляе пазбегнуць новага асобнага набору выпраўленняў): git commit --amend

  10. Push у галінку master: 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 , або напісаць любое імя, якое вы ўжо ўсталявалі

 git mergetool -t p4merge 

і пасля завяршэння файла вам прыйдзецца захаваць і закрыць, каб адкрыць наступны.

27
26 янв. адказ дадзены Mohamed Selim 26 студз. 2016-01-26 20:42 '16 у 20:42 2016/01/26 20:42

Вы можаце выправіць канфлікты зліцця некалькімі спосабамі, як іншыя дэталізаваў.

Я думаю, што рэальны ключ - гэта веданне таго, як змены цякуць з лакальнымі і выдаленымі рэпазітарамі. Ключом да гэтага з'яўляецца разуменне галін адсочвання. Я выявіў, што я думаю пра галінцы адсочвання як "якая адсутнічае часткі ў сярэдзіне" паміж мной, маім лакальным, фактычным файлавым каталогам і выдаленым, што вызначаюцца як паходжанне.

Я асабіста прывык да двум рэчам, каб дапамагчы пазбегнуць гэтага.

замест:

 git add . git commit -m"some msg" 

Што мае два недахопу -

a) Усе новыя / змененыя файлы дадаюцца і могуць утрымліваць некаторыя непажаданыя змены.
б) Вы не можаце спачатку паглядзець сьпіс файлаў.

Такім чынам, замест гэтага:

 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.