June 12, 2022

Поговорим про слияния веток, м?

Вступление

Немного теории. Для начала предлагаю вкратце вспомнить пару терминов из git:

Ветка

Ветвление в GIt. Две ветки master и featuer1

Ветки имеют две функции: ответвляться и сливатся.

Предназначены разделять поток разработки. Если мы говорим про продуктовую разработку - с помощью веток мы можем разбить состояния продукта на версии (релизы/release), а для каждых релизов вести разработку несколько функциональных новшеств (фичи/features) разными или одним и тем же разработчиками.

Комиты

Создание нового комита

Комиты - снимок текущего состояния содержимого файла(ов).

Через команду

git add . // git заносит файлы в stage area

Оттуда уже можно выполнить команду

git commit -m “комментарий по изменениям” 

тем самым создать комит в ветке. (Как показано на рисунке выше)

Слияние. Git Merge

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

Ветвление ветки stage от master

Для этого в ветку master нужно слить последние изменения ветки stage (обычно в этой ветке находятся актуальные, полностью протестированные новые фичи)

Git предоставляет такую возможность, с помощью команды merge.

Для начала нам нужно перейти в ветку master.

git checkout master

Далее

git merge stage
Слияние ветки stage в master

Fast forward или быстрая склейка.

Хочу обратить ваше внимание после выполнения данной операции, git предупреждает нас в консоли, что произошло так называемое быстрая склейка” (fast-forward).

Это произошло потому, что комит S1 имеет в качестве родителя - последний коммит ветки master. Git видит, что параллельно разработки на ветке stage, в ветке master не было воспроизведено никаких изменений, следовательно, можно считать, что stage фактически является продолжением ветки master. Отсюда “быстрая склейка”.

В оригинальном переводе fast forward дословно переводиться с англ. на рус. как “быстрая перемотка”. Для удобства понимания я назвал это явление “быстрая склейка”

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

Ветвление ветки feature-2341 от dev с наличием параллельной разработки в ветке dev

Теперь представим, немного другую ситуацию, которая является самой распространенной.

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

Вот, пришла задача - разработать шапку для сервиса и мы создали ветку feature-2341 от ветки dev (коммит C3 - начало ответвления ветки feature-2341).

В процессе разработки/решения этой задачи в dev другие разработчики сливали другие задачки, образуя новые комиты (C4, C5).

И вот вопрос, каким же образом Git будет сливать в этом случаи ветку feature-2341в dev?

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

Решение называется трехстороннее слияние потому, что git берёт последние комиты с ветки feature-2341 и dev, и третьим комитом - берёт родительский комит для ветки feature-2341 - С3, по итогу получаем 3 комита, отсюда название.

Дальше git создает новый комит.

Git merge после трехстороннего слияния ветки feature-2341 с веткой dev

Примечание по fast-forward

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

То есть, таким образом:

git merge stage —no-ff

В таком случаи, git создаст новый комит (merge commit)

Проблема merge

И так, вот мы добрались до кульминационного момента.

Бывает такая потребность, что при merge не хотелось бы получать новый комит.

Решение, на самом деле, есть, но оно заключается в использовании другой команды - rebase.

Git Rebase

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

Разветвление ветки feature-2022 от ветки dev

Представим, что нам нужно обновить ветку feature-2022 до актуального состояния ветки dev.

Для этого мы можем выполнить команду rebase.

Убедимся что мы находимся на ветке feature-2022, далее можно выполнить rebase:

git rebase dev

Что же произойдет?

Механика работы Rebase

Механика работы Git Rebase

После выполнения команды гита - git rebase dev Git “оторвёт” ветку от изначального ответвляющего комита-родителя C4 и перенесёт-закрепит ответвление в самый конец ветки dev, тем самым в ветке feature-2022 фиксируются все актуальные изменения dev.

Важно понимать!!!

После перебазировки ветки все её комиты изменяют свой hash, это потому, что при “переносе” ветки в конец подливаемой ветки, на самом деле, создаются новые комиты и удаляются старые, от старого родителя.

Поэтому, после Вам следует быть с этим способом обновления ветки очень аккуратными, поскольку меняется (не дополняется, как в случаи merge) история Git, и при командной разработке - может сыграть злую шутку, если не предупреждать команду об обновлении.

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

git push -f origin HEAD

HEAD - символическая ссылка на текущую ветку. На этом подробно останавливаться не будем.

Итого

  • Вкратце вспомнили, что такое ветки, комиты
  • Рассмотрели возможность и механику команды merge на поверхностном уровне понимания
  • Познакомились с Git Rebase, для обновления ветки изменениями другой ветки.

На самом деле, это только вершина вершины айсберга, тот же самый git rebase имеет помимо всего интерактивный режим, можно склеивать несколько комитов, менять комментарий и много другое.

Подписывайтесь на мой профиль в TenChat - дальше больше, я сам в своём роде только углубляюсь в процессы работы Git’а, в том плане, как это работает, на самом деле.

Данная статья послужит неким началом, хоть и не совсем систематически в плане материалы такой темы как Git, но тем не менее, надеюсь, заинтересую.

Буду рад, если найдете очепятки, какие-либо неточности - пишите в комментариях. Всё исправлю, если это будет конструктивно.