This branch has conflicts that must be resolved что делать

This branch has conflicts that must be resolved что делать

Безболезненное разрешение Merge конфликтов в Git

Предлагаю читателям «Хабрахабра» перевод публикации «Painless Merge Conflict Resolution in Git»
из блога blog.wuwon.id.au.

В моей повседневной работе, часто приходится иметь дело со множеством git ветвей (branch). Это могут быть ветви промежуточных релизов, ветви с устаревшим API находящиеся на поддержке для некоторых клиентов, или ветви с экспериментальными свойствами. Лёгкость создания ветвей в модели Git так и соблазняет разработчиков создавать все больше и больше ветвей, и как правило бремя от большого количества ветвей становится очень ощутимым, когда приходится все эти ветви поддерживать и периодически делать слияния (merge) с другими ветвями.

Слияния очень важны для поддержания кода в актуальном состоянии, и как правило ошибка сделанная при слиянии может привести к большей головной боли, нежели ошибка сделанная при простом коммите. К сожалению ошибки слияния далеко не редкость, потому что во-первых слияния имеют несколько родительских ветвей. Даже при анализе истории слияния ветвей, бывает очень трудно понять, какие же изменения были сделаны для разрешения конфликта. Во-вторых, отмена неудачного слияния может превратиться в большую головную боль. В-третьих, большая часть конфликтов слияния происходит при работе с чужим кодом, потому что само понятие ветвей подразумевает множество пользователей, т.е. далеко не всегда слияние производит тот же человек который работал с той или иной веткой. В сухом остатке, сделать ошибку при слиянии очень легко, её трудно исправить и трудно найти. Таким образом время потраченное на изучение и понимание процесса слияния ветвей, окупится с лихвой.

Удивительно, но я обнаружил, что многие доступные инструменты и интерфейсы предназначенные для выполнения слияний, не достаточно хорошо оснащены для эффективного выполнения этого процесса. Часто программист просто надеется что команда git merge сделает за него всю работу. Но когда все-таки происходит конфликт, то обычно стратегия слияния заключается в беглом просмотре кода вокруг строки конфликта, и интуитивном угадывании что именно данный кусок кода предпочтительней другого.

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

Голубые Розы (Roses are Blue)

Давайте предположим что вашей команде поручили писать поэмы в отведённом для этих целей репозитории. (Какой кошмар!) А вам доверили самое главное — делать слияния последних фиксов из ветки master в ветку beta. Итак, вы переключаетесь в ветку beta и выполняете следующую команду:

Ого, это конфликт. Вы решаете просмотреть файл на который ссылается git:

Замечательно! Весь файл, как показывает Listing 1, находится в конфликтном состоянии. Какой же вариант файла является более корректным? Оба варианта выглядят корректно. Верхний вариант написан в хакер-стиле с элементами цветовой кодировки в стиле HTML и с использованием только строчных букв. Нижний вариант выглядит более натурально, с использованием пунктуации и заглавных букв.

Если бы это был ваш проект, вы бы могли просто выбрать один вариант и покончить с этим слиянием. Но проблема в том, что это не ваша поэма, вы никогда не читали эту поэму раньше, не были ответственны за написание или редактирование, и вы отлично понимаете что в случае не верного решения чья-то тяжёлая работа может кануть в небытие. Однако вас всё же назначили ответственным по слиянию этих веток. Что же вам делать?

Назад к Базе (Back to Base)

Хитрость заключается в том, что Listing 1 не даёт вам полную информацию, необходимую для совершения корректного слияния. На самом деле, в процессе слияния участвуют четыре важных части информации (состояния), три из которых просто необходимы для успешного разрешения конфликта. В случае Listing 1, Git предоставил вам только два состояния.

Следующая диаграмма иллюстрирует эти четыре состояния:

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Состояния (B) и © относятся к текущим положениям (head) веток master и beta соответственно, эти два состояния как раз таки и отражены в Listing 1. Состояние (D) это результат слияния, то что вы хотите получить/сгенерировать в конечном итоге (в большинстве случаев Git автоматически генерирует состояние (D)). Состояние (А) на самом верху, представляет собой базу (основу) слияния веток master и beta. База слияния (A) это последний общий предок веток master и beta, и пока предположим что это база слияния уникальна. Как мы увидим позже состояние (A) играет ключевую роль в разрешении конфликтов. На диаграмме я также отразил дельты 1 и 2, которые представляют изменения между состояниями (A)-(B), и (A)-© соответственно. Зная состояния (A), (B) и © дельты 1 и 2 могут быть легко получены (вычислены). Обратите внимание, что дельты 1 и 2 могут состоять из более чем одного коммита. Но для наших целей будем считать что все дельты монолитны.

Чтобы понять, как получить состояние (D), вы должны понимать что же операция слияния пытается сделать. Состояние (D) должно представлять собой сочетание изменений, внесённых в ветку master и beta соответственно. Т.е. другими словами сочетание дельт 1 и 2. Идея проста на поверхности и большую часть времени не требует вмешательства со стороны человека, за исключением особых случаев когда дельты затрагивают наслаиваемые (пересекающиеся) части файла. В такой ситуации вам требуется помочь машине сгенерировать результат (D), путём сравнения дельт 1 и 2.

Определение Отличий (Identifying the Differences)

Для того чтобы найти изменения внесённые в каждую ветку, необходимо знать как выглядит база слияния, состояние (A). Самый простой механизм получения информации о базе слияния, это установка опции merge.conflictstyle в значение diff3

Теперь мы видим третий фрагмент посередине, который и является базой слияния или состояние (A). Изменения видны как на ладони: в ветке beta (HEAD) человеческие названия цветов были заменены на HTML коды, а в ветку master добавили капитализацию и пунктуацию. Основываясь на этих знаниях, мы теперь знаем что результат должен включать в себя капитализацию, пунктуацию и HTML коды цветов.

В принципе на этом можно было бы и закончить, потому что результат достигнут. Но есть решение и получше.

Графическое Слияние (GUI Merging)

Хотя и простое текстовое представление конфликта слияния делает свою работу в простых случаях, на практике конфликты могут быть более радикальными и сложными. В таких случаях могут помочь графические инструменты. Мой выбор пал на простой инструмент написанный на Python под названием meld, но может подойти любой другой графический инструмент, способный представить слияние в трёх-колоночном виде.

Для использования графического инструмента (он должен быть установлен), после того как git пожаловался что есть конфликт, введите следующую команду:

Последует вопрос какой программой для слияния вы хотели бы воспользоваться, просто введите meld и нажмите Enter. Вот как окно программы может выглядеть (подразумевается опция merge.conflictstyle не была включена):

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Несмотря на то что информация представлена бок о бок, она не отображает нужные фрагменты которые были в Listing 2. Мы не видим здесь фрагмента базы слияния (состояния (A)), что мы видим это файл roses.txt.LOCAL.2760.txt в левой колонке и файл roses.txt.REMOTE.2760.txt в правой колонке и файл посередине это неудачное слияние. Т.е. по сути нам представили состояния (B), © и несостоявшееся состояние (D), но состояние (A) отсутствует.

Правда отсутствует? Давайте проверим, в старом добром терминале:

Видим интересующий нас файл: roses.txt.BASE.2760.txt. Это и есть файл базы слияния. Теперь нам осталось всего лишь найти изменения внесённые в ветки master и beta, по отношению к базе. Мы можем сделать это двумя отдельными вызовами meld:

(Кто-то может подметить что было бы более разумно, поменять порядок аргументов в первом вызове, для того чтобы файл базы находился в левой колонке в обоих случаях, но именно такой порядок сохраняет подобие трёх-колоночного вида, при котором база остаётся по середине.) Результат выполнения — два окна как показано ниже:

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делатьThis branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

При чтении первого окна справа налево и второго окна слева направо, становится ясно как день, какие изменения произошли в каждой ветке. Так как meld любезно подсветил все изменения, теперь практически не возможно пропустить даже мелко заметные правки (Кто-нибудь заметил добавление предлога «of» при просмотре текстового представления разрешения конфликта Listing 1 или даже Listing 2?)

Вооружившись этими знаниями, мы теперь можем вернуться к трёх-колоночному представлению и сделать изменения. Моя стратегия ручного слияния это взять весь текст из ветки с более весомыми изменениями (в данном случае master/REMOTE т.е. beta), и поверх него производить пошаговые правки, т.е. вносить изменения сделанные в другой ветке (master). Вот что получилось:

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

А теперь всё вместе (All Together Now)

И добавьте следующее в ваш

Теперь, когда вы в следующий раз будете запускать команду git mergetool для разрешения конфликта, откроются все три окна:

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

Бонус от переводчика

Для тех кто пользуется tmux и n?vim, предлагаю следующий скрипт gitmerge:

Примечание: если вы не используете эту опцию в своем

/.tmux.conf, то вам надо поменять в двух последних строках «$sn:1» на «$sn:0»

Соответственно добавьте следующее в ваш

Воркфлоу разрешения конфликта будет выглядеть так:

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Пока игнорируем вопрос (Was the merge successful [y/n]?) и переключаемся в сессию под названием gitmerge (сочетание TMUXPREFIX + s):

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Видим наше трёх-оконное представление на одном экране. Цифрами обозначены сплиты (panes) tmux’a, буквами соответствующие состояния. Делаем правки для разрешения конфликта, т.е. редактируем состояние (D) и сохраняем. После этого возвращаемся обратно в исходную сессию tmux’a и подтверждаем что слияние произошло успешно.

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

git rebase master

Лично я предпочитаю и считаю более правильным делать сначала rebase master в ветке beta, и только после этого переключаться в master и делать git merge beta. В принципе воркфлоу не сильно отличается, за исключением трёх-оконного вида.

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Переключаемся в сессию gitmerge

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Обратите внимание, что состояния (B) и © поменялись местами:

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Рекомендую всем поиграться с примером репозитария хотя бы один раз, сделать разрешение конфликта по вышеописанной схеме. Лично я больше не гадаю а что же выбрать «Accept theirs» или «Accept yours».

How does one solve «This branch has conflicts that must be resolved» in git while merging pull request? #648

Comments

jns111 commented Sep 30, 2015

No description provided.

The text was updated successfully, but these errors were encountered:

jaw6 commented Sep 30, 2015

You’ll need to update your branch with new commits from master, resolve those conflicts and push the updated/resolved branch to GitHub. Something like this:

shankar26 commented Apr 18, 2016

leonardojulius commented Jul 15, 2016

@jaw6 thanks it helps me 👍

kirankakkeratd commented Oct 9, 2016

jitendravyas commented Oct 11, 2016

It helped me. thanks

23ranjan commented Oct 20, 2016

jitendravyas commented Nov 19, 2016

i get this error

otisidev commented Nov 27, 2016

every helpful, thank you!

nj1306 commented Jun 21, 2017 •

If someone getting below error like me

fatal: cannot do a partial commit during a merge.

Georodent commented Dec 1, 2017

tdk408 commented Jan 30, 2018

On «git checkout «, should it be a new branch created for fixing the conflicts, or the original branch that reported the conflicts?

ningcui-refundlabs commented Nov 26, 2018

perfect solution. Thanks.

sunset12321215 commented Jan 9, 2019

ghost commented Jan 16, 2019

veasnama commented Jan 30, 2019

thank sir that really works for me. i never thought i would be fine. this is my day.

Ahkshaey commented Mar 13, 2020

@thanks. Worked like pure magic. Bookmarking it as a great resource when trying to resolve conflicts on git for future reference.

hyungtaecf commented Apr 8, 2020

I got this after trying to merge with master:
Automatic merge failed; fix conflicts and then commit the result.

lfc-256 commented May 26, 2020

repl-mohit-kumar commented Jul 13, 2021

the conflict occurred because after ur change, someone else updated that file
so Github could not determine which lines to keep and which to remove with ur change
when we merged master, we pointed the local HEAD to the master code and with that Github was able to fix the merge conflict automatically.

OmarAlareeki commented Sep 10, 2021

Thank you, this is very helpful

Carlo8699 commented Dec 6, 2021

kazyon commented Jan 15, 2022

Wenjie76 commented Jul 27, 2022

Thank you, quite helpful

Footer

© 2022 GitHub, Inc.

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

Конфликты слияния в Git

Системы контроля версий предназначены для управления дополнениями, вносимыми в проект множеством распределенных авторов (обычно разработчиков). Иногда один и тот же контент могут редактировать сразу несколько разработчиков. Если разработчик A попытается изменить код, который редактирует разработчик B, может произойти конфликт. Для предотвращения конфликтов разработчики работают в отдельных изолированных ветках. Основная задача команды git merge заключается в слиянии отдельных веток и разрешении любых конфликтующих правок.

Общие сведения о конфликтах слияния

Слияние и конфликты являются неотъемлемой частью работы с Git. В других инструментах управления версиями, например SVN, работа с конфликтами может быть дорогой и времязатратной. Git позволяет выполнять слияния очень просто. В большинстве случаев Git самостоятельно решает, как автоматически интегрировать новые изменения.

Обычно конфликты возникают, когда два человека изменяют одни и те же строки в файле или один разработчик удаляет файл, который в это время изменяет другой разработчик. В таких случаях Git не может автоматически определить, какое изменение является правильным. Конфликты затрагивают только того разработчика, который выполняет слияние, остальная часть команды о конфликте не знает. Git помечает файл как конфликтующий и останавливает процесс слияния. В этом случае ответственность за разрешение конфликта несут разработчики.

Типы конфликтов слияния

Конфликт во время слияния может произойти в двух отдельных точках — при запуске и во время процесса слияния. Далее рассмотрим, как разрешать каждый из этих конфликтных сценариев.

Git прерывает работу в самом начале слияния

Git прерывает работу во время слияния

Сбой В ПРОЦЕССЕ слияния говорит о наличии конфликта между текущей локальной веткой и веткой, с которой выполняется слияние. Это свидетельствует о конфликте с кодом другого разработчика. Git сделает все возможное, чтобы объединить файлы, но оставит конфликтующие участки, чтобы вы разрешили их вручную. При сбое во время выполнения слияния выдается следующее сообщение об ошибке:

Создание конфликта слияния

Чтобы лучше разобраться в конфликтах слияния, в следующем разделе мы смоделируем конфликт для дальнейшего изучения и разрешения. Для запуска моделируемого примера будет использоваться интерфейс Git c Unix-подобной командной строкой.

С помощью приведенной в этом примере последовательности команд выполняются следующие действия.

Представленная выше последовательность команд выполняет следующие действия.

БАХ! 💥 Возник конфликт. Хорошо, что система Git сообщила нам об этом.

Выявление конфликтов слияния

Вывод команды git status говорит о том, что из-за конфликта не удалось слить пути. Теперь файл merge.text отображается как измененный. Давайте изучим этот файл и посмотрим, что изменилось.

Разрешение конфликтов слияния с помощью командной строки

Самый простой способ разрешить конфликт — отредактировать конфликтующий файл. Откройте файл merge.txt в привычном редакторе. В нашем примере просто удалим все разделители конфликта. Измененное содержимое файла merge.txt будет выглядеть следующим образом:

Git обнаружит, что конфликт разрешен, и создаст новый коммит слияния для завершения процедуры слияния.

Команды Git, с помощью которых можно разрешить конфликты слияния

Общие инструменты

Команда status часто используется во время работы с Git и помогает идентифицировать конфликтующие во время слияния файлы.

Команда diff помогает найти различия между состояниями репозитория/файлов. Она полезна для выявления и предупреждения конфликтов слияния.

Инструменты для случаев, когда Git прерывает работу в самом начале слияния

Команда checkout может использоваться для отмены изменений в файлах или для изменения веток.

Команда reset может использоваться для отмены изменений в рабочем каталоге или в разделе проиндексированных файлов.

Инструменты для случаев, когда конфликты Git возникают во время слияния

Команду git reset можно использовать для разрешения конфликтов, возникающих во время выполнения слияния, чтобы восстановить заведомо удовлетворительное состояние конфликтующих файлов.

Резюме

Конфликты слияния могут пугать. К счастью, Git предлагает мощные инструменты их поиска и разрешения. Большую часть слияний система Git способна обрабатывать самостоятельно с помощью функций автоматического слияния. Конфликт возникает, когда в двух ветках была изменена одна и та же строка в файле или когда некий файл удален в одной ветке и отредактирован в другой. Как правило, конфликты возникают при работе в команде.

Готовы попробовать ветвление?

Ознакомьтесь с этим интерактивным обучающим руководством.

About merge conflicts

In this article

Merge conflicts happen when you merge branches that have competing commits, and Git needs your help to decide which changes to incorporate in the final merge.

Git can often resolve differences between branches and merge them automatically. Usually, the changes are on different lines, or even in different files, which makes the merge simple for computers to understand. However, sometimes there are competing changes that Git can’t resolve without your help. Often, merge conflicts happen when people make different changes to the same line of the same file, or when one person edits a file and another person deletes the same file.

You must resolve all merge conflicts before you can merge a pull request on GitHub. If you have a merge conflict between the compare branch and base branch in your pull request, you can view a list of the files with conflicting changes above the Merge pull request button. The Merge pull request button is deactivated until you’ve resolved all conflicts between the compare branch and base branch.

This branch has conflicts that must be resolved что делать. Смотреть фото This branch has conflicts that must be resolved что делать. Смотреть картинку This branch has conflicts that must be resolved что делать. Картинка про This branch has conflicts that must be resolved что делать. Фото This branch has conflicts that must be resolved что делать

Resolving merge conflicts

To resolve a merge conflict, you must manually edit the conflicted file to select the changes that you want to keep in the final merge. There are a couple of different ways to resolve a merge conflict:

If you have a merge conflict on the command line, you cannot push your local changes to GitHub until you resolve the merge conflict locally on your computer. If you try merging branches on the command line that have a merge conflict, you’ll get an error message. For more information, see «Resolving a merge conflict using the command line.»

Resolving a merge conflict using the command line

In this article

You can resolve merge conflicts using the command line and a text editor.

Merge conflicts occur when competing changes are made to the same line of a file, or when one person edits a file and another person deletes the same file. For more information, see «About merge conflicts.»

Tip: You can use the conflict editor on GitHub to resolve competing line change merge conflicts between branches that are part of a pull request. For more information, see «Resolving a merge conflict on GitHub.»

Competing line change merge conflicts

To resolve a merge conflict caused by competing line changes, you must choose which changes to incorporate from the different branches in a new commit.

For example, if you and another person both edited the file styleguide.md on the same lines in different branches of the same Git repository, you’ll get a merge conflict error when you try to merge these branches. You must resolve this merge conflict with a new commit before you can merge these branches.

Navigate into the local Git repository that has the merge conflict.

Generate a list of the files affected by the merge conflict. In this example, the file styleguide.md has a merge conflict.

Open your favorite text editor, such as Atom, and navigate to the file that has merge conflicts.

Add or stage your changes.

Commit your changes with a comment.

You can now merge the branches on the command line or push your changes to your remote repository on GitHub and merge your changes in a pull request.

Removed file merge conflicts

To resolve a merge conflict caused by competing changes to a file, where a person deletes a file in one branch and another person edits the same file, you must choose whether to delete or keep the removed file in a new commit.

For example, if you edited a file, such as README.md, and another person removed the same file in another branch in the same Git repository, you’ll get a merge conflict error when you try to merge these branches. You must resolve this merge conflict with a new commit before you can merge these branches.

Navigate into the local Git repository that has the merge conflict.

Generate a list of the files affected by the merge conflict. In this example, the file README.md has a merge conflict.

Open your favorite text editor, such as Atom, and navigate to the file that has merge conflicts.

Decide if you want keep the removed file. You may want to view the latest changes made to the removed file in your text editor.

To add the removed file back to your repository:

To remove this file from your repository:

Commit your changes with a comment.

You can now merge the branches on the command line or push your changes to your remote repository on GitHub and merge your changes in a pull request.

Источники информации:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *