Git mergetool как работать
Перейти к содержимому

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

  • автор:

Git merge

Слияние используется в Git, чтобы собрать воедино разветвленную историю. Команда git merge выполняет слияние отдельных направлений разработки, созданных с помощью команды git branch , в единую ветку.

Обратите внимание: все приведенные ниже команды выполняют слияние в текущую ветку, в то время как целевая ветка остается без изменений. Поэтому команда git merge часто используется в сочетании с командами git checkout (для выбора текущей ветки) и git branch -d (для удаления устаревшей целевой ветки).

Порядок действий

Команда git merge объединяет несколько последовательностей коммитов в общую историю. Чаще всего команду git merge используют для объединения двух веток. Этот вариант слияния рассматривается в следующих примерах. В таких случаях команда git merge принимает два указателя на коммиты (обычно последние в ветке) и находит общий для них родительский коммит. Затем Git создает коммит слияния, в котором объединяются изменения из обеих последовательностей, выбранных к слиянию.

Представим, что у нас есть новая функциональная ветка, которая отходит от главной ветки main . И мы хотим объединить эту функциональную ветку с main .

Слияние ветки feature с веткой main

Окно консоли

Связанные материалы
Расширенный журнал Git
СМ. РЕШЕНИЕ
Изучите Git с помощью Bitbucket Cloud

При вызове этой команды произойдет слияние указанной функциональной ветки с текущей — в данном случае с веткой main . Git автоматически определяет алгоритм слияния (подробнее см. ниже).

Новый узел коммита слияния

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

Подготовка к слиянию

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

Проверка выбора принимающей ветки

Выполните команду git status . Это позволит убедиться, что HEAD указывает на ветку, принимающую результаты слияния. При необходимости выполните команду git checkout , чтобы переключиться на принимающую ветку. Для примера выполним команду git checkout main .

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

Убедитесь, что в принимающей ветке и ветке для слияния содержатся последние изменения из удаленного репозитория. Выполните команду git fetch , чтобы получить из него последние коммиты. Затем убедитесь, что в ветке main также содержатся последние изменения. Для этого выполните команду git pull .

Выполнение слияния

После указанных выше действий по подготовке можете приступать к слиянию. Для этого выполните команду git merge , где — название ветки, которая будет объединена с принимающей.

Ускоренное слияние

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

Однако выполнить ускоренное слияние не получится, если ветки после разделения развивались независимо друг от друга. Если до целевой ветки нет прямого пути, Git будет вынужден объединить их методом трехстороннего слияния. Такое слияние выполняется с помощью специального коммита, который служит для объединения двух историй. Метод называется трехсторонним, поскольку Git использует три коммита для создания коммита слияния (последние коммиты двух веток и общий родительский элемент).

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

В первом примере демонстрируется ускоренное слияние. С помощью кода создается новая ветка, после чего в нее добавляется два коммита. Затем она включается в основную ветку посредством ускоренного слияния.

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add
git commit -m "Start a feature"
# Edit some files
git add
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

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

Обратите внимание, что теперь Git сможет без проблем выполнить команду git branch -d , поскольку ветка new-feature теперь доступна из главной ветки.

Если при ускоренном слиянии вам понадобится коммит слияния для учета изменений, вы можете выполнить команду git merge с параметром —no-ff .

git merge --no-ff

Эта команда выполнит объединение указанной ветки с текущей с обязательным созданием коммита слияния (даже если слияние будет ускоренным). Это полезно для учета всех слияний в репозитории.

Трехстороннее слияние

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

Start a new feature
git checkout -b new-feature main
# Edit some files
git add
git commit -m "Start a feature"
# Edit some files
git add
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

Обратите внимание, что Git не может выполнить ускоренное слияние, потому что невозможно перенести указатель main на ветку new-feature без использования предыдущих коммитов.

В большинстве случаев ветка new-feature отводится под более объемные функции с продолжительным временем разработки, за которое в ветке main появляются новые коммиты. Если бы реальный размер вашей функциональной ветки был так же мал, как в приведенном выше примере, было бы проще перебазировать ее на ветку main и выполнить ускоренное слияние. В этом случае не потребовалось бы засорять историю проектов лишними коммитами слияния.

Разрешение конфликтов

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

Преимущество слияния в Git заключается в том, что разрешение конфликтов при слиянии проходит по привычной схеме «редактирование — индексирование — коммит». При обнаружении конфликта выполните команду git status , чтобы увидеть, какие файлы необходимо исправить. Так, если в обеих ветках изменена одна и та же часть файла hello.py , вы увидите следующее:

On branch main
Unmerged paths:
(use "git add/rm . " as appropriate to mark resolution)
both modified: hello.py

Представление конфликтов

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

here is some content not affected by the conflict
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

Обычно содержимое перед отметкой ======= относится к принимающей ветке, а все, что указано после нее, — к ветке, для которой выполняется слияние.

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

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

Резюме

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

1. При слиянии в Git цепочки коммитов объединяются в общую историю.

2. В Git есть два основных способа объединения изменений: ускоренное и трехстороннее слияние.

3. Если в обеих цепочках коммитов нет конфликтующих изменений, система Git объединит их автоматически.

В документе также упоминаются другие команды Git: git branch, git pull и git fetch. Подробные сведения о них см. на соответствующих страницах.

Безболезненное разрешение 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».

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 — запуск инструментов разрешения конфликтов слияния для разрешения конфликтов слияния.

Synopsis

git mergetool [--tool=] [-y | --[no-]prompt] […​]

Description

Используйте git mergetool для запуска одной из нескольких утилит слияния для разрешения конфликтов слияния. Обычно он запускается после git merge .

Если заданы один или несколько параметров , будет запущена программа инструмента слияния для разрешения различий в каждом файле (пропуская те, которые не указаны в conflicts).. При указании каталога будут включены все неразрешенные файлы по этому пути. Если имена не указаны, git mergetool запустит программу инструмента слияния для каждого файла с конфликтами слияния.

Options

Используйте программу разрешения слияния, указанную .. Допустимые значения включают emerge, gvimdiff, kdiff3, meld, vimdiff и tortoisemerge. Запустите git mergetool —tool-help , чтобы получить список допустимых настроек .

Если программа разрешения слияния не указана, git mergetool будет использовать переменную конфигурации merge.tool . Если переменная конфигурации merge.tool не задана, git mergetool выберет подходящее значение по умолчанию.

Вы можете явно указать полный путь к инструменту, задав переменную конфигурации mergetool..path . Например, вы можете настроить абсолютный путь к kdiff3, установив mergetool.kdiff3.path . В противном случае git mergetool предполагает, что инструмент доступен в PATH..

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

Когда git mergetool вызывается с помощью этого инструмента (либо с помощью опции -t или —tool , либо с помощью переменной конфигурации merge.tool ), сконфигурированная командная строка будет вызываться с $BASE , для которой задано имя временного файла, содержащего общую базу для слияния, если она доступна; $LOCAL задается именем временного файла, содержащего содержимое файла текущей ветки; $REMOTE — имя временного файла, содержащего содержимое файла, который нужно объединить, а $MERGED — имя файла, в который инструмент слияния должен записать результат разрешения слияния.

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

Распечатайте список инструментов слияния, которые можно использовать с —tool .

Не запрашивать перед каждым вызовом программы разрешения слияний. Это значение по умолчанию, если программа разрешения слияния явно указана с помощью параметра —tool или переменной конфигурации merge.tool .

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

Когда git-mergetool вызывается с параметром -g или —gui , инструмент слияния по умолчанию будет считываться из настроенной переменной merge.guitool вместо merge.tool . Если merge.guitool не задан, мы вернемся к инструменту, настроенному под merge.tool . Это может быть выбрано автоматически с помощью переменной конфигурации mergetool.guiDefault .

Это переопределяет предыдущую настройку -g или —gui или конфигурацию mergetool.guiDefault и считывает инструмент слияния по умолчанию из настроенной переменной merge.tool .

Обрабатывайте файлы в порядке, указанном в ,, который имеет один шаблон оболочки на строку. Это переопределяет переменную конфигурации diff.orderFile (см. git-config[1] ). Чтобы отменить diff.orderFile , используйте -O/dev/null .

Configuration

Все, что ниже этой строки в этом разделе, выборочно включено из документации git-config[1] . Содержание такое же, как и то, что там есть:

mergetool..path

Переопределить путь для данного инструмента. Это полезно, если вашего инструмента нет в PATH..

Укажите команду для вызова указанного инструмента слияния. Указанная команда оценивается в оболочке со следующими доступными переменными: BASE — имя временного файла, содержащего общую базу объединяемых файлов, если она доступна; LOCAL — имя временного файла, содержащего содержимое файла текущей ветки; REMOTE — имя временного файла, содержащего содержимое файла из объединяемой ветки; MERGED содержит имя файла, в который инструмент слияния должен записать результаты успешного слияния.

Позволяет пользователю переопределить глобальное значение mergetool.hideResolved для определенного инструмента. Полное описание см. в mergetool.hideResolved .

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

Более старые версии meld не поддерживают опцию —output . Git попытается определить, поддерживает ли meld —output , проверив выходные данные meld —help . При настройке mergetool.meld.hasOutput Git пропустит эти проверки и вместо этого будет использовать настроенное значение. Установка mergetool.meld.hasOutput в true указывает Git безоговорочно использовать опцию —output , а false избегает использования —output .

Когда предоставлен —auto-merge , объединение автоматически объединит все неконфликтующие части, выделит конфликтующие части и будет ждать решения пользователя. Установка mergetool.meld.useAutoMerge в true указывает Git безоговорочно использовать опцию —auto-merge с meld . Если задать для этого значения значение auto , git определит, поддерживается ли —auto-merge , и будет использовать —auto-merge , только если он доступен. Значение false полностью исключает использование —auto-merge и является значением по умолчанию.

Серверная часть vimdiff использует эту переменную для управления тем, как выглядят разделенные окна. Применяется, даже если вы используете Neovim ( nvim ) или gVim ( gvim ) в качестве инструмента слияния. Подробнее см. в разделе BACKEND SPECIFIC HINTS.

Во время слияния Git автоматически разрешит как можно больше конфликтов и запишет файл MERGED , содержащий маркеры конфликтов вокруг любых конфликтов, которые он не может разрешить; LOCAL и REMOTE обычно представляют собой версии файла до разрешения конфликта Git. Этот флаг вызывает перезапись LOCAL и REMOTE , так что инструменту слияния представляются только неразрешенные конфликты. Можно настроить для каждого инструмента с помощью переменной конфигурации mergetool..hideResolved . По умолчанию false .

После выполнения слияния исходный файл с маркерами конфликтов можно сохранить как файл с расширением .orig . Если для этой переменной установлено значение false , этот файл не сохраняется. По умолчанию true (i.e. сохранить резервную копию files).

При вызове пользовательского инструмента слияния Git использует набор временных файлов для передачи инструменту. Если инструмент возвращает ошибку и для этой переменной установлено значение true , то эти временные файлы будут сохранены, в противном случае они будут удалены после выхода из инструмента. По умолчанию false .

Git по умолчанию записывает временные версии конфликтующих файлов BASE , LOCAL и REMOTE в рабочее дерево. Git попытается использовать временный каталог для этих файлов при установке true . По умолчанию false .

Запрашивать перед каждым вызовом программы разрешения слияния.

Установите true для использования merge.guitool по умолчанию (эквивалентно указанию —gui argument), или auto для выбора merge.guitool или merge.tool в зависимости от наличия значения переменной среды DISPLAY . По умолчанию используется false , где аргумент —gui должен быть указан явно для merge.guitool для использоваться.

Temporary files

git mergetool создает файлы резервных копий *.orig при разрешении слияний. Их безопасно удалить после слияния файла и завершения его сеанса git mergetool .

Установка для переменной конфигурации mergetool.keepBackup значения false приводит к тому, что git mergetool автоматически удаляет резервную копию после успешного объединения файлов.

Подсказки для бэкенда

vimdiff

Description

При указании —tool=vimdiff в git mergetool Git откроет Vim с 4-мя окнами, распределенными следующим образом:

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

LOCAL , BASE и REMOTE являются буферами только для чтения, показывающими содержимое конфликтующего файла в определенных коммитах («коммит, в который вы вливаетесь», «фиксация общего предка» и «коммит, из которого вы сливаетесь» соответственно)

MERGED — это буфер с возможностью записи, в котором вы должны разрешать конфликты (используя другие буферы только для чтения в качестве reference).). Когда вы закончите, сохраните и выйдите из Vim как обычно ( :wq ) или, если вы хотите прервать, выйдите, используя :cq .

Layout configuration

Вы можете изменить расположение окон, используемое Vim, установив переменную конфигурации mergetool.vimdiff.layout , которая принимает строку, в которой следующие разделители имеют особое значение:

  • + используется для «открытия новой вкладки»
  • , используется для «открытия нового вертикального разделения».
  • / используется для «открытия нового горизонтального разделения».
  • @ используется для указания файла, содержащего окончательную версию после разрешения конфликтов. Если он отсутствует, по умолчанию будет использоваться MERGED .

Приоритет операторов такой (вы можете использовать круглые скобки, чтобы изменить it):

Давайте посмотрим на несколько примеров, чтобы понять, как это работает:

  • layout = «(LOCAL,BASE,REMOTE)/MERGED»

Это точно такой же макет по умолчанию, который мы уже видели. Обратите внимание, что / имеет приоритет над , , поэтому скобки в этом случае не нужны. Следующее определение макета эквивалентно:

layout = "LOCAL,BASE,REMOTE / MERGED"

Если нас по каким-то причинам не интересует буфер BASE .

------------------------------------------ | | | | | | | | | LOCAL | MERGED | REMOTE | | | | | | | | | ------------------------------------------

Будет показан только буфер MERGED . Однако обратите внимание, что все остальные по-прежнему загружаются в vim, и вы можете получить к ним доступ с помощью команды «buffers».

------------------------------------------ | | | | | MERGED | | | | | ------------------------------------------

При отсутствии MERGED в раскладке необходимо «пометить» один из буферов звездочкой. Это станет буфером, который вам нужно отредактировать и сохранить после разрешения конфликтов.

------------------------------------------ | | | | | | | | | | LOCAL | REMOTE | | | | | | | | | | ------------------------------------------

Откроются три вкладки: первая является копией макета по умолчанию, а две другие показывают только различия между ( BASE и LOCAL ) и ( BASE и REMOTE ) соответственно.

------------------------------------------ | TAB #1> | TAB #2 | TAB #3 | | ------------------------------------------ | | | | | LOCAL | BASE | REMOTE | | | | | ------------------------------------------ | | | MERGED | | | ------------------------------------------
------------------------------------------ | TAB #1 | TAB #2> | TAB #3 | | ------------------------------------------ | | | | | | | | | | BASE | LOCAL | | | | | | | | | | ------------------------------------------
------------------------------------------ | TAB #1 | TAB #2 | TAB #3> | | ------------------------------------------ | | | | | | | | | | BASE | REMOTE | | | | | | | | | | ------------------------------------------

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

--------------------------------------------- | TAB #1 | TAB #2 | TAB #3 | TAB #4> | --------------------------------------------- | LOCAL | | |---------------------| | | BASE | MERGED | |---------------------| | | REMOTE | | ---------------------------------------------

Обратите внимание, что в определении третьей вкладки нам нужно использовать круглые скобки, чтобы , имел приоритет над / .

Variants

Вместо —tool=vimdiff вы также можете использовать один из следующих вариантов:

  • —tool=gvimdiff , чтобы открыть gVim вместо Vim.
  • —tool=nvimdiff , чтобы открыть Neovim вместо Vim.

При использовании этих вариантов, чтобы указать пользовательский макет, вам нужно будет установить переменные конфигурации mergetool.gvimdiff.layout и mergetool.nvimdiff.layout вместо mergetool.vimdiff.layout .

Кроме того, для обратной совместимости с предыдущими версиями Git вы также можете добавить 1 , 2 или 3 к vimdiff или любому из вариантов (например, vimdiff3 , nvimdiff1 и т. д.), чтобы использовать предопределенный макет. Другими словами, использование —tool=[g,n,]vimdiffx аналогично использованию —tool=[g,n,]vimdiff и настройке переменной конфигурации mergetool.[g,n,]vimdiff.layout на…

  • x=1 : «@LOCAL, REMOTE»
  • x=2 : «LOCAL, MERGED, REMOTE»
  • x=3 : «MERGED»

Пример: использование —tool=gvimdiff2 откроет gvim с тремя столбцами (LOCAL, MERGED и REMOTE)..

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

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