1. Обзор
Работая с git в качестве нашей системы контроля версий (VCS), мы можем следовать любой из стратегий ветвления, но в конечном итоге нам может понадобиться интегрировать изменения из одной из веток функций в основную или основную ветку.
В этом руководстве мы рассмотрим два разных способа интеграции изменений из одной ветки в другую.
2. Перебазировать Git
Проще говоря, git rebase берет всю вашу функциональную ветку и перемещает ее в конец основной ветки . Он создает новые коммиты для каждого коммита в исходной функциональной ветке.
Давайте создадим новый репозиторий и ветку функций в репозитории, чтобы понять, как работает перебазирование:
git clone <your_repository_here>
git branch testBranch1
git branch testBranch2
Давайте создадим новый файл в функциональной ветке testBranch1
и зафиксируем изменения:
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch1
git log
Выполнение этих команд даст нам вывод ниже:
Теперь давайте попробуем перебазировать эту ветку на основную
ветку:
git rebase main
Это приведет к следующему сообщению:
Так как в основной
ветке нет коммитов, как видно из вышеизложенного, ожидать каких-либо изменений не стоит.
Теперь давайте объединим ветку функций с основной веткой:
git checkout main
git merge testBranch1
git push
git log
Эти команды выведут следующее:
Идентификаторы коммитов из ветки функций не изменяются при слиянии с основной веткой. Это похоже на то, что происходит при быстром слиянии.
Поскольку мы уже объединили testBranch1
с основной
веткой, в testBranch2
отсутствуют коммиты, из которых она была вырезана.
Давайте посмотрим, как происходит перебазирование и слияние testBranch2 .
Давайте создадим новый файл в функциональной ветке testBranch2
и зафиксируем изменения:
git checkout testBranch2
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch2
git log
И после выполнения этих команд мы увидим:
Теперь попробуем перебазировать эту ветку на основную
ветку:
git rebase main
И это должно дать нам сообщение, отличное от предыдущего случая:
Поскольку в основной
ветке есть некоторые коммиты , функциональная ветка была перебазирована на нее. Теперь давайте объединим featureBranch2 с основной веткой. Мы должны ожидать, что идентификаторы коммитов будут разными для featureBranch2
до и после перебазирования:
git checkout main
git merge testBranch2
git push
git log
Эти команды выведут следующее:
Идентификаторы коммитов отличаются, как и ожидалось, и если мы посмотрим на график журнала git, мы увидим, что репо имеет линейную историю:
git log --graph --oneline
Приведенная выше команда показывает структуру графа, отображающую информацию о коммите в одной строке:
3. Слияние Git
Git merge возьмет две ветки, которые мы объединяем, найдет общий базовый коммит, а затем воспроизведет последовательность коммитов из двух веток в базовом коммите, чтобы объединить ветки .
Давайте создадим новый репозиторий и пару веток функций, чтобы понять, как работает слияние:
Клонируйте репозиторий на свой локальный компьютер и создайте новую ветку функций:
git clone <your_repository_here>
git branch testBranch1
git branch testBranch2
Давайте создадим новый файл в функциональной ветке testBranch1
и зафиксируем изменения:
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch1
git log
Выполнение этих команд даст нам вывод ниже:
Теперь давайте объединим эту функциональную ветку с основной
веткой с помощью команды слияния:
git checkout main
git merge testBranch1
git push
git log
Эти команды выведут следующее:
Мы можем заметить, что последние идентификаторы коммитов такие же, как и на предыдущем изображении, но указатель HEAD указывает на основную
ветку.
Выше было простое слияние, в котором не было никаких изменений в основной
ветке, пока мы работали над нашей функциональной
веткой.
Давайте рассмотрим другой сценарий, в котором есть изменения как в основной, так и в функциональной ветке, и как git их обрабатывает.
Давайте создадим новый файл в функциональной ветке testBranch2
и зафиксируем изменения:
git checkout testBranch2
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch2
git log
И после выполнения этих команд мы получим следующее:
Теперь давайте объединим эту функциональную ветку с основной
веткой с помощью команды слияния:
git checkout main
git merge testBranch2
git log
Затем мы можем увидеть это в терминале:
Существует отдельный коммит слияния, на который сейчас указывает HEAD, в то время как исходные коммиты присутствуют для обеих ветвей функций. Самый верхний коммит также имеет дополнительный информационный ключ «Слияние», в котором указаны идентификаторы коммитов для обеих ветвей.
Мы также можем проверить граф ветвей и проверить историю репозитория:
git log --graph --oneline
Приведенная выше команда показывает структуру графа, отображающую информацию о коммите в одной строке:
4. Варианты использования
Всякий раз, когда нам требуется, чтобы история нашего репозитория была линейной, мы должны использовать перебазирование. Но мы должны быть осторожны с использованием перебазирования вместо слияния коммитов за пределами наших репозиториев, поскольку другие соавторы могут иметь свою собственную работу, основанную на существующих коммитах.
Перебазирование уже отправленных коммитов в общедоступный репозиторий приведет к другим идентификаторам коммитов, что может заставить git подумать, что основная ветка других разработчиков и ваша перебазированная основная ветка расходятся. Это может создать потенциально сложную ситуацию для слияния/синхронизации, если есть несколько соавторов.
5. Вывод
В этой статье мы рассмотрели основные различия между git merge и git rebase, которые должен знать каждый разработчик при работе с git VCS.