Home Как актуализировать изменения в общих модулях без pull request.
Post
Cancel

Как актуализировать изменения в общих модулях без pull request.

Проблема разработки с общим CommonUI

Освежим общий процесс разработки.

  1. Создаем задачу в Projects на GitHub
  2. Зная номер задачи создаем ветку feature/X, где X - номер задачи
  3. Разрабатываем, делая N комитов
  4. Когда задача завершена - делаем pull request
  5. Жмем кнопку и сливаем эти изменения в master.

Данная схема имеет смысл только когда напрямую в master комитить нельзя. Так у нас и настроено, чтобы этот flow нельзя было обойти.

Разработка фичи происходит какое-то время - несколько дней, неделю. И как можно заключить из вышеуказанного алгоритма разработки - pull request делается в общем один раз на фичу. Т.е. мы фичу разрабатываем в изоляции от master ветки.

Что делать, если кто-то залил свои изменения в master ? Казалось бы залил и залил. Но при pull request возникнет ошибка, и git заставит сначала выкачать новые изменения из master. Поэтому рекомендуется как можно чаще обновлять свою фича ветку из мастера, это избавит от проблем при pull request.

master branch has changes

Здесь видим, что master появились чужие изменения. Поэтому чтобы привести свою фича ветку develop в актуальное состояние выполняем команду:

1
2
$ git checkout master
$ git rebase develop master

После чего все встает на свои места:

master rebased to develop

Проблема обмена изменениями в Common модулях

Опишем следующую проблему в разработке. Допустим два разработчика разрабатывают 2 разные фичи и их изменения не пересекаются. Но пересечения все-таки скорее всего произойдут в общим модулях, таких как - Common или CommonUI. Иными словами, когда я разрабатываю экран, возможно я создам какой-то красивый UI элемент, который все могут переиспользовать. Но они не смогут им воспользоваться, пока разработчик не закончит разработку всей фичи и не зальет ее в master. А это, как уже говорилось, может произойти через несколько дней, а то и через неделю.

Как можно решить эту проблему ? Первый способ который напрашивается - вынести изменения в CommonUI и Common как отдельные задачи. Тогда и pull request по ним будет оправдан. Но все же, как я считаю, это плохой вариант, мы никогда не знаем когда захотим поправить common компонент, т.е. эти изменения сложно спланировать. И если делать на каждый небольшой чих pull request - это приведет к замедлению разработки и большому количеству лишних действий.

Другой способ, как я считаю, более оптимальный - иметь отдельную ветки для common и commonUI через которые фича ветки будут обмениваться последними изменениями в commonUI не прибегая к ветке master.

Посмотрим на примере. Создадим фейковый проект, с простой структурой папок.

1
2
3
4
5
6
7
8
.
├── Common
│   └── SomeCode.swift
├── Feature1
│   └── Feature1Source.swift
├── Feature2
│   └── Feature2Source.swift
└── Read.ME

Допустим я нахожусь в ветке feature/1 и произвел изменения в файлах Feature1Source.swift и SomeCode.swift. Т.е. Часть изменения касается непосредственно моей фичи, а другая общего модуля Common.

Теперь я хочу чтобы мои изменения в Common были доступны другим разработчикам, но саму фичу я еще продолжаю разрабатывать и не хочу еще делать pull request. Для этого я делаю комит своих изменений в Common. Здесь очень ВАЖНО! сделать кормит только изменения в папке Common.

Проэмулируем работу с файлами через консоль:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# изменения в файле Feature1/Feature1Source.swift

$ echo "some feature1 code" >> Feature1/Feature1Source.swift

# изменения в файле SomeCode.swift

$ echo "some common code" >> Common/SomeCode.swift

# убедиться что в файлах изменения добавились можно командой

$ cat Feature1/Feature1Source.swift

# в результате выведется:

some feature1 code

Далее делаем кормит изменений только в папке Common

1
2
3
4
5
6
7
8
$ git add -- ./Common
$ git commit -m 'My changes to Common' -- ./Common

# в результате выведется:

[feature/1 (root-commit) 4e1d4b0] My changes to Common
1 file changed, 1 insertion(+)
create mode 100644 Common/SomeCode.swift

Отлично, мы видим что в комит попали только изменения SomeCode.swift, что нам и нужно было.

Далее необходимо закомитить все остальные изменения по фиче:

1
2
$ git add .
$ git commit -m “Feature 1 changes”

Ура! Все наши изменения закомичены.

Далее необходимо сделать небольшое отступление и объяснить что такое cherry pick.

Cherry pick

Если простыми словами - cherry pick это способность взять отдельный комит и скопировать его в другую ветку. А это как раз то, что нам нужно - взять изменения модуля Common и перенести их в общую ветку для обмена ими в обход master ветки.

Посмотрим как работает cherry-pick схематично. Допустим у нас есть две ветки:

1
2
3
a - b - c - d  Main
 \
  e - f - g    Feature

И мы хотим кормит f перенести в ветку Main. Тогда выполняем две команды

1
2
$ git checkout main
$ git cherry-pick f

В результате получаем следующую картину:

1
2
3
a - b - c - d - f  Main
 \
  e - f - g    Feature

Применение cherry pick на практике.

Сольём только Common изменения в ветку common.

Вернемся к нашему проекту. Первое что нам нужно - это узнать sha код комита, который мы сделали из папки Common. Для этого выполняем команду:

1
$ git log

Получаем приблизительно такой результат:

1
2
3
4
5
6
7
8
9
10
11
12
commit abae47d4524651fea4c08bf47393963a0a1dde47 (HEAD -> feature/1)
Author: Sergio <afirthes@gmail.com>
Date:   Wed Sep 14 21:17:23 2022 +0300

    Feature 1 changes

commit 4e1d4b0a91cea71aaac23839db4443133c20ab5a (common)
Author: Sergio <afirthes@gmail.com>
Date:   Wed Sep 14 21:01:01 2022 +0300

    My changes to Common

Там может быть много записей, нас интересует именно наш комит по Common. Для его поиска можно ориентироваться на ветку feature/1 и комментарий комита.

Далее запоминаем sha комита - 4e1d4b0a91cea71aaac23839db4443133c20ab5a. На самом деле достаточно запомнить первые несколько символов, вероятность что они повторяются довольно мала.

И делаем следующее:

1
2
$ git checkout common
$ git cherry-pick 4e1d4b0

Если все прошло успешно - с помощью git log - мы увидем в списке наш коммит с соотвествующим кодом. Задача выполнена - мы слили в ветку common все изменения касающиеся папки Common, а все другие изменения оставили в feature/1 ветке.

Осталось только разобраться как забирать в свою фича ветку изменения из common ветки.

Подтягивание в свою ветку изменений из common.

Итак, допустим я разрабатываю фичу 2 в ветке feature/2 и мне нужно подгрузиь изменения из common. Тогда делаю просто:

1
2
$ git checkout feature/2
$ git rebase feature/2 common

Всё. Мы подтянули изменения в папке Common из ветки feature/1 в ветку feature/2, используя промежуточную ветку common. Теперь я могу использовать общие компоненты своего коллеги, даже несмотря на то, что их пока нет в master.

Не забываем что ветки нужно как можно чаще push-ить на сервер.

Примерно схему такой работы можно показать так:

common branch flow scheme

This post is licensed under CC BY 4.0 by the author.
Trending Tags