Комментарии 36
Увидев в очередной раз базворд GitFlow я психанул и решил перевести описание более простой и менее проблемной схемы работы с ветками под названием GitHub Flow. Именно её имеет смысл использовать по умолчанию, переходя к какой-то другой лишь в случае непреодолимых обстоятельств.
GitHub Flow, так же как и другие виды бранч менеджмента могут решить, а могут и не решить задач конкретной команды. Стоит подбирать метод под свои задачи, а не под веление современности. Не люблю смотреть на вопрос однобоко - наверно это и была цель статьи.
Все равно начинать изучать вопрос стоит сначала, в дальнейшем я хочу рассмотреть GitHubFlow, как один из современных подходов, а так же опишу свои мысли на эту тему.
В любом случае спасибо за активность и отзыв о проделанной работе!!!
Благодарю!!!
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, да еще и с картинками из старых статей?
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' - я имел в виду, что в индустрии есть, а не то что я к нему отношения имею. Прошу прощения за неудачность выражения мысли.
GitFlow процесс