Что делает «git merge –abort»?
Главное меню » Статьи » Что делает «git merge –abort»?
Цель операции «git merge –abort»:
Прежде чем понять использование операции «git merge –abort», мы должны понять, зачем нам вообще нужна такая операция. Как вы все знаете, Git ведет историю всех различных версий файла или кода; поэтому разные версии, которые вы создаете, называются коммитами Git. Кроме того, существует выделенная текущая фиксация, то есть версия файла, над которым вы в настоящее время работаете. Иногда вы можете почувствовать необходимость объединить ранее зафиксированный файл с тем, над которым вы сейчас работаете.
Однако во время этого процесса слияния может случиться так, что любой другой ваш коллега также работает с тем же файлом. Он может отменить изменения, которые вы сохранили, или изменить строки, которые вы только что добавили в файл. Этот сценарий может привести к конфликту слияния в Git. Как только возникает конфликт слияния в Git, и вы пытаетесь проверить статус Git, он отображает сообщение о том, что произошел конфликт слияния. Вы не сможете ничего сделать с этим конкретным файлом, пока вам не удастся исправить этот конфликт.
Здесь в игру вступает операция «git merges –abort». По сути, вы хотите вернуться к старому состоянию, в котором вы можете сохранить текущую версию файла без изменений и начать вносить изменения заново. Таким образом вы гарантируете, что подобные конфликты больше не возникнут в будущем. Таким образом, операция «git merge –abort» по существу завершает слияние, которое вы только что выполнили, и разделяет две версии вашего файла, то есть текущую версию и старую версию.
Таким образом, текущая версия вашего файла вернется в то же состояние, в котором она была до выполнения операции слияния, и, следовательно, вы сможете восстановить ее без каких-либо потенциальных трудностей. Однако здесь следует отметить важный момент: операция «git merge –abort» работает только в том случае, если вы только что слили свои файлы и еще не зафиксировали их. Если вы уже совершили это слияние, то операция «git merge –abort» больше не будет служить этой цели; скорее, вам придется искать другие способы отменить слияние.
Заключение:
Поняв обсуждение, которое мы провели сегодня, вы легко поймете цель операции «git merge –abort». Эта операция не только разрешает конфликты слияния, которые возникают до фиксации слияния, но также помогает восстановить ваши файлы до того же состояния, в котором они находились раньше. Таким образом, ваши данные не потеряны, и вы можете удобно начать работу над ними заново.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Конфликты слияния в 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 способна обрабатывать самостоятельно с помощью функций автоматического слияния. Конфликт возникает, когда в двух ветках была изменена одна и та же строка в файле или когда некий файл удален в одной ветке и отредактирован в другой. Как правило, конфликты возникают при работе в команде.
Готовы попробовать ветвление?
Ознакомьтесь с этим интерактивным обучающим руководством.
Продвинутое слияние
Обычно выполнять слияния в Git довольно легко. Git упрощает повторные слияния с одной и той же веткой, таким образом, позволяя вам иметь очень долго живущую ветку, и вы можете сохранять ее всё это время в актуальном состоянии, часто разрешая маленькие конфликты, а не доводить дело до одного большого конфликта по завершению всех изменений.
Однако, иногда всё же будут возникать сложные конфликты. В отличие от других систем управления версиями, Git не пытается быть слишком умным при разрешении конфликтов слияния. Философия Git заключается в том, чтобы быть умным, когда слияние разрешается однозначно, но если возникает конфликт, он не пытается сумничать и разрешить его автоматически. Поэтому, если вы слишком долго откладываете слияние двух быстрорастущих веток, вы можете столкнуться с некоторыми проблемами.
В этом разделе мы рассмотрим некоторые из возможных проблем и инструменты, которые предоставляет Git, чтобы помочь вам справиться с этими более сложными ситуациями. Мы также рассмотрим некоторые другие нестандартные типы слияний, которые вы можете выполнять, и вы узнаете как можно откатить уже выполненные слияния.
Конфликты слияния
Мы рассказали некоторые основы разрешения конфликтов слияния в Основные конфликты слияния, для работы с более сложными конфликтами Git предоставляет несколько инструментов, которые помогут вам понять, что произошло и как лучше обойтись с конфликтом.
Во-первых, если есть возможность, перед слиянием, в котором может возникнуть конфликт, позаботьтесь о том, чтобы ваша рабочая копия была без локальных изменений. Если у вас есть несохранённые наработки, либо припрячьте их, либо сохраните их во временной ветке. Таким образом, вы сможете легко отменить любые изменения, которые сделаете в рабочем каталоге. Если при выполнении слияния вы не сохраните сделанные изменения, то некоторые из описанных ниже приёмов могут привести к утрате этих наработок.
Давайте рассмотрим очень простой пример. Допустим, у нас есть файл с исходниками на Ruby, выводящими на экран строку ‘hello world’.
В нашем репозитории, мы создадим новую ветку по имени whitespace и выполним замену всех окончаний строк в стиле Unix на окончания строк в стиле DOS. Фактически, изменения будут внесены в каждую строку, но изменятся только пробельные символы. Затем мы заменим строку «hello world» на «hello mundo».
Теперь мы переключимся обратно на ветку master и добавим к функции некоторую документацию.
Теперь мы попытаемся слить в текущую ветку whitespace и в результате получим конфликты, так как изменились пробельные символы.
Прерывание слияния
Эта команда пытается откатить ваше состояние до того, что было до запуска слияния. Завершиться неудачно она может только в случаях, если перед запуском слияния у вас были не припрятанные или не зафиксированные изменения в рабочем каталоге, во всех остальных случаях всё будет хорошо.
Игнорирование пробельных символов
В данном конкретном случае конфликты связаны с пробельными символами. Мы знаем это, так как это простой пример, но в реальных ситуациях это также легко определить при изучении конфликта, так как каждая строка в нем будет удалена и добавлена снова. По умолчанию Git считает все эти строки изменёнными и поэтому не может слить файлы.
Поскольку в этом примере реальные изменения файлов не конфликтуют, то при игнорировании изменений пробельных символов всё сольётся хорошо.
Это значительно облегчает жизнь, если кто-то в вашей команде любит временами заменять все пробелы на табуляции или наоборот.
Ручное слияние файлов
Хотя Git довольно хорошо обрабатывает пробельные символы, с другими типами изменений он не может справиться автоматически, но существуют другие варианты исправления. Например, представим, что Git не умеет обрабатывать изменения пробельных символов и нам нужно сделать это вручную.
Во-первых, мы перейдём в состояние конфликта слияния. Затем нам необходимо получить копии нашей версии файла, их версии файла (из ветки, которую мы сливаем) и общей версии (от которой ответвились первые две). Затем мы исправим либо их версию, либо нашу и повторим слияние только для этого файла.
Получить эти три версии файла, на самом деле, довольно легко. Git хранит все эти версии в индексе в разных «состояниях», каждое из которых имеет ассоциированный с ним номер. Состояние 1 — это общий предок, состояние 2 — ваша версия и состояния 3 взято из MERGE_HEAD — версия, которую вы сливаете («их» версия).
Вы можете извлечь копию каждой из этих версий конфликтующего файла с помощью команды git show и специального синтаксиса.
Выражение :1:hello.rb является просто сокращением для поиска такого SHA-1 хеша.
Итак, здесь мы можем легко увидеть что же произошло с нашей веткой, какие изменения в действительности внесло слияние в данный файл — изменение только одной строки.
В данный момент мы можем использовать команду git clean для того, чтобы удалить не нужные более дополнительные файлы, созданные нами для выполнения слияния.
Использование команды checkout в конфликтах
Возможно, нас по каким-то причинам не устраивает необходимость выполнения слияния в текущий момент, или мы не можем хорошо исправить конфликт и нам необходимо больше информации.
Давайте немного изменим пример. Предположим, что у нас есть две долгоживущих ветки, каждая из которых имеет несколько коммитов, что при слиянии приводит к справедливому конфликту.
Мы хотели бы увидеть в чем состоит данный конфликт. Если мы откроем конфликтующий файл, то увидим нечто подобное:
В обеих сливаемых ветках в этот файл было добавлено содержимое, но в некоторых коммитах изменялись одни и те же строки, что и привело к конфликту.
Давайте рассмотрим несколько находящихся в вашем распоряжении инструментов, которые позволяют определить как возник этот конфликт. Возможно, не понятно как именно вы должны исправить конфликт и вам требуется больше информации.
После того, как вы выполните эту команду, файл будет выглядеть так:
Это может быть действительно полезным при возникновении конфликтов в бинарных файлах (в этом случае вы можете просто выбрать одну из версий), или при необходимости слить из другой ветки только некоторые файлы (в этом случае вы можете выполнить слияние, а затем перед коммитом переключить нужные файлы на требуемые версии).
История при слиянии
Для получения полного списка всех уникальных коммитов, которые были сделаны в любой из сливаемых веток, мы можем использовать синтаксис «трёх точек», который мы изучили в Три точки.
Это список всех шести коммитов, включённых в слияние, с указанием также ветки разработки, в которой находится каждый из коммитов.
Комбинированный формат изменений
Так как Git добавляет в индекс все успешные результаты слияния, то при вызове git diff в состоянии конфликта слияния будет отображено только то, что сейчас конфликтует. Это может быть полезно, так как вы сможете увидеть какие ещё конфликты нужно разрешить.
Если вы выполните git diff сразу после конфликта слияния, то получите информацию в довольно своеобразном формате.
Такой формат называется «комбинированным» («Combined Diff»), для каждого различия в нем содержится два раздела с информацией. В первом разделе отображены различия строки (добавлена она или удалена) между «вашей» веткой и содержимым вашего рабочего каталога, а во втором разделе содержится то же самое, но между «их» веткой и рабочим каталогом.
Таким образом, в данном примере вы можете увидеть строки и >>>>>>> в файле в вашем рабочем каталоге, хотя они отсутствовали в сливаемых ветках. Это вполне оправдано, потому что, добавляя их, инструмент слияния предоставляет вам дополнительную информацию, но предполагается, что мы удалим их.
В этом выводе указано, что строка «hola world» при слиянии присутствовала в «нашей» ветке, но отсутствовала в рабочей копии, строка «hello mundo» была в «их» ветке, но не в рабочей копии, и, наконец, «hola mundo» не была ни в одной из сливаемых веток, но сейчас присутствует в рабочей копии. Это бывает полезно просмотреть перед коммитом разрешения конфликта.
Отмена слияний
Теперь когда вы знаете как создать коммит слияния, вы можете сделать его по ошибке. Одна из замечательных вещей в работе с Git — это то, что ошибки совершать не страшно, так как есть возможность исправить их (и в большинстве случаев сделать это просто).
Есть два подхода к решению этой проблемы, в зависимости от того, какой результат вы хотите получить.
Исправление ссылок
, то указатели веток восстановятся так, что будут выглядеть следующим образом:
Перемещает ветку, на которую указывает HEAD. В данном случае мы хотим переместить master туда, где она была до коммита слияния ( C6 ).
Приводит индекс к такому же виду что и HEAD.
Приводит рабочий каталог к такому же виду, что и индекс.
Отмена коммита
Если перемещение указателей ветки вам не подходит, Git предоставляет возможность сделать новый коммит, который откатывает все изменения, сделанные в другом. Git называет эту операцию «восстановлением» («revert»), в данном примере вы можете вызвать её следующим образом:
История с коммитом восстановления (отменой коммита слияния) выглядит следующим образом:
Лучшим решением данной проблемы является откат коммита отмены слияния, так как теперь вы хотите внести изменения, которые были отменены, а затем создание нового коммита слияния:
Другие типы слияний
До этого момента мы рассматривали типичные слияния двух веток, которые обычно выполняются с использованием стратегии слияния, называемой «рекурсивной». Но существуют и другие типы слияния веток. Давайте кратко рассмотрим некоторые из них.
Выбор «нашей» или «их» версий
В этом случае Git не будет добавлять маркеры конфликта. Все неконфликтующие изменения он сольёт, а для конфликтующих он целиком возьмёт ту версию, которую вы указали (это относится и к бинарным файлам).
Если мы вернёмся к примеру «hello world», который использовали раньше, то увидим, что попытка слияния в нашу ветку приведёт к конфликту.
В этом случае, вместо добавления в файл маркеров конфликта с «hello mundo» в качестве одной версии и с «hola world» в качестве другой, Git просто выберет «hola world». Однако, все другие неконфликтующие изменения будут слиты успешно.
На случай если вам нужно нечто подобное, но вы хотите, чтобы Git даже не пытался сливать изменения из другой версии, существует более суровый вариант — стратегия слияния «ours». Важно отметить, что это не то же самое что опция «ours» рекурсивной стратегии слияния.
Фактически, эта стратегия выполнит ненастоящее слияние. Она создаст новый коммит слияния, у которой родителями будут обе ветки, но при этом данная стратегия даже не взглянет на ветку, которую вы сливаете. В качестве результата слияния она просто оставляет тот код, который находится в вашей текущей ветке.
Вы можете видеть, что между веткой, в которой мы были, и результатом слияния нет никаких отличий.
Слияние поддеревьев
Идея слияния поддеревьев состоит в том, что у вас есть два проекта и один из проектов отображается в подкаталог другого. Когда вы выполняете слияние поддеревьев, Git в большинстве случаев способен понять, что одно из них является поддеревом другого и выполнить слияние подходящим способом.
Далее мы рассмотрим пример добавления в существующий проект другого проекта и последующее слияние кода второго проекта в подкаталог первого.
Первым делом мы добавим в наш проект приложение Rack. Мы добавим Rack в наш собственный проект, как удалённый репозиторий, а затем выгрузим его в отдельную ветку.
Таким образом, теперь у нас в ветке rack_branch находится основная ветка проекта Rack, а в ветке master — наш собственный проект. Если вы переключитесь сначала на одну ветку, а затем на другую, то увидите, что они имеют абсолютно разное содержимое:
Может показаться странным, но, на самом деле, ветки в вашем репозитории не обязаны быть ветками одного проекта. Это мало распространено, так как редко бывает полезным, но иметь ветки, имеющие абсолютно разные истории, довольно легко.
Когда мы будем выполнять коммит, он будет выглядеть так, как будто все файлы проекта Rack были добавлены в этот подкаталог — например, мы скопировали их из архива. Важно отметить, что слить изменения одной из веток в другую довольно легко. Таким образом, если проект Rack обновился, мы можем получить изменения из его репозитория просто переключившись на соответствующую ветку и выполнив операцию git pull :
Таким образом, слияние поддеревьев даёт нам возможность использовать рабочий процесс в некоторой степени похожий на рабочий процесс с подмодулями, но при этом без использования подмодулей (которые мы рассмотрим в Подмодули). Мы можем держать ветки с другими связанными проектами в нашем репозитории и периодически сливать их как поддеревья в наш проект. С одной стороны это удобно, например, тем, что весь код хранится в одном месте. Однако, при этом есть и некоторые недостатки — поддеревья немного сложнее, проще допустить ошибки при повторной интеграции изменений или случайно отправить ветку не в тот репозиторий.
Вот как выглядит процедура сравнения содержимого подкаталога rack с содержимым ветки master на сервере после последнего скачивания изменений:









