Як вирішити конфлікти злиття в Git


4764

Як вирішити конфлікти злиття в Git?


31
Наступна публікація в блозі, здається, дає дуже хороший приклад того, як вирішити конфлікт злиття з Git, який повинен навести вас у правильному напрямку. Поводження та уникнення конфліктів у Git
mwilliams

4
Ви можете налаштувати інструмент злиття (kdiff3 jebaird.com/2013/07/08/… ), а потім використовувати git mergetool. Працюючи у великих командах розробників, ви завжди стикаєтеся з конфліктами злиття.
Grady G Cooper

Не забувайте, що ви можете пом'якшити більшість конфліктів, що зливаються, регулярно об'єднуючись за течією!
Мураха P


8
Захоплююче питання: Заданий у 2008 році, 100% відкритість закінчилася зовсім не натяком на те, про що йдеться насправді (це про GUI? Про команди git? Про семантику? Про штовхання / потягування чи просто загальні конфлікти?) - абсолютно невідчутно. 30 відповідей, всі вони (наскільки швидкий погляд показує) більш-менш продовжують працювати над різними інструментами diff3 та злиття, жодної не прийнято. Відповідь, що голосує вгорі, згадує команду, яка не працює навіть із встановленої за замовчуванням gitустановки. Мені вдалося потрапити на початкову сторінку SE для мене сьогодні, 2017, з 1,3 мільйонами переглядів та тисячами голосів обома способами. Захоплююче.
AnoE

Відповіді:


2911

Спробуйте: 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 - це файл з поточної гілки

БАЗА - звичайний пращур, як файл виглядав до обох змін

ВИДАЛЕНО - файл, який ви об’єднуєте у свою філію

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.


54
Ви можете скористатися git mergetool -yдля збереження декількох натискань клавіш, якщо об’єднаєте багато файлів одночасно.
davr

373
Ну, це не обов'язково відкривати графічний інтерфейс, якщо ви не встановите його. Біг git mergetoolдля мене призвів до vimdiffвикористання. Ви можете встановити один з наступних інструментів , щоб використовувати його замість: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge.
Джош Гловер

31
Хороший момент Джош. У ubuntu мені пощастило з meld, його тристоронній дисплей злиття непоганий. На OSX git вибрав хороший за замовчуванням.
Пітер Бернс

18
Це відкрило KDiff3. Який у мене абсолютно немає поняття, як користуватися.
Девід Мердок

7
Ви також можете використовувати Beyond Compare 3 зараз ( git mergetool -t bc3).
AzP

1703

Ось вірогідний випадок використання зверху:

Ви збираєтеся внести деякі зміни, але, на жаль, ви не в курсі:

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.

Тож ви вирішили поглянути на зміни:

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.

Та-да!


19
Це було дуже корисно, тому що у мене було багато помилок злиття з бінарними файлами (художніми активами), а об'єднання цих даних, здається, завжди не вдається, тому мені потрібно перезаписувати його з новим файлом завжди, а не "зливати"
petrocket

188
Обережно! Значення --ours та --theirs - зворотне. --в = = віддалений. --theirs == місцеві. Дивітьсяgit merge --help
mmell

57
У моєму випадку я підтверджую, що --theirs = віддалений сховище, --ours = мій власний локальний сховище. Це протилежне коментарям @mmell.
Арьо

24
@mmell Тільки на ребазі, мабуть. Дивітьсяthis question
Навін

184
Хлопці, "наші" та "їхні" відносно того, чи зливаєте ви, чи відновлюєте. Якщо ви зливаєтеся , то "наша" означає гілку, в яку ви зливаєтесь, а "їхня" - це галузь, в яку ви зливаєтесь. Коли ви перезапускаєте , то "наша" означає зобов'язання, на які ви відновлюєте. , тоді як "їхнє" посилається на документи, які ви хочете перезавантажити.

736

Я знаходжу інструменти злиття рідко допомагають мені зрозуміти конфлікт чи вирішення. Зазвичай я успішніше дивлюся на маркери конфліктів у текстовому редакторі і використовую журнал 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 (i.e. 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

Це не те саме, що використовувати інструмент злиття, оскільки інструмент злиття буде включати в себе і всі неконфліктні розрізнення. Я вважаю, що це відволікає.

Порада друга

Хтось уже згадував про це, але розуміння наміру, що стоїть за кожною різною частиною, як правило, дуже корисно для розуміння, звідки виник конфлікт і як його впоратися.

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

Тут відображаються всі коміти, які торкнулися цього файлу між загальним предком і двома головами, які ви зливаєте. (Отже, він не включає комітети, які вже існують в обох гілках перед об'єднанням.) Це допомагає вам ігнорувати різні переклади, які явно не є фактором у вашому поточному конфлікті.

Порада третя

Перевірте свої зміни за допомогою автоматизованих інструментів.

Якщо у вас є автоматизовані тести, запустіть їх. Якщо у вас є обличчя , запустіть це. Якщо це збірний проект, то складіть його перед тим, як здійснити виконання, і т. Д. У всіх випадках вам потрібно зробити трохи тестування, щоб переконатися, що ваші зміни нічого не порушили. (Хек, навіть злиття без конфліктів може порушити робочий код.)

Порада четверта

Планувати заздалегідь; спілкуватися з колегами.

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

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

Що стосується великих рефактори, які вирізають велику частину коду, слід наполегливо розглянути можливість послідовної роботи: усі припиняють роботу над цією областю коду, тоді як одна людина виконує повний рефакторинг.

Якщо ви не можете працювати серійно (можливо, через тиск у часі), то спілкування про очікувані конфлікти злиття принаймні допомагає вирішити проблеми швидше, поки деталі ще свіжі. Наприклад, якщо працівник колективу робить порушуючий ряд зобов’язань протягом одного тижня, ви можете вирішити об'єднання / повторне базування цього відділення співробітників один або два рази на день протягом цього тижня. Таким чином, якщо ви знайдете конфлікти злиття / відновлення, ви можете вирішити їх швидше, ніж якщо зачекати кілька тижнів, щоб злити все разом в один великий грудочок.

Порада п’ята

Якщо ви не впевнені в злитті, не змушуйте його.

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

Зрештою, планування заздалегідь та усвідомлення того, над чим працюють інші, є найкращими інструментами для передбачення конфліктів злиття та підготуйтеся до їх правильного вирішення за менший час.


6
Варіант diff3 - це відмінна функція, яка має бути злиттями. Єдиний графічний інтерфейс, на який я стикався, показує, що це Perforce's p4merge, який можна встановити та використовувати окремо від інших інструментів Perforce (які я не використовував, але чув скарги на це).
alxndr

3
Після спроби відновлення бази даних, яка призвела до конфлікту злиття: $ git log --merge -p build.xml output: fatal: --merge без MERGE_HEAD?
Ед Рендалл

що робити, якщо у мене є зміни в одному файлі з відділення1 та видалення цього файлу в гілці2. Як я можу вирішити конфлікт злиття? Чи є спосіб використання git, де я можу їх об'єднати, зберігаючи зміни однієї гілки?
Мед

git config merge.conflictstyle diff3- Дякую вам сер. Це дивовижно і звільнило мене від спроб знайти (і заплатити $$) за хороший інтерфейс графічного інтерфейсу в 3 способи. IMO це краще, тому що він показує загального предка, а також локальний / віддалений, і показує останні рядки журналу фіксування, які (AFAIK) не робить GUI. Коміти, безумовно, допоможуть вам визначити, який код належить до тієї галузі.
ffxsam

Я виявив, що іноді конфліктний стиль diff3 призводить до величезних розрізень, які в значній мірі однакові, тоді як за замовчуванням створюються більш дрібні, більш керовані. На жаль, у мене немає репродуктора, який я можу використовувати для звіту про помилку. Але якщо ви зіткнулися з цією проблемою, ви можете розглянути можливість тимчасового вимкнення цього параметра.
Дейв Абрахамс

348
  1. Визначте, які файли конфліктують (Git повинен вам це сказати).

  2. Відкрийте кожен файл і вивчіть відмінності; Гіт розмежовує їх. Сподіваємось, буде очевидно, яку версію кожного блоку зберігати. Можливо, вам доведеться обговорити це з іншими розробниками, які ввели код.

  3. Після вирішення конфлікту у файлі git add the_file.

  4. Після того як ви вирішите всі конфлікти, виконайте git rebase --continueабо будь-яку команду, яку сказав Git, коли ви виконали.


38
@Justin Подумайте про Git як відстеження вмісту, а не для відстеження файлів. Тоді легко помітити, що оновлений оновлений вміст не знаходиться у сховищі і його потрібно додати. Такий спосіб мислення також пояснює, чому Git не відстежує порожні папки: Хоча технічно вони є файлами, не можна відстежувати вміст.
Гарет

7
вміст є, конфлікт виникає через те, що існує 2 версії вмісту. Тому "git add" не звучить правильно. І це не працює (git add, git commit), якщо ви хочете зробити лише те, що один файл після вирішення конфлікту був вирішений ("фатально: не можна зробити часткове здійснення під час злиття.")
Dainius

1
Так, технічно це відповідає на запитання, яке, як і задали, але не є корисною, на мій погляд, вибачте. Який сенс зробити одну гілку такою ж, як і іншу? Звичайно, злиття матимуть конфлікти ..
Туфір

5
Тульфір: хто що сказав про те, щоб зробити одну гілку такою ж, як і іншу? Існують різні сценарії, коли вам потрібно об'єднатись, не "роблячи одну гілку такою ж, як іншу". Перший - це коли ви закінчите з галуззю розвитку і хочете включити її зміни в головну гілку; після цього гілку розвитку можна видалити. Інший - коли ви хочете відновити свою галузь розробки, щоб полегшити можливе остаточне злиття в головний майстер.
Teemu Leisti

4
@JustinGrant git addставить файли в індекс; він нічого не додає до сховища. git commitдодає речі до сховища. Це використання має сенс для злиття - злиття автоматично стадіює всі зміни, які можна об'єднати автоматично; Ваша відповідальність - об'єднати решту змін і додати їх до індексу, коли Ви закінчите.
Марк Е. Хааз

105

Перегляньте відповіді на запитання про переповнення стека. Скасування злиття в Git , особливо відповідь Чарльза Бейлі, яка показує, як переглянути різні версії файлу з проблемами, наприклад,

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

Також ознайомтесь з опцією "-m" на "git checkout -m" - це дозволяє витягувати різних мух назад на робочу область
qneill

Це врятувало мене. Перегляд кожного файлу окремо дозволив мені пригадати, що я збирався робити у кожній гілці. Тоді я міг прийняти рішення вибрати.
Ромер

99

Конфлікти злиття трапляються, коли в файл одночасно вносяться зміни. Ось як це вирішити.

git CLI

Ось прості кроки, що потрібно робити, коли потрапляєш у конфліктний стан:

  1. Зверніть увагу на список конфліктуючих файлів за допомогою: git status(під Unmerged pathsрозділом).
  2. Вирішіть конфлікти окремо для кожного файлу одним із наступних підходів:

    • Використовуйте GUI для вирішення конфліктів: git mergetool(найпростіший спосіб).

    • Для того, щоб прийняти віддалений / інші версії, використання: git checkout --theirs path/file. Це відхилить усі локальні зміни, які ви зробили для цього файлу.

    • Щоб прийняти локальну / нашу версію, використовуйте: git checkout --ours path/file

      Однак ви повинні бути обережними, оскільки віддалені зміни, які конфлікти були зроблені з якоїсь причини.

      Супутнє: Яке точне значення "наше" та "їхнє" в git?

    • Відредагуйте конфліктні файли вручну та знайдіть код коду між <<<<</ >>>>>та виберіть версію зверху чи знизу =====. Див.: Як представлені конфлікти .

    • Конфлікти шляху та імен можна вирішити за допомогою git add/ git rm.

  3. Нарешті, перевірте файли готові для фіксації з допомогою: git status.

    Якщо у вас є якісь - або файли в Unmerged paths, і ти розв'язати конфлікт вручну, то нехай Git знаю , що ви вирішили його: git add path/file.

  4. Якщо всі конфлікти були вирішені успішно, введіть зміни за допомогою: git commit -aта натисніть на віддалений як завжди.

Дивіться також: Вирішення конфлікту злиття з командного рядка в GitHub

Для практичного підручника перевірте: Сценарій 5 - Виправлення конфліктів злиття від Katacoda .

DiffMerge

Я успішно використовував DiffMerge, який дозволяє візуально порівнювати та об’єднувати файли в Windows, macOS та Linux / Unix.

Він графічно може відображати зміни між 3 файлами, і це дозволяє автоматичне об'єднання (коли це безпечно) та повний контроль над редагуванням отриманого файлу.

DiffMerge

Джерело зображення: DiffMerge (скріншот Linux)

Просто завантажте його та запустіть у репо як:

git mergetool -t diffmerge .

macOS

На macOS ви можете встановити через:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

І, ймовірно, (якщо це не передбачено) вам потрібні такі додаткові прості обгортки, які розміщені у вашій PATH (наприклад /usr/bin):

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

Тоді ви можете використовувати наступні комбінації клавіш:

  • - Alt- Up/ Downдля переходу до попередніх / наступних змін.
  • - Alt- Left/ Rightприймати зміни зліва або справа

Крім того, ви можете використовувати opendiff (частина інструментів Xcode), яка дозволяє об'єднати два файли або каталоги разом, щоб створити третій файл або каталог.


79

Якщо ви робите часті невеликі комітети, то почніть з перегляду коментарів із виконання git log --merge. Тоді git diffпокажуть вам конфлікти.

У конфліктах, які містять більше кількох рядків, простіше зрозуміти, що відбувається у зовнішньому інструменті графічного інтерфейсу. Мені подобається opendiff - Git також підтримує vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, вийде з коробки і ви можете встановити інші: git config merge.tool "your.tool"встановіть вибраний інструмент, а потім git mergetoolпісля невдалого злиття покаже вам відмінності в контексті.

Кожен раз, коли ви редагуєте файл, щоб вирішити конфлікт, git add filenameоновити індекс, і ваш розмінник більше не відображатиме його. Коли всі конфлікти будуть вирішені, а їхні файли git add-ed, git commitзавершиться злиттям.


8
Використання "git add" - справжня хитрість тут. Можливо, ви навіть не хочете виконувати зобов’язання (можливо, ви хочете приховати), але вам доведеться зробити "git add", щоб завершити злиття. Я думаю, що mergetool робить додаток для вас (хоча його немає на сторінці сторінки), але якщо ви зробите злиття вручну, вам потрібно скористатися "git add", щоб завершити його (навіть якщо ви не хочете робити зобов'язання).
nobar

47

Перегляньте, як представлені конфлікти або документацію в Git, git mergeщоб зрозуміти, що таке маркери конфліктів злиття.

Також у розділі " Як вирішити конфлікти " пояснюється спосіб вирішення конфліктів:

Побачивши конфлікт, ви можете зробити дві речі:

  • Вирішіть не зливатися. Єдині необхідні очищення - це скинути індексний файл до HEADзобов’язання обернути реверс 2. та очистити зміни робочого дерева, внесені на 2. та 3.; git merge --abortможна використовувати для цього.

  • Вирішіть конфлікти. Git позначить конфлікти в робочому дереві. Відредагуйте файли у формі та додайте git addїх до індексу. Використовуйте git commitдля підписання угоди.

Ви можете працювати через конфлікт з низкою інструментів:

  • Використовуйте mergetool. git mergetoolзапустити графічний mergetool, який пропрацює вас через злиття.

  • Подивіться на відмінності. git diffпокаже тристоронній розбіг, виділивши зміни як версій, так HEADі MERGE_HEADверсій.

  • Подивіться на відмінності кожної галузі. git log --merge -p <path>покаже розходження для HEADверсії, а потім для MERGE_HEADверсії.

  • Подивіться на оригінали. git show :1:filenameпоказує загального предка, git show :2:filenameпоказує HEADверсію та git show :3:filenameпоказує MERGE_HEADверсію.

Ви також можете прочитати про злиття конфліктних маркерів та способи їх вирішення в розділі книги Pro Git Основні конфлікти злиття .


42

Я або хочу, щоб моя або їх версія була повністю, або хочу переглянути окремі зміни та прийняти рішення щодо кожної з них.

Повністю прийміть мою чи їхню версію :

Прийміть мою версію (локальну, нашу):

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.


Ця команда: git checkout --theirs - <ім'я_файлу> змінила ВСІ файли на свої, а не лише <ім'я_файлу>
Donato

Насправді я помилявся. Це лише оновлення вказаного файлу.
Донато

40

Для користувачів 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

закінчити злиття.


33

Бонус:

Говорячи про тягнення / отримання / злиття у вищезазначених відповідях, я хотів би поділитися цікавим та продуктивним трюком,

git pull --rebase

Ця вище команда - найкорисніша команда в моєму житті git, яка зекономила багато часу.

Перед тим, як натиснути щойно здійснену зміну на віддалений сервер, спробуйте git pull --rebaseскоріше git pullі вручну, mergeі вона автоматично синхронізує останні зміни на віддаленому сервері (із вилученням і злиттям) і поставить останню локальну фіксацію вгорі в журналі git. Не потрібно турбуватися про ручне потягування / злиття.

У разі конфлікту просто використовуйте

git mergetool
git add conflict_file
git rebase --continue

Деталі можна знайти на веб- сайті: http://gitolite.com/git-pull--rebase


32

Просто, якщо ви добре знаєте, що зміни в одному з сховищ не є важливими, і хочете вирішити всі зміни на користь іншого, скористайтеся:

git checkout . --ours

щоб вирішити зміни на користь вашого сховища , або

git checkout . --theirs

вирішити зміни на користь іншого чи основного сховища .

Або ж вам доведеться використовувати інструмент злиття графічного інтерфейсу, щоб переглядати файли один за одним, скажімо, інструмент злиття є p4merge, або написати будь-яке ім’я, яке ви вже встановили

git mergetool -t p4merge

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


2
git checkout. - їхні вирішили мою проблему завдяки
Рамеш Чанд

якщо ви віддаєте перевагу вирішенню конфліктів вручну, спробуйте відкрити папку у коді Visual Studio, вона позначає файли з конфліктами та кольорами конфліктних ліній всередині кожного
Мохамед Селім

31

Виконайте наступні кроки, щоб виправити конфлікти злиття в Git:

  1. Перевірте статус Git: статус git

  2. Отримайте патчсет: git fetch ( оформити правильний патч від вашої Git комісії)

  3. Оформити локальну гілку (temp1 у моєму прикладі тут): git checkout -b temp1

  4. Витягніть останній вміст з master: git pull - master master origin

  5. Запустіть mergetool і перевірте конфлікти та виправте їх ... і перевірте зміни у віддаленій гілці за допомогою вашої поточної гілки: git mergetool

  6. Перевірте статус ще раз: статус git

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

  8. Перевірте статус ще раз: статус git

  9. Введіть зміни в той самий id комісії (це дозволяє уникнути нового окремого набору патчів): git commit --amend

  10. Натисніть на головну гілку: git push (до вашого сховища Git)


28

Є 3 кроки:

  1. Знайдіть, які файли викликають конфлікти за командою

    git status
    
  2. Перевірте файли, в яких ви знайдете конфлікти, позначені як

    <<<<<<<<head
    blablabla
    
  3. Змініть його так, як вам потрібно, а потім виконайте команди

    git add solved_conflicts_files
    git commit -m 'merge msg'
    

Працювали для мене! Дякую!
Nuwan Jayawardene

Ви повинні звернути увагу, якщо це зробити під час перезавантаження. Ви повинні використовувати git rebase - продовжувати замість git commit
Samuel Dauzon

27

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

Я думаю, що справжнім ключем є те, як змінюються зміни з локальними та віддаленими сховищами. Ключовим моментом є розуміння відстеження гілок. Я виявив, що я вважаю гілку відстеження як "пропущений фрагмент в середині" між мною моїм локальним, фактичним каталогом файлів і віддаленим, визначеним як джерело.

Я особисто ввійшов у звичку 2 речі, щоб допомогти цього уникнути.

Замість:

git add .
git commit -m"some msg"

У якого є два недоліки -

а) Додаються всі нові / змінені файли, які можуть включати небажані зміни.
б) Ви не спершу переглядаєте список файлів.

Тому замість цього я роблю:

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.

тому що притягування передбачає злиття, і якщо у вас є місцеві зміни, які ви не хотіли об'єднати, ви можете легко закінчити об'єднаний код та / або конфлікти злиття для коду, який не повинен був бути об'єднаний.

Натомість я намагаюся це зробити

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

Ви також можете скористатися цією корисною:

git гілка, вилка, витяг, злиття, відновлення та клонування, які відмінності?


Гей, я якось зрозумів вашу відповідь. Але оскільки я новачок у конфліктах злиття Github, я думаю, чогось не вистачає. Що відбувається з вашими локальними модифікаціями, коли ви робите git checkout masterта git fetch і git rebase --hard origin/master
Suhaib

Я вважаю, що вам слід додати більше інформації про те, що робити. Ще один приклад, який мене бентежить, ви згадали у своїй відповіді: ми це зробимо git add ., чи збережемо наші локальні модифікації, щоб ми могли продовжувати роботу git checkout master? чи це два різні сценарії?
Suhaib

@MichaelDurrant $ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option hard 'використання: git rebase [-i] [параметри] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] або: git rebase [-i] [ параметри] [--exec <cmd>] [--onto <newbase>] --root [<Branch>] або: git rebase - продовжити | --аборт | --скіп | --edit-todo `
likejudo

24

Відповідь CoolAJ86 підсумовує майже все. Якщо у вас є зміни в обох гілках в одному і тому ж фрагменті коду, вам доведеться виконати об'єднання вручну. Відкрийте файл в конфлікті в будь-якому текстовому редакторі, і ви повинні побачити наступну структуру.

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

Виберіть одну з альтернатив або комбінацію обох способів, яким ви хочете, щоб був новий код, видаляючи однакові знаки та кутові дужки.

git commit -a -m "commit message"
git push origin master

17
git log --merge -p [[--] path]

Мабуть, не завжди працює для мене, і зазвичай в кінцевому підсумку відображається кожен комітет, який відрізнявся між двома гілками, це відбувається навіть при використанні --для відділення шляху від команди.

Що я роблю для вирішення цього питання - це відкрити два командні рядки та за один пробіг

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

а в іншому

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

Замінившись $MERGED_IN_BRANCHіз гілкою, я злився і [path]з файлом, який конфліктує. Ця команда буде реєструвати всі коміти у формі виправлення між ( ..) двома комітами. Якщо ви залишите одну сторону порожньою, як у командах над git, автоматично використовуватиметься HEAD(гілка, в яку ви зливаєтеся в цьому випадку).

Це дозволить вам побачити, які коміти входили у файл у двох гілках після їх розбіжності. Зазвичай це значно полегшує вирішення конфліктів.


16

Використання patience

Я здивований, що ніхто не говорив про вирішення конфлікту за patienceдопомогою рекурсивної стратегії злиття. Для великого конфлікту злиття, використовуючи patienceхороші результати для мене. Ідея полягає в тому, що вона намагатиметься відповідати блокам, а не окремим рядкам.

Якщо змінити відступ програми, наприклад, стратегія злиття Git за замовчуванням іноді відповідає одній дужці, {яка належить до різних функцій. Цього уникнути patience:

git merge -s recursive -X patience other-branch

З документації:

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

Порівняння із загальним предком

Якщо у вас конфлікт злиття і хочете побачити, що мали на увазі інші, змінюючи свою гілку, іноді простіше порівняти їх гілку безпосередньо із загальним предком (замість нашої гілки). Для цього ви можете використовувати merge-base:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

Зазвичай ви хочете бачити лише зміни для певного файлу:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>

У моєму випадку це не добре вирішило конфлікти злиття, оскільки чомусь воно зберігало повторювані рядки конфігурації у проектах C #. Хоча це було більш доброзичливим, ніж ЦІЛЬКИЙ ФАЙЛ Є РІЗНИМ, що я мав раніше
Mathijs Segers

15

З 12 грудня 2016 року ви можете об’єднати гілки та вирішити конфлікти на github.com

Таким чином, якщо ви не хочете використовувати командний рядок або будь-які сторонні інструменти, які тут пропонуються зі старих відповідей , перейдіть з нативним інструментом GitHub.

У цьому дописі в блозі докладно роз'яснено, але основи полягають у тому, що при "об'єднанні" двох гілок через інтерфейс користувача ви побачите параметр "вирішити конфлікти", який переведе вас до редактора, що дозволяє вирішувати ці конфлікти злиття.

введіть тут опис зображення


це не запитання про github, тому я вниз проголосував за те, що я вважаю дуже поганою відповіддю.
mschuett

1
@mschuett має рацію, питання полягає в "як вирішити конфлікти в git", а не "як вирішити конфлікти в github". Різниця є, і вже дуже багато людей, які думають, що git і github - це одне і те ж, тому все, що поширює це почуття, не є правильним.
Патрік Мевзек

15

Якщо ви хочете об'єднатись з гілки (тесту) в master, виконайте наступні дії:

Крок 1 : Перейдіть до гілки

git checkout test

Крок 2 :

git pull --rebase origin master

Крок 3 : Якщо є деякі конфлікти, перейдіть до цих файлів, щоб змінити їх.

Крок 4 : Додайте ці зміни

git add #your_changes_files

Крок 5 :

git rebase --continue

Крок 6 : Якщо конфлікт все ще існує, поверніться до кроку 3 знову. Якщо конфлікту немає, зробіть наступне:

git push origin +test

Крок 7 : І тоді між тестом і майстром немає конфлікту. Ви можете використовувати об'єднання безпосередньо.


13

Я завжди дотримуюся наведених нижче кроків, щоб уникнути конфліктів.

  • git checkout master (Приходьте у майстер-відділення)
  • git pull (Оновіть свого майстра, щоб отримати останній код)
  • git checkout -b mybranch (Ознайомтесь з новою гілкою і почніть працювати над цією гілкою, щоб ваш господар завжди залишався вгорі стовбура.)
  • git add. І git фіксують і git push (у вашому місцевому відділенні після змін)
  • git checkout master (Поверніться до свого господаря.)

Тепер ви можете зробити те саме і підтримувати стільки місцевих гілок, які ви хочете, і працювати одночасно, я просто роблю виїзд у ваш відділення, коли це буде потрібно.


12

Конфлікти злиття можуть виникати в різних ситуаціях:

  • Під час запуску "git fetch", а потім "git merge"
  • Під час запуску "git fetch", а потім "git rebase"
  • Під час запуску "git pull" (що фактично дорівнює одній із вищезазначених умов)
  • Під час запуску "git stash pop"
  • Коли ви застосовуєте git-патчі (комісії, які експортуються у файли, що передаються, наприклад, електронною поштою)

Для вирішення конфліктів вам потрібно встановити інструмент злиття, сумісний з Git. Я особисто використовую KDiff3, і мені це було приємно і зручно. Ви можете завантажити його версію для Windows тут:

https://sourceforge.net/projects/kdiff3/files/

BTW, якщо ви встановлюєте Git Extensions, у його майстра налаштування є можливість встановити Kdiff3.

Потім встановіть конфігурації git, щоб використовувати Kdiff як свій mergetool:

$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false

$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false

(Не забудьте замінити шлях фактичним шляхом до файлу Kdiff exe.)

Потім кожного разу, коли ви стикаєтеся з конфліктом злиття, вам просто потрібно виконати цю команду:

$git mergetool

Потім він відкриває Kdiff3 і спочатку намагається вирішити конфлікти злиття автоматично. Більшість конфліктів буде вирішено спонтанно, а решту потрібно виправити вручну.

Ось як виглядає Kdiff3:

Введіть тут опис зображення

Потім, як тільки ви закінчите, збережіть файл, і він перейде до наступного файлу з конфліктом, і ви знову зробите те саме, поки всі конфлікти не будуть вирішені.

Щоб перевірити, чи все об’єднано успішно, просто запустіть команду mergetool ще раз, ви повинні отримати такий результат:

$git mergetool
No files need merging

8

Ця відповідь полягає в тому, щоб додати альтернативу тим користувачам VIM, як я, який вважає за краще робити все в редакторі.


TL; DR

введіть тут опис зображення


Tpope придумав цей чудовий плагін для VIM під назвою втікач . Після встановлення ви можете запустити :Gstatusдля перевірки файлів, які конфліктують та:Gdiff відкрити Git трьома способами злиття.

Потрапивши в 3-х напрямкове злиття, втікач дозволить вам змінити будь-яку з гілок, які ви об’єднуєте, таким чином:

  • :diffget //2, отримати зміни з оригінальної ( HEAD ) гілки:
  • :diffget //3, отримайте зміни від галузі, що об'єднується:

Після того як ви закінчите об'єднання файлу, введіть :Gwriteоб'єднаний буфер. Vimcasts випустив чудове відео, де детально пояснюються ці кроки.


6

Гітленсе для коду VS

Ви можете спробувати Gitlense для VS Code. Основними функціями є:

3. Легко вирішуйте конфлікти.

Мені вже подобається ця функція:

введіть тут опис зображення

2. Поточна винна лінія.

введіть тут опис зображення

3. Вину з жолобів

введіть тут опис зображення

4. Винна панель стану

введіть тут опис зображення

І є багато функцій, ви можете перевірити їх тут .


5

git fetch
git checkout вашого філіалу
git rebase master

На цьому кроці ви спробуєте виправити конфлікт, використовуючи перевагу IDE

Ви можете перейти за цим посиланням, щоб перевірити, як вирішити конфлікт у файлі
https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/

git add
git rebase - продовжити
git commit - змінити
походження git push HEAD: refs / drafts / master (push як чернетки)

Тепер все добре, і ви знайдете свою прихильність в Геррі

Сподіваюся, що це допоможе кожному, хто стосується цього питання.


3

Спробуйте скористатися кодом Visual Studio для редагування, якщо ви ще цього не зробили. Що ви робите, це те, що ви спробуєте об'єднатись (і розташуватися в конфліктах злиття) .VS код автоматично виявить конфлікти злиття.

Це може допомогти вам дуже добре, показавши, які зміни були внесені до оригіналу, і якщо ви приймаєте incomingабо

current change(мається на увазі оригінал перед об'єднанням) '?.

Це допомогло для мене, і це може працювати і для вас!

PS: Він буде працювати лише в тому випадку, якщо ви налаштували git зі своїм кодом та кодом Visual Studio.


2

Більш безпечним способом вирішення конфліктів є використання git-mediate (поширені рішення, запропоновані тут, є досить схильними до помилок).

Перегляньте цю публікацію для швидкого ознайомлення з тим, як її використовувати.


2

Для тих, хто використовує Visual Studio (2015 в моєму випадку)

  1. Закрийте проект у VS. Особливо у великих проектах VS, як правило, відлякує при об'єднанні за допомогою інтерфейсу.

  2. Зробіть об'єднання в командному рядку.

    git checkout target_branch

    git merge source_branch

  3. Потім відкрийте проект у VS та перейдіть до Team Explorer -> Відділення. Тепер з'явилося повідомлення, яке говорить про те, що об’єднання очікує на розгляд, а файли, що суперечать один одному, перераховуються під цим повідомленням.

  4. Клацніть файл, що суперечить, і у вас буде можливість об'єднати, порівняти, взяти джерело, взяти за мету. Інструмент злиття в VS дуже простий у використанні.


Я використовую VS Code 2017 для дуже великого проекту і не потребую закривати проект. Він справляється з цим досить добре :)
protoEvangelion

2

Якщо ви використовуєте intelliJ як IDE, спробуйте об'єднати батьківство з вашою філією

git checkout <localbranch>
git merge origin/<remotebranch>

Він покаже всі подібні конфлікти

A_MBPro: перевірити початок злиття anu $ git / Автоматичне об'єднання src / test / java / com /.../ TestClass.java CONFLICT (content): конфлікт злиття в src / test / java / com /.../ TestClass.java

Тепер зауважте, що файл TestClass.java відображається червоним кольором в intelliJ Також буде показаний статус git

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified:   src/test/java/com/.../TestClass.java

Відкрийте файл в IntelliJ, він буде мати розділи з

  <<<<<<< HEAD
    public void testMethod() {
    }
    =======
    public void testMethod() { ...
    }
    >>>>>>> origin/<remotebranch>

де HEAD - це зміна вашої локальної гілки та походження / - це зміни від віддаленої гілки. Тут зберігайте потрібні вам речі та видаліть потрібні вам речі. Після цього слід виконати звичайні дії. Це є

   git add TestClass.java
   git commit -m "commit message"
   git push

2

Я використовую візуальний код Microsoft для вирішення конфліктів. Його дуже просто у використанні. Я тримаю свій проект відкритим у робочій області. Він виявляє та висвітлює конфлікти, а також надає GUI можливість вибрати будь-яку зміну, яку я хочу зберегти від HEAD або вхідних. введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.