Pull to refresh

Comments 36

Увидев в очередной раз базворд GitFlow я психанул и решил перевести описание более простой и менее проблемной схемы работы с ветками под названием GitHub Flow. Именно её имеет смысл использовать по умолчанию, переходя к какой-то другой лишь в случае непреодолимых обстоятельств.

GitHub Flow, так же как и другие виды бранч менеджмента могут решить, а могут и не решить задач конкретной команды. Стоит подбирать метод под свои задачи, а не под веление современности. Не люблю смотреть на вопрос однобоко - наверно это и была цель статьи.

Все равно начинать изучать вопрос стоит сначала, в дальнейшем я хочу рассмотреть GitHubFlow, как один из современных подходов, а так же опишу свои мысли на эту тему.

В любом случае спасибо за активность и отзыв о проделанной работе!!!

Благодарю!!!

Благодарю за мнение, оно очень важно для меня.

Это не мнение, а восполнение пробела в ваших знаниях. Не стоит благодарности.

Это Вы о чём?

C++ ещё старше.

И? Какой Вы сделаете вывод? C++ не нужен? Устарел?

С++ устарел, когда появился D.

2010 - перевод оригинальной статьи https://habr.com/ru/articles/106912/
2020 - опровержение оригинальной статьи https://habr.com/ru/companies/flant/articles/491320/
альтернативы - https://habr.com/ru/companies/infopulse/articles/345826/
и практика - https://habr.com/ru/articles/705032/
На хабре точно была нужна еще одна подобная статья про gitflow, да еще и с картинками из старых статей?

За последние 4 года я участвовал в семи разных проектах и ни один я бы не назвал маленьким, но нигде не было нормального git менеджмента, соответственно стоит потрогать информацию снова. Мне очень симпатичен процесс изучения от истоков к современности. Какой git менеджент предпочитаете вы?

GitFlow имеет смысл только если нет простого механизма отката изменений из прода (читай "мобильная разработка"). В остальных случаях GitHub Flow проще и стабильнее. Для обеспечения стабильности, катить в прод нужно до того как слили в мастер, и сливать только после того как убедились, что ничто не сломано. Если сломано - rollback на последний мастер в общем случае.

Хранение кода в любом случае это вопрос творческий. Катить в препрод и проверять там до мастера я согласен, а в сам прод до мастера - звучит неправильно. Спасибо, я обязательно разберу github flow в следующей статье, как один из современных подходов.

Хранение кода в любом случае это вопрос творческий.

И не обязан быть в одном репозитарии.

Хотелось бы увидеть статью, посвященную методов, когда репозитариев - много (на машинах разработчиков, для стенд(ов) тестирования, архивный итд) и ветки из одного в другой перекидываются в процессе разработки.

"звучит неправильно" - так себе аргумент. Код в ветке после ребейза на мастер ничем не отличается от кода в мастере после мержа. Разница между этими подходами только в том, что сливая в мастер до выкатки мы увеличиваем вероятность получить сломанный коммит в мастере.

Я не очень понимаю о чем вы. При любом мерже или ребейсе, есть вероятность получить конфликт. То есть где-то в какой-то ветке у вас код рабочий, а в мастере конфликт неправильно решен, но создавать фича ветки вы будете из мастера. ИТОГ? Код не будет правильно работать в след версиях.

При чем тут конфликты? Если мы ребейзнули ветку на последний мастер, то мерж этой ветки в мастер будет fast-forward, master и feature-branch будут указателями на один и тот же коммит.

Снепшот кода который мы деплоим будет одинаковым в обоих вариантах флоу:

# flow 1
git fetch
git rebase origin/master
deploy to prod
git checkout master
git merge feature-branch

# flow 2
git fetch
git rebase origin/master
git checkout master
git merge feature-branch
deploy to prod

Понятно что в реальности есть куча нюансов, если команда большая, то возможно будет нужно настроить merge queue и тд., но думаю, общий смысл понятен.

Если бы все были такими умными и грамотными, как вы =)

Я когда уходил с одного из проектов, вместо меня релизы делать поставили Джуна, а он «ребейс» слово такое не слышал.

Точно так же и в самих программах прослойках (условно гитхаб подобных системах) есть баги.

Если есть вероятность на какой-то из точек упасть или ошибиться, то это плохо.

Мы же особенности flow обсуждаем, причем тут джуны и ошибки?

Как раз с точки зрения риска и сложности gitflow проигрывает, если мы говорим о типичной backend разработке.

Зачем рисковать возникновением эмерджентных багов при интеграции фич , усложнять цикл разработки и размывать ответственность введением таких ролей как релиз-инженер и тд, когда можно быстро катить фичи атомарно?

Научить людей ребейзить - не очень сложная задача.

Я бы с удовольствием почитал о вашем варианте бранч менеджмента.

В общем и целом - https://githubflow.github.io/

Выкатка в прод немного отличается. Алгоритм следующий:
1. Lock master branch
2. Rebase on origin/master
3. Deploy to production
4. Track metrics
5. Merge to master
6. Unlock master

Если на 4-м шаге возникли какие-то проблемы то просто откатываем на последний мастер.
Разработчик полностью отвечает за весь цикл разработки фичи и сам катит ее в прод. Каждая фича катится атомарно, то есть нет необходимости выяснять кто и что сломал в ветке где идет интеграция при подготовке релиза, так как "релизов" по сути нет. При таком флоу нормальная продуктивная команда из 5-7 человек катит в прод 2-3 раза в день.

А что если другая команда выпустила свою фичу и раньше влила ее в мастер и merge с мастером имеет конфликты?

Технически такая ситуация не возможна, обычно разные команды пишут код в разных репах.

Расскажите это ребятам из google или yandex :)

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

Вы соседям можете диктовать что им делать только снаружи их територии, но не внутри!

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

<Глядим на (в который раз повторяющейся) картинки.>

И пытаемся объяснить/нарисовать.

  • Как будет выглядеть граф коммитов и тегов, когда у нас выпускается хотфикс, который приводит к появлению версий 0.3 и 1.1 Все на main поставить уже не получится, если я ничего не путаю.

  • Какой цели вообще ветка main служит? Хранит 'рабочие/продовские' версии? Ну так у нас теги 0.3, 1.0 итд есть, которые можно с успехом поставить на коммитках веток release-*

Это я к тому, что master ветка как таковая тут практически лишняя и тащится из объяснения к объяснению просто по инерции.

Мастер ветка нужна для того, чтобы там были исключительно релизные коммиты-теги, от которых отпочковываться в случае хотфиксов (которые затем назад вливаются одним коммитом).
Очень чистая ветка, один коммит - один релиз

Девелоп ветка содержит чистые вливания готовых и законченных фич, и от нее отпочковываются релизные ветки. Это нужно в том случае, если у вас в разработке может быть сразу несколько релизов с разными набором фич, которые еще допиливаются, и надо ближайший релиз уже отрезать от девелопмента, чтобы в него непопадали новые фичи следующих релизов.

А вот релизные ветки как таковые хранить не нужно, в них просто всякий "мусор" - вливания фич, багфиксы в процессе тестирования, срочные довливания и заметание под ковер перед релизом, это все в деталях хранить не обязательно.

Поэтому в git workflow стабильные ветки это только мастер и девелопмент. ВСЕ остальные удаляются после мержа или после мержа с небольшой задержкой.

Но вообще, перед тем как выбирать воркфлоу, автору следовало в первую очередь подумать именно над релизами, именно от политики релизов и разработки следует отталкиваться при выборе своего флоу (или кастомизации любого популярного)

Да, вы правы, Я тоже за чистоту в ветках!

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

Согласен, при выборе метода для бранч менедждмента, схема и частотность релизов один из главных критериев. В моем случае магистральная доставка вообще не имела быть, потому что проект разрабатывался с нуля, и релизить каждую новую таблицу или функцию не имело практичекского смысла.

Мастер ветка нужна для того, чтобы там были исключительно релизные коммиты-теги, от которых отпочковываться в случае хотфиксов (которые затем назад вливаются одним коммитом).Очень чистая ветка, один коммит - один релиз

Для чего нужна ветка. Релизных коммит-тегов, поставленных там где надо - достаточно же вроде? То что там между этими тегами пачки коммитов будут - вроде ничему не мешает.

А так же смотрим у меня первый пункт. Версию 0.3 как на main помещать придется?

А вот релизные ветки как таковые хранить не нужно, в них просто всякий "мусор" - вливания фич, багфиксы в процессе тестирования, срочные довливания и заметание под ковер перед релизом, это все в деталях хранить не обязательно.

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

Вот есть у нас у PostgreSQL версии 16.* и он же 10.* -- неужели эти ветки 'хранить не нужно'? (Я про картину мира gitflow. Мое собственное мнение - что таки да, не нужно. Те же аргументы, что про main выше, и к ним применимы -- расставляем теги где надо и все)

Хранить ветки релизов и хотфиксов, где проставляется тег новой версии - тоже один из подходов, но для меня это точно так же как и не мыть посуду после еды =))

Я считаю, что все версии стоит хранить в одной коробке (main), что бы не нарушать принцип консистентности данных. Да и остальные 100 - 500 веток релизов и фиксов - нужно удалить.

Зачем все это тащить в новый мир?

Для чего нужна ветка. Релизных коммит-тегов, поставленных там где надо - достаточно же вроде? То что там между этими тегами пачки коммитов будут - вроде ничему не мешает.

Очень даже мешает.

Лишние коммиты мешают и просмотру истории нормальной и отпочковыванию. Если в вашем проекте релиз в полгода-год и коммитов 50-60 в месяц, то представьте проект где релизы идут каждую неделю, а коммитов столько, что даже фича бренчей за полгода накапливается пару тысяч.

Зачем это все хранить, менеджить?
Как автоматизировать релиз ноты, если в коммитах куча мусора, а не аккуратное JIRA-1000 feature blabla, JIRA-2000 bugfix blabla

А так же смотрим у меня первый пункт. Версию 0.3 как на main помещать придется?

Хотфикс это тоже релиз. Просто слово хотфикс обозначает и фикс конкретного ишью, и релиз, когда в продакшен это изменение выводится А ведь одним релизом можно несоклько ишью поправить поэтому в данном случае хотфикс - это именно релиз, минорный, без новыйх фич, просто багфиксы/хотфиксы. И он должен быть в майн ветке, поскольку версию 2 нужно отпочковывать уже не от 2.0, а от 2.03 хотфикса, как последнего в этой версии.

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

Релизная ветка - это ветка, которая готовится для релиза ДО того как он выведен в продакшен.

Раньше делали code freeze - замораживали всю разработку и тестировали эту версию, внося багфиксы перед релизом. Сейчас можно сделать релизную ветку и фиксить в ней, при этом все фиксы для эотго релиза мержатся и в релизную ветку и в девелоп. А новые фичи - уже только в девелоп - они пойдут в следующий релиз. После того как релиз произошел, релизная ветка больше не нужна - в мастер можно ее замержить или перед релизом и взять билд с мастер ветки, или даже после релиза, важна не столько дата, сколько коммит.
А бывает что в разработке сразу релиз 1, который в конце недели выйдет, релиз 2, который планируется на следующий месяц и релиз три, который на следующий квартал. И тут без чистоты в ветках будет просто гроб.

Вот есть у нас у PostgreSQL версии 16.* и он же 10.* -- неужели эти ветки 'хранить не нужно'? (Я про картину мира gitflow. Мое собственное мнение - что таки да, не нужно. Те же аргументы, что про main выше, и к ним применимы -- расставляем теги где надо и все)

У вас просто постгрес. А не 100 полунезависимых микросервисов, где для релиза надо еще их как-то между собой синхронизировать, и тут semver не сильно помогает.
Еще раз, проекты бывают разные. Бывает когда проект пишет одна команда, а бывает когда десять. А бывает когда это 5 команд сишников, 2 команды дба, пару команд UI и вообще отдельная команда QA. ИЛи наоборот универсальные команды, которым попадают разные наборы фич или как-то еще делится. И этим всем нужно управлять, чтобы люди не простаивали и не тратили больше времени на бюрократию чем на код.

классический git workflow очень неплох для ентерпрайзов с множественными командами. А постгрес, несморя на свой вклад в ИТ мире, не совсем ентерпрайз компания, им такое не нужно. Бизнес фичи не падают с неба за неделю до релиза, технические джиры имеют хороший приоритет, ибо это в первую очередь технологический продукт. В общем вы не то сравниваете. Сравните да хотя бы такой проект, как "панели настройки виндовс", когда в 11 винде для одного настройки можно найти 3-5 панелей с ней от разных версий, плюс реестр, повершелл и может быть что-то еще.

И он должен быть в майн ветке, поскольку версию 2 нужно отпочковывать уже не от 2.0, а от 2.03 хотфикса, как последнего в этой версии.

Не понял возражения. Вот на стандартной картинке есть приложение версии 0.2 оно у кого-то стоит. И есть приложение/сервис/библиотека версии 1.0, более новое. Оно тоже у кого-то стоит. Одновременно с версией 0.2, Потому что люди, пользующиеся 0.2, еще на 1.0 не смогли переехать.

И тут находится критический баг в версии 0.2. Которого, возможно, в 1.0 уже нет просто потому что соответствующий код уже давно весь переписан.

Мы делаем исправленную версию 0.3, ответвляясь от 0.2. Ставим тег, отгружаем клиенту..

Все хорошо и понятно.

Вот только эта процедура ломает концепцию main-а. Потому что релизного коммита 0.3 на ней нет.

Вот только эта процедура ломает концепцию main-а. Потому что релизного коммита 0.3 на ней нет.

Так я вам повторяю, постгрес - это не ентерпрайз. Это продукт, который продается разным клиентам. А в ентерпрайзе пишется своя система для себя, свой складской учет, свой банкинг. Единственному клиенту. И там поддержка предыдущих версий нужна только пока в релиз не выйдет более новая версия, ну и для отчетности/бюрократических моментов на случай аутсорс разработки и передачи кода.

То есть опять таки, отталкиваемся от релизов.

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

Это очень оптимистичный энтерпрайз. Если он большой и толстый, то может быть и так:

Сборка 2.17 сейчас эксплуатируется с набором конфигурационных параметров версии 13.7

Сегодня будут эту же сборку будут внедрять с набором конфигурационных параметров версии 14.0 (Потом что полнолунье и нужно включить фичу, которую мы для этого дня приготовили пару месяцев назад)

На полном интеграционном тестировании находится сборка 3.11 (полное - все сервисы в сборе максимально близко к эксплуатационной конфигурации)

На частичном интеграционном тестировании находится сборка 4.17 (частичная - вместо внешних сервисов стоят тестовые эмуляторы)

А пишем мы сейчас то, что будет сборкой 5.3

Ну и вот дефект разной степени критичности может может прилететь с любого места в этой цепочке. Т.е. нам может потребоваться чинить любую версию кода из (2.17, 3.11, 4.17), потом вливать этот фикс во все затронуты версии (можем получить 2.18, 3.12, 4.18 в различных сочетаниях) собирать их, пускать тестирование либо совсем заново либо по укороченному пути... И так далее.

В общем, разных "предыдущих" версий по отношению к тому, что мы вот прямо сейчас кодим - может быть небольшая кучка.

То есть опять таки, отталкиваемся от релизов.

Оно в обе стороны влияет в разной степени. Когда выбирают релизный цикл - приходится смотреть, какой вариант получится сделать (и не запутаться), а какой нет.

Сборка 2.17 сейчас эксплуатируется с набором конфигурационных параметров версии 13.7

Вот это для меня непонятно. Конфигурация должна быть совместима, и собственно сборка и версия это одно и тоже?
Никто же не мешает сделать релиз, в котором только конфиги отличаются?

Что по поводу мержа фиксов в разные версии:

Стандартный git flow предполагает, что в продакшене сейчас только одна версия.
Поэтому для мержа нужно просто взять продакшен релиз из main, сделать от него хотфикс ветку, замержить все необходимое туда, зарелизиться и замержить хотфикс назад в main с новой версией.
Параллельно хотфикс надо замержить в девелоп.
Все.
Ну если прямо сейчас идет подготовка к новому релизу, то замержить в его релизную ветку. При этом может быть даже не нужно делать хотфикс для старой ветки, если исправление бага не срочное и оно может просто выйти с этим новым релизом.

Если у вас продукт может стоять в нескольких экземплярах разных версий, то ЕСТЕСТВЕННО нужно хранить релизные ветки для каждой актуально, и тогда main теряет смысл.

То есть мы спорим ни о чем. Я изначально говорил, что flow в первую очередь зависит от ваших релизов.

Зачем это все хранить, менеджить?

Вот именно. Зачем мучать себя мержем чего-то в main и хранить его, когда можно этого не делать?

Как автоматизировать релиз ноты, если в коммитах куча мусора, а не аккуратное JIRA-1000 feature blabla, JIRA-2000 bugfix blabla

По текстам тегов. Которые "толстые". Именно потому что в коммиты постоянно попадает всякий мусор и редактировать их текст не очень удобно, когда ветка успела убежать.

А теги - редактируются легче. Плюс их ставить может совсем другой человек.

классический git workflow очень неплох для ентерпрайзов с множественными командами.

Я не спорю. Мой тезис - что main там достаточно лишний, т.к. ничего слишком полезного не добавляет и скорее запутывает и усложняет.

И да, когда я писал 'Вот есть у нас у PostgreSQL' - я имел в виду, что в индустрии есть, а не то что я к нему отношения имею. Прошу прощения за неудачность выражения мысли.

Sign up to leave a comment.

Articles