- •Цели лабораторной работы
- •Задачи к лабораторной работе
- •Методические материалы
- •Системы контроля версий
- •Знакомство с Git
- •Целостность Git
- •Ветвление в Git
- •Ветки
- •Fast-forward
- •Rebase
- •Ход работы
- •Установка Git
- •Выполнение работы
- •Создание нового репозитория
- •Работа с репозиторием
- •Создание мастер репозитория
- •Клонирование репозитория
- •Конфликт и решение конфликта
- •Контрольные вопросы
3.4Слияние и перебазирование веток
В процессе работы у вас может появится потребность объединить код из разных веток: к примеру, в основную ветку вашего проекта надо добавить функционал из ветки feature . Git предоставляет несколько способов, как это можно сделать.
3.4.1Fast-forward
В приведённом ниже примере ветка feature опережает ветку main на два коммита, то есть ветка main не имеет параллельных версий, а граф имеет линейную структуру. В такой ситуации достаточно перенести указатель вперёд (fast-forward):
1.Для слияния ветки <source_branch> в ветку <target_branch> с помощью команды git merge <source_branch> необходимо находится на <target_branch> . Так как мы хотим влить ветку feature в main , нам надо переключится на ветку main ;
2.Выполним команду git merge feature . Обратите внимание на сообщение "Fastforward"в выводе;
Вслучаях, когда при fast-forward слиянии необходимо оставить историю, можно
ккоманде git merge <source_branch> добавить флаг --no-ff (no fast-forward), тогда будет создан новый коммит:
15
3.4.2Merge
В ситуации, когда коммит, на котором мы находимся, не является прямым родителем ветки, с которой мы выполняем слияние, Git выполняет простое трёхстороннее слияние, используя последние коммиты объединяемых веток и общего для них родительского коммита.
В данном примере в ветку main был добавлен новый файл, которого нет в ветке
16
feature . Следовательно, при слиянии Git объединил версии feature и main в один новый коммит.
Но в процессе разработки, один и тот же файл может независимо изменяться в разных ветках, и тогда при слиянии появится конфликт версий, который нам придется решить вручную, и после закончить слияние:
В примере выше файл readme.md был изменён в двух ветках. При попытке их
17
слияния Git выдал сообщение о конфликте. При этом файл внутри себя содержит информацию о изменениях текущей ветки (строки между <<<<<<< HEAD и ======= ) и вливаемой ветки (строки между ======= и >>>>>>> feature ).
Предположим, что мы хотим оставить строку # Greeting , но поменять приветствие на то, которое было сделано в ветке main . Отредактируем файл соответствующим образом.
При проверке статуса, Git сообщает, что имеются неслитые изменения. Добавляем изменённый файл в индекс и коммитим.
3.4.3Rebase
Суть метода rebase (перебазирования) заключается в том, чтобы взять изменения из одной ветки и применить их поверх другой. В таком случае берётся общий родительский коммит двух веток (текущей, и той, поверх которой вы выполняете перебазирование), определяется дельта каждого коммита текущей ветки и сохраняется во временный файл, текущая ветка устанавливается на последний коммит ветки, поверх которой вы выполняете перебазирование, а затем по очереди применяются дельты из временных файлов.
В отличие от команды git merge , для git rabase необходимо находиться на той ветке, которая будет перебазирована.
18
При перебазировании ветки у нас возникает конфликт. Смотрим содержимое и видим, что это конфликт с коммитом eb1fb68 – всё верно, так как было сказано ранее: при перебазировании определяются изменения для каждого коммита ветки. Решаем конфликт и продолжаем процедуру ( git rebase --continue ) и снова встречаем конфликт, но уже коммита 046a91f :
19
Решаем конфликт и продолжаем перебазирование ( git rebase --continue ). После завершения переноса коммитов граф принимает линейный вид. Теперь мы можем переключится на ветку main и выполнить быстрое перемещение указателя.
Обратите внимание, что "перенесённые"коммиты имеют отличный от оригинала хеш. Всё по тому, что это новые коммиты, а исходные попали в состояние, когда ни одна ветка не указывает на них.
20
