Перейти к содержимому

Git mergetool как работать

  • автор:

A3.4 Приложение C: Команды Git — Ветвление и слияния

За создание новых веток и слияние их воедино отвечает несколько Git команд.

git branch

Команда git branch — это своего рода «менеджер веток». Она умеет перечислять ваши ветки, создавать новые, удалять и переименовывать их.

Большая часть главы Ветвление в Git посвящена этой команде, она используется повсеместно в этой главе. Впервые команда branch была представлена в разделе Создание новой ветки главы 3, а большинство таких её возможностей как перечисление и удаление веток были разобраны в разделе Управление ветками главы 3.

В разделе Отслеживание веток главы 3 мы показали как использовать сочетание git branch -u для отслеживания веток.

Наконец, мы разобрались что происходит за кулисами этой команды в разделе Ссылки в Git главы 10.

git checkout

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

Мы познакомились с этой командой в разделе Переключение веток главы 3 вместе с git branch .

В разделе Отслеживание веток главы 3 мы узнали как использовать флаг —track для отслеживания веток.

В разделе Использование команды checkout в конфликтах главы 7 мы использовали эту команду с опцией —conflict=diff3 для разрешения конфликтов заново, в случае если предыдущее решение не подходило по некоторым причинам.

Мы рассмотрели детали взаимосвязи этой команды и git reset в разделе Раскрытие тайн reset главы 7.

Мы исследовали внутренние механизмы этой команды в разделе HEAD главы 10.

git merge

Команда git merge используется для слияния одной или нескольких веток в текущую. Затем она устанавливает указатель текущей ветки на результирующий коммит.

Мы познакомили вас с этой командой в разделе Основы ветвления главы 3. И хотя git merge встречается в этой книге повсеместно, практически все использования имеют вид git merge с указанием единственной ветки для слияния.

Мы узнали как делать «сплющенные» слияния (когда Git делает слияние в виде нового коммита, без сохранения всей истории работы) в конце раздела Форк публичного проекта.

В разделе Продвинутое слияние главы 7 мы глубже разобрались с процессом слияния и этой командой, включая флаги -Xignore-all-whitespace и —abort , используемый для отмены слияния в случае возникновения проблем.

Мы научились проверять криптографические подписи перед слияниями если ваш проект использует GPG в разделе Подпись коммитов главы 7.

Ну и наконец в разделе Слияние поддеревьев главы 7 мы познакомились со слиянием поддеревьев.

git mergetool

Команда git mergetool просто вызывает внешнюю программу слияний, в случае если у вас возникли проблемы слияния.

Мы вкратце упомянули о ней в разделе Основные конфликты слияния главы 3 и рассказали как настроить свою программу слияния в разделе Внешние программы слияния и сравнения главы 8.

git log

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

Практически во всех главах книги эта команда используется для демонстрации истории проекта.

Мы познакомились c git log и некоторыми её деталями в разделе Просмотр истории коммитов главы 2. Там мы видели использование опций -p и —stat для получения представления об изменениях в каждом коммите, а также —pretty and —oneline для настройки формата вывода этой команды — более полным и подробным или кратким.

В разделе Создание новой ветки главы 3 мы использовали опцию —decorate чтобы отобразить указатели веток на истории коммитов, а также —graph чтобы просматривать историю в виде дерева.

В разделах Небольшая команда главы 5 и Диапазоны коммитов главы 7 мы познакомили вас с синтаксисом branchA..branchB , позволяющем команде git log показывать только коммиты, присутствующие в одной ветке, но отсутствующие в другой. Мы довольно подробно рассматриваем этот вопрос в разделе Диапазоны коммитов.

В разделах История при слиянии и Три точки главы 7 мы рассмотрели синтаксис branchA…​branchB и опцию —left-right позволяющие увидеть, что находится в одной или в другой ветке, но не в них обеих сразу. Также в разделе История при слиянии мы рассмотрели опцию —merge , которая может быть полезной при разрешении конфликтов, а также —cc для просмотра конфликтов слияния в истории проекта.

В разделе RefLog-сокращения главы 7 мы использовали опцию -g для вывода git reflog , используя git log .

В разделе Поиск главы 7 мы рассмотрели использование опций -S и -L для поиска событий в истории проекта, например, истории развития какой-либо фичи.

В разделе Подпись коммитов главы 7 мы показали, как использовать опцию —show-signature для отображения строки валидации подписи для каждого коммита в git log .

git stash

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

Эта команда практически целиком раскрыта в разделе Припрятывание и очистка главы 7.

git tag

Команда git tag используется для задания постоянной метки на какой-либо момент в истории проекта. Обычно она используется для релизов.

Мы познакомились и разобрались с ней в разделе Работа с тегами главы 2 и использовали на практике в разделе Помечайте свои релизы главы 5.

Мы научились создавать подписанные с помощью GPG метки, используя флаг -s , и проверять их, используя флаг -v , в разделе Подпись главы 7.

Git для начинающих. Урок 9.
Слияния или мерджи веток

Краткое содержание урока, основные инструкции для командной строки, полезные ссылки и советы.

Ветка master — еще раз

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

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

Подробнее о разных соглашениях мы поговорим во второй части курса.

Что такое мердж или слияние веток

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

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

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

Мастер сливается в ветку или мастер подтягивается в ветку, когда мы продолжаем работать над веткой, но хотим периодически подтягивать новые коммиты с сервера — новый код, который написали наши коллеги. Если работа над веткой идет довольно долго, есть смысл подтягивать изменения из мастера хоть каждый день.

Следует четко различать мердж своей ветки в мастер и мердж мастера в свою ветку.

Мердж ветки в мастер

Выполняется после завершения работы над своей веткой при помощи команды git merge. Чтобы вмерджить ветку в мастер, нужно сначала перейти в мастер, а затем выполнить git merge branch_name.

 $ git checkout master $ git merge news 

При этом возможны разные ситуации

Поговорим о них подробнее

Пока мы работали над веткой, в мастере не появилось новых коммитов

То есть мы создали ветку, поработали над ней, собрались заливать ее в мастер, а за это время новых коммитов там не появилось. Тогда слияние проходит так

 $ git merge news Updating f32b91e..33ea897 Fast-forward index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) $ git push origin master $ git branch -d news 

Git понимает, что это новый код, который можно просто положить поверх старого. Это простая ситуация и git не задает никаких вопросов.

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

Теперь другая ситуация.

Пока мы работали над веткой, в мастере появились коммиты от коллег

Сначала переключаемся на мастер

 $ git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'. 

Почему «is up-to-date»? Потому что мы еще не сделали git pull. Делаем

 $ git pull --rebase origin master 

Мерджим свою ветку в мастер

 $ git merge news-styles 

И не забываем запушить изменения

 $ git push origin master 

Что если сначала не подтягивать мастер, а смерджить свою ветку

Принципиально ничего не изменится, но лучше сначала сделать актуальной ветку мастер, а уже потом заливать свои изменения. А еще лучше держать актуальной свою ветку относительно мастера. Это значит, что стоит почаще подтягивать мастер в свою ветку. Таким образом мы в своей ветке будем работать с актуальным кодом и у нас меньше риска что-нибудь поломать. А если поломаем, то лучше чинить это в своей ветке, а не в мастере.

Как вмерджить мастер в свою ветку

Сначала идем в мастер, подтягиваем изменения с сервера, то есть делаем git pull. Затем переключаемся в свою ветку и делаем git merge master

 $ git checkout master $ git pull --rebase origin master $ git checkout news-redesign $ git merge master 

Затем проверяем, что ничего не поломалось и продолжаем работать.

Мердж коммиты

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

Посмотрим список коммитов и найдем мердж-коммит с хэшем 051f754

 $ git log --oneline 051f754 Merge branch 'news' . 

Посмотрим его содержимое

 $ git show 051f754 commit 051f75475cb1dca3cd08c1c7367a3308671ccf7b Merge: 0a3a6a3 2346be5 Author: Alexandr Shestakov Date: Sat Feb 8 14:10:39 2020 +0300 Merge branch 'news' 

То есть информация только о том, что в мастер была залита ветка news. Сами изменения в файлах, которые мы делали в ветке news, лежат в других коммитах.

Споры о том, есть польза от таких коммитов, ведутся годами и не закончатся, видимо, никогда.

Плюс в том, что у нас есть возможность выбора — git позволяет обходиться без таких коммитов вообще. Тогда история коммитов будет содержать только изменения в коде, а не операции с ветками. Это достигается механизмом ребейза, но это тема, которая выходит за рамки первой курса. Ребейз, его плюсы и минусы, мы подробно рассмотрим во второй части курса.

Также можете почитать мою старую статью — Отличия мерджа от ребейза.
В ней нет видеоурока, но наглядно объясняется на скриншотах.

Мерджи всегда проходят так гладко?

К сожалению, нет

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

Подробнее о конфликтах и их разрешении мы поговорим в следующем уроке.

Git merge без конфликта

Что могу посоветовать

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

Спасибо за внимание и до встречи!

Все уроки курса

  • Вводный урок
  • 1. Установка и базовая настройка git
  • 2. Создание и клонирование репозитория git
  • 3. Делаем первые изменения, git status и git diff
  • 4. Коммиты и история коммитов, git commit, git log и git show
  • 5. Подробнее об истории коммитов. Путешествие по истории
  • 6. Работа с сервером, git push и git pull
  • 7. Ветки — главная фишка git, git branch и git checkout
  • 8. Работа с ветками на сервере, git fetch
  • 9. Слияния или мерджи веток, git merge
  • 10. Конфликты и их разрешение
  • Платная часть курса. Презентация
  • * 11. Работа с gitignore и git exclude
  • * 12. Буфер обмена git, git stash
  • * 13. Копирование коммитов, git cherry-pick
  • * 14. Отмена и редактирование последнего коммита
  • * 15. Отмена произвольного коммита, git revert
  • 16. Склеивание коммитов, git rebase —interactive и git reflog
  • * 17. Зачем склеивать коммиты. Плюсы и минусы сквоша
  • * 18. Работа с git rebase. Отличия от merge
  • * 19. Что такое git push —force и как с ним работать
  • * 20. Ищем баги с помощью git, git bisect
  • * 21. Как и зачем работать с тегами git
  • * 22. Процессы: github flow и git flow
  • * 23. Псевдонимы в git
  • 24. Мердж-реквесты
  • * 25. Форки

Команда git-mergetool: опции, ключи и примеры использования

Общие команды – Общие команды, присущие различным операционным системам.

git mergetool

Run merge conflict resolution tools to resolve merge conflicts. More information: https://git-scm.com/docs/git-mergetool.

  • Launch the default merge tool to resolve conflicts:
  • List valid merge tools:

git mergetool —tool-help

  • Launch the merge tool identified by a name:
  • Don’t prompt before each invocation of the merge tool:

git mergetool —no-prompt

  • Explicitly use the GUI merge tool (see the merge.guitool config variable):

git mergetool —gui

  • Explicitly use the regular merge tool (see the merge.tool config variable):

git mergetool —no-gui

Изображение Выучи 10 хороших привычек для работы в UNIX от IBM

Примеры кода, демонстрирующие общие подходы в программировании или же решающие небольшие прикладные задачи. Языки программирования и библиотеки, позволяющие эффективно решать задачи разработки. Объектно-ориентированное программирование, функциональное программирование и прочие подходы и …

Фото Код

Трюки Bash

Полезные заметки по работе с командной строкой: bash и прочие *sh. Однострочники, скрипты, позволяющие решать большие и малые задачи администрирования и настройки Юникс систем. Zsh для современного MacOS, Bash для …

Фото Трюки Bash

Заметки о настройке различных IT-штуковин. Настройка, допиливание, полировка. Конфигурируем приложения и тюнингуем сервера. Полезные параметры и ключи запуска программ. Увеличиваем скорость, уменьшаем отклик, ускоряем работу и улучшаем результаты работы. Объясняем …

Фото Настройки

Терминал/Консоль

Команды и инструкции терминала (консоли) Linux, MacOS, Windows и прочих операционных систем. Трюки и особенности командных оболочек, скрипты для администрирования Unix. Программирование и скриптование Windows и Linux, тонкая настройка Macos. …

Фото Терминал/Консоль

Также может быть вам интересно:

  • Как получить дерево директорий на Bash одним однострочником
  • Python: Функции
  • Python: Встроенные типы данных (list, set, dict, etc)
  • Python: типы данных, переменные, логическое ветвление и циклы
  • Как сделать свою middleware в Django (с примерами)

Свежее на «Цифре»
MessageId или как дебажить систему с минимумом проблем
Программы, 09.09.2023
Проверочный список для выпуска промышленных приложений с иллюстрациями
Работа и управление, 30.07.2023
В Google Pixel и Windows Snipping Tool есть возможность восстановления обрезанных изображений
Новости, 23.03.2023
Два подарка «под ёлочку» от Heroes of Might and Magic
Новости, 25.12.2022
Вышел Pulsar – редактор кода на основе Atom
Новости, 25.12.2022
Ленивый backup PostgreSQL
Программы, 17.12.2022
Google анонсировала OSV-Scanner: сканер уязвимостей в программных проектах
Новости, 16.12.2022

Фото Gitea запускает коммерческую версию, а недовольные – форк Forĝejo

Gitea запускает коммерческую версию, а недовольные – форк Forĝejo

На днях группа бывших разработчиков Gitea решили создать на базе хостинга кода Gitea свою версию проекта – «Forgejo». Причиной тому …

Фото Пользователи и их создание в Django - своя регистрация на сайте

Пользователи и их создание в Django — своя регистрация на сайте

Если вашим сайтом должны активно пользоваться несколько человек, то полезно их различать, а значит — надо уметь создавать пользователей, либо …

Фото Новый синтаксис старой команды with в Python 3.10

Новый синтаксис старой команды with в Python 3.10

Как же долго моё чувство прекрасного страдало… Но в Python 3.10 появился новый парсер синтаксических конструкций Python!

Фото Добавляем постраничную пагинацию на Django сайт

Добавляем постраничную пагинацию на Django сайт

На сайтах часто встречаются многостраничные объекты: список товаров, список заметок и т.д. Поэтому важно уметь добавить навигацию по страницам на …

Фото Новый оператор match-case в Python

Новый оператор match-case в Python

В новой версии Python (3.10) появится новый оператор. Новый оператор сопоставления по шаблону (match-case).

Фото Нет слов, одни. однострочники

Нет слов, одни. однострочники

На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.

Фото Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

В Django вы можете передавать данные в шаблоны посредством контекстов. Контекст передаётся из контроллера (view в терминах Django), однако, если …

Фото Пример своей консольной команды в Django проекте

Пример своей консольной команды в Django проекте

Если вы работали с Django проектом, то, скорее всего, запускали команды из консоли (manage.py). В Django есть простой способ писать …

Фото Разграничение прав доступа на Django сайте

Разграничение прав доступа на Django сайте

Почти на любом веб-сайте необходимо разделять пользователей на группы и предоставлять им разные возможности. В Django есть довольно серьёзная система …

Безболезненное разрешение 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 merge master Auto-merging roses.txt CONFLICT (content): Merge conflict in roses.txt Automatic merge failed; fix conflicts and then commit the result.

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

$ cat roses.txt >>>>>> master (Listing 1)

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

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

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

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

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

four states

Состояния (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

$ git config merge.conflictstyle diff3

После включения этой опции, попробуйте заново сделать слияние (git reset —hard; git merge master) и проинспектируйте конфликтующий файл ещё раз:

$ cat roses.txt >>>>>> master (Listing 2)

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

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

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

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

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

$ git mergetool

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

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

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

$ ls -1 roses.txt roses.txt.BACKUP.2760.txt roses.txt.BASE.2760.txt roses.txt.LOCAL.2760.txt roses.txt.REMOTE.2760.txt

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

$ meld roses.txt.LOCAL.2760.txt roses.txt.BASE.2760 & $ meld roses.txt.BASE.2760 roses.txt.REMOTE.2760.txt &

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

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

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

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

Надеюсь, вы найдёте этот трёх-окошечный метод разрешения конфликтов, таким же полезным каким нахожу его я. Но согласитесь что запускать новые вызовы meld вручную каждый раз при разрешении конфликтов, не очень то и удобно. Выход, это настроить git таким образом чтобы все три окна открывались автоматически при вызове команды git mergetool. Для этого можно создать выполняемый скрипт, который должен находится в переменной окружения PATH (например $HOME/bin/gitmerge), со следующим содержимым:

#!/bin/sh meld $2 $1 & sleep 0.5 meld $1 $3 & sleep 0.5 meld $2 $4 $3

И добавьте следующее в ваш ~/.gitconfig файл:

[merge] tool = mymeld [mergetool "mymeld"] cmd = $HOME/bin/gitmerge $BASE $LOCAL $REMOTE $MERGED

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

Окно дифа между BASE и LOCAL Окно дифа между BASE и REMOTE Окно трёх-колоночного вида

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

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

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

#!/bin/sh sn=gitmerge tmux new-session -d -s "$sn" -n "diff3" "nvim -d $2 $4 $3" tmux split-window -t "$sn:1" -v "nvim -d $2 $1" tmux split-window -t "$sn:1" -h "nvim -d $1 $3"

Примечание: если вы не используете эту опцию в своем ~/.tmux.conf, то вам надо поменять в двух последних строках «$sn:1» на «$sn:0»

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

[mergetool "gitmerge"] cmd = $HOME/bin/gitmerge \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\" [merge] tool = gitmerge

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

git merge master workflow

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

sessiow switch

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

git merge master

git rebase master

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

git merge master workflow

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

sessiow switch

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

git merge master

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

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

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