Pull to refresh

Comments 177

Мне кажется, что большинство людей используют сильно упрощенную версию git flow, а ля «ну короче, для каждой фичи делаем ветку».
UFO just landed and posted this here
UFO just landed and posted this here

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

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

В вашем trunk-based development хотфикс сделать невозможно. Кто-то уже вмерджил еще что-то в мастер. Релизы ломающие обратную совместимость превращаются в русскую рулетку. Откатить нельзя, захотфиксить нельзя, остается только собирать из мастера и молиться что так ничего нового проблемного не вмерджено.
Ну и это нормально работает. Если какую-то фичу делать долго, то еще надо добавить в процесс регулярный rebase этой ветки на свежий мастер.
А это накладные расходы, т.к. CI фактически нет.
И расписание мержей веток перед релизом, т.к. всем нужно успеть…
Я не говорю, что это однозначно плохо — сам такую модель внедрял. Но поддерживать ее трудозатратно, т.е. теоретически есть резерв повышения эффективности. Но практического решения пока не нашел.

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

UFO just landed and posted this here
Понятно зачем: чтобы при merge не возникало конфликтов.

В идеале merge с конфликтами вообще не должен случаться.

В принципе. Никтогда. Потому что это значит что вы меняете код во время слияния, а значит в ветку вливается, как бы, совершенно не протестированный код.

Иногда, конечно, если изменения небольшие — можно на это «забить», но если что-то нетривиальное правится — лучше сделать rebase и протестировать всё ещё раз.
UFO just landed and posted this here
Как «обратный мёрдж» решает проблему мусорных коммитов, в которых непонятно что, непонятно как, и непонятно зачем делается?

Он решает проблему вливания непротестированного кода.

Потому что это значит что вы меняете код во время слияния, а значит в ветку вливается, как бы, совершенно не протестированный код
Мержите сначала себе в ветку, фиксите конфликты, проверяете, коммите мерж, а потом мержите в девелоп/мастер протестированный код без конфликтов
И как и в какой момент из истории, при этом, исчезают сделанные вами бессмысленные изменения, которые оказались ненужными?
Зачем, чтобы с этим репозиторием можно было хоть как-то работать.
С ним можно прекрасно работать без любого ребейза
Ну если под работать это что-то типа «посчитать число строк, написанных Васей» (чтобы ему на этом основании зарплату платить) — тогда да.

Но мне казалось что CVS, так-то, для другого существуют.
В момент комита фикса конфликта.
Он вполне себе фиксирует «удаление» этих бессмысленных/ненужных изменений
Интересно как это работат. Как вы какой-нибудь банальный git bisect собираетесь делать, когда у вас в репозитории бардак и половина косситов тесты не проходят?
UFO just landed and posted this here
Какая разница? Вы либо хотите понимать какой из небольших коммитов привёл к той или иной беде, либо нет.

В первом случае git flow бесполезен. Во втором — он не нужен.
UFO just landed and posted this here
Если я хочу найти в своей ветке — то она вообще не относится к гитфлоу. В своей ветки каждый делает что хочет и как хочет. Вплоть до использования другого VCS.
Это понятно.

Если ветка на нескольких разрабов — то я хочу понимать сначала чей мерж сломал и потом передать проблему ему.
Этот подход предполагает, что этот человек захочет разбираться с проблемой и что он всё про неё помнит.

Для этого все эти ветки вообще не нужны, достаточно делать squash и вливать новые фичи как один большой commit.

Ну а дальше — пусть разбирается как хочет, это уже его дело…
Как вы какой-нибудь банальный git bisect собираетесь делать, когда у вас в репозитории бардак и половина косситов тесты не проходят?
Искать только по мержам в девелоп.
То есть вся история разработки хранится, но никак не используется?

Зачем она тогда вам нужна?

Делайте squash и вливайтесь вместо хранения мусора в репе.

Будет хотя бы честно.

Можно подумать, конфликты при ребейзе исправлять приятнее.

Конечно приятнее. Конфликты при rebase исправляет человек, который этот код написал и всё про него знает.

Конфликты при merge часто приходится исправлять человеку, который код не писал и про него мало что понимает.

Особенно это важно, когда у вас разрабатывается одновременно несколько разных релизов (для разных продуктов, рынков, etc) — а ведь git flow позиционируется подходящим вот именно для таких вот случаев…

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


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

Я привык, что разработчик перед тем как отдать PR на мердж, должен втянуть актуальные изменения.
Какие именно «актуальные измения»? Актуальные изменения Samsung? Или актуальные изменения LG? А может актуальные изменения ARC++?

Только делается это один раз на мердж (а не на каждый отребейзенный коммит) и с возможностью в любой момент откатить неудачный мердж и сделать заново
То есть вы упрощаете работу для разрабочика за счёт усложнения её для всех остальных. Если у вас есть только одна актальная ветка и вопросы «пойдёт эта фича в релиз или не пойдёт» у вас не встают — это, в принципе, и нормально.

Но только если проект большой и сложный (хотя бы уровня GCC или ядра Linux) — это не работает. Если у вас фичи могут годами быть в разработке без окончательного решения о том — будут они, в конечном итоге, интегрированы в проект или нет, то идея хранить всё «историю вопроса» и все опробованные и отвергнутые идеи… кажется безумием.

Чтобы история более компактно выглядела без тысяч ненужных мердж-веток. Мало интересно в истории знать КОГДА именно коммит случился. Более полезно видеть сгруппированные коммиты один за одним начинающиеся от мастер-ветки и замердженные в неё же.

UFO just landed and posted this here
Почему не мерж свежего мастера в ветку?
Этот подход допустим если вы в принципе допускаете появление в репозитории бесмысленных (непротестированных и отревьюенных) изменений.

И это, как мне кажется, принципиальная разница. Либо вы искользуете Git так, как его использование задумывал Линус (все измнения отревьюены и имеют смысл), либо используете его как Mercurial (всё что вы натворили — это история и мы не хотим её потерять)… но тогда зачем Git? Mercurial тоже вполне себе существует…

На мой взгляд ребейз применим только для неопубликованных (незапушенных) изменений.
Очень характерный пример: для вас опубликованные изменения ничем не отличаются от «запушенных»… но ведь это не обязательно так.

У Линуса — это точно не так.
И это, как мне кажется, принципиальная разница. Либо вы искользуете Git так, как его использование задумывал Линус (все измнения отревьюены и имеют смысл), либо используете его как Mercurial (всё что вы натворили — это история и мы не хотим её потерять)… но тогда зачем Git? Mercurial тоже вполне себе существует…

золотые слова! Странно, что не все это понимают. И, да, меркуриал совершенно не плох и такое ощущение, что в него порог входа ниже, чем в гит

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

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

ну, я лично одобряю force push в ветку задачи, но зачем он нужен — если при вливании в мастер все равно все сквошнется. Главное, чтобы от этой ветки задачи никто не почковался.

Если сквошить, зачем тогда вообще история нужна, как с ней работать?
По задаче был произведен рефакторинг, после которого было внесено добавление новой функциональности, из-за которого сломалась другая функциональность. В первом коммите изменено 1000 строк, во втором 10. Искать нужные 10 строк среди 1000 сложнее, чем просто проанализировать их, когда они отдельно.
Другой пример, нужно сделать изменения, аналогичные сделанным ранее по другой задаче. Но по этой задаче еще 2 коммита было сделано. Выискивать там нужные изменения сложнее, чем просто взять отдельный коммит и сделать по аналогии.

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

Так они и реализуют функционал целиком, просто в разных коммитах это разный функционал, который объединяется условиями задачи.

Ну да, я вот коммиты делаю каждый раз когда вижу, что все вроде как работает. Штук по 3-5 в час.

Вроде "работает" или "еще не окончательно сломалось" ?


/прошу прощения за легкий троллинг/

Совершенно верно, но в этом тоже может быть смысл. Если у вас изменений в проекте немного, работает вы с ним тоже просматривая всё глазками, всякими «излишествами» типа git bisect не пользуетесь — то хранить вот всё это добро может оказаться и неплохим вариантом.

Git — это инструмент для ручного создания летописи проекта… а все эти *flow — это попытки превратить шуруповёрт в молоток.

Если вы хотите иметь в репозитории не написанную руками историю, а вот именно «всё как оно реально происходило» — для этого нужен Mercurial.

Этот подход допустим если вы в принципе допускаете появление в репозитории бесмысленных (непротестированных и отревьюенных) изменений.

Но ведь состояние файлов будет одно и то же и после мержа и после ребейза. Мерж сам по себе не влияет на летопись проекта. Я бы сказал, он наоборот вносит ясность.

Разумеется если вы не занимаетесь написанием истории, то в истории будет мусор.

Точно также, как если вы не чистите код, то мусор будет в кода.

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

Разумеется там появляется копи-паста, что замечает ревьюер. Поступает предложение — сделать сначала рефакторинг и вынести вспомогательный код в отдельный класс, а потом добавить конвертор «в другую сторону».

В случае если вы сделаете мёрдж у вас в истории неизбежно возникнет состояние, где есть этот скопированный код. В случае если вы сделаете rebase — вы можете его из истории просто исключить.

Да, если у вас в команде три человека — это неважно, разберётесь как-нибудь.

Но в этом случае вообще всё неважно — люди к командах в три человека отлично и без всяких VCS справляются, пересылая друг другу .zip файлы.

А вот если у вас людей много, фич тоже много и изменения происходят «по всему фронту» (собственно пример — ядро Линукса с которого начался Git в приниципе), то это может снизить размер истории на порядки (то есть в десять раз и более).

Я не очень понял этот пример и разницу с rebase.


есть класс A
вы сделали отдельную ветку по задаче
сделали класс B, похожий на A (коммит 1)
отправили pull-request (потенциальный мерж)


ревьюер вам говорит, сначала вынесем код из A в CBase, потом добавим класс B


вы откатили у себя локально коммит 1
сделали класс CBase, вынесли код из A (коммит 2)
сделали класс B (коммит 3)
сделали force push в ветку на сервере
отправили pull-request (потенциальный мерж)


Вместо отката коммита может быть произвольный интерактивный rebase внутри ветки.
Коммита с копипастой нет, merge есть, rebase на свежий master не нужен. Merge удалению коммита из истории не мешает.


Если же не откатывать коммит 1, а просто сделать следующий, то да, в истории останется скопированный код. Он там будет и при merge и при rebase вместо merge. Если его надо удалить, непонятно, зачем это делать путем rebase на свежий master, отказываясь от merge, если можно сделать rebase внутри ветки.

Если его надо удалить, непонятно, зачем это делать путем rebase на свежий master, отказываясь от merge, если можно сделать rebase внутри ветки.
Вопрос когда и как делать rebase — он немного философский. И вот тот факт, чтобы тут тут вы сравниваете два варианта rebase, а не rebase и merge — тоже.

Тот факт, что без rebase бы не избавитесь от грязи — очевиден. А вот уже когда и как его делать — это не так важно.

Он там будет и при merge и при rebase вместо merge.
Речь не шла о командах Git. Я, например, git rebase вообще очень редко использую — предпочитаю делать git cherry-pick, поскольку это позволяет мне более аккуратно выбирать какие измнение за каким следует. «Логически» — это всё равно rebase.
И вот тот факт, чтобы тут тут вы сравниваете два варианта rebase, а не rebase и merge — тоже.

Потому что merge возможен в обоих случаях, merge и rebase это не взаимоисключающие понятия.


Речь не шла о командах Git.
«Логически» — это всё равно rebase.

Я и не говорил про команды Git. TortoiseGit интерактивный rebase тоже через cherry-pick делает.
Речь о том, что вы приводите некие аргументы, почему не надо использовать merge, но для этих аргументов отказываться от merge не нужно.

Речь о том, что вы приводите некие аргументы, почему не надо использовать merge, но для этих аргументов отказываться от merge не нужно
Где я это написал, извините? Я не говорю о том, что merge не нужен — это тоже инструмент. И Линус, кстати, подробно описывает, когда rebase неуместен и лучше использовать merge (грубо: после каждого rebase нужно всё заново аккуратно протестировать… если вы этого сделать не можете, по той или иной причине — лучше использовать merge).

Ну собственно если бы merge никогда не был бы нужен — его бы в Git и не было.

Я говорю о том, что всевозможные flow, в принципе не предусматривающие использование rebase — превращают Git в плохое подобие Mercurial.

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


И также:
— Понятно зачем: чтобы при merge не возникало конфликтов.


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


По вашей ссылке тоже про это написано:
Many projects require that branches in pull requests be based on the current trunk so that no merge commits appear in the history. The kernel is not such a project; any rebasing of branches to avoid merges will, most likely, lead to trouble.

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

Давайте начнём с конца: зачем вы делаете merge мастера в вашу ветку? Если не для разрешения конфликтов — то это бессмысленно: фикс поверх изменений в мастере отлично «встанет» без всяких «обратных merge» и так. Если же конфликты таки есть (особенно если они есть из-за того, что для ваших целей чего-то там на master поменяли) — то стоит сделать regards, чтобы «причесать историю».

По вашей ссылке тоже про это написано:
Ну дык. Марксизмом-ленинизмом («наука», которая к концу СССР превратилась в умение оправдать цитатами из Маркса и Ленина что угодно) вы овладели.

Посмотрите лучше сюда:
When a patch series must move to a new base, pick a stable point (such as one of the -rc releases) to move to.
Во-первых — что такое «patch series», во-вторых — почему вдруг она «must move» и, главное, узнайте что такое " -rc release" и как часто они выходят?
зачем вы делаете merge мастера в вашу ветку? Если не для разрешения конфликтов — то это бессмысленно
фикс поверх изменений в мастере отлично «встанет» и так

Верно.
Если под выражением "фикс поверх изменений" вы подразумеваете rebase, то он здесь низачем не нужен, merge-коммит тоже отлично встанет. Или какие тогда проблемы он решает?


для ваших целей чего-то там на master поменяли
чтобы «причесать историю»

Почему кто-то для моих целей меняет что-то в мастере, а не в ветке задачи?
Если же там изменения по другой задаче, которые по каким-то причинам пересекаются с моими, то мне причесывать историю нет необходимости, она и так уже причесана по максимуму интерактивным rebase внутри ветки. Надо сделать merge мастера и протестировать только его, а не все предыдущие коммиты ветки.


умение оправдать цитатами что угодно

Почему цитата про метод избегание конфликтов не является подтверждением аргументов про метод избегания конфликтов? В цитате не аналогия и не описание другой ситуации, а именно то, о чем идет речь. Это не что угодно, а именно то, для чего эта цитата вообще может быть использована как пруф.


Посмотрите лучше сюда

Там этот пункт начинается словами "If you must reparent a repositorу", а мы говорим о причинах это сделать.


А в предыдущем пункте написано "Just being on a newer base or avoiding a merge with an upstream repository is not generally a good reason". То есть в большинстве случаев надо делать merge.


Я согласен, что бывают случаи, когда лучше сделать rebase на новые изменения, но это редкие случаи, и это не должно быть основным решением.

Почему кто-то для моих целей меняет что-то в мастере, а не в ветке задачи?
Потому что, предствьте себе, мир не вертится вокруг вашей задачи. И то что может быть полезно вам — может быть полезно кому-то ещё.

Простейший пример: предположим, что в вашей библиотеке Widget'ов было изначально всё сделано так, что цвета задаются при их создании — и больше никогда не меняются.

А в ваше задаче — потребовалось их поменять.

Понятно, что потребуется целый механизм, который «разошлёт сообщения» всем кнопочками, заставить их отрисоваться и так далее.

И он, строго говоря, к вашей задаче никакого отношения не имеет — так зачем ему в вашей ветке разрабатываться?

Почему цитата про метод избегание конфликтов не является подтверждением аргументов про метод избегания конфликтов?
Потому что она выдрана из контекста.

Я согласен, что бывают случаи, когда лучше сделать rebase на новые изменения, но это редкие случаи, и это не должно быть основным решением.
Вот только разработчики Git'а считают иначе…

То есть в большинстве случаев надо делать merge.
Слушайте — вы вообще документ читали или только искали там цитаты для подтвержения вашей точки зрения? Вот это вот:
While merges from downstream are common and unremarkable, merges from other trees tend to be a red flag when it comes time to push a branch upstream.
Или вот это:
One of the most frequent causes of merge-related trouble is when a maintainer merges with the upstream in order to resolve merge conflicts before sending a pull request. Again, this temptation is easy enough to understand, but it should absolutely be avoided.
Это вот — вообще про ваш случай, который вы считаете нормальным и естествнным.

Там вообще половина документа посвящена объяснению того, почему предлагаемые вами merge (из мастера в ветку) — это не просто плохо, а очень, очень, ОЧЕНЬ плохо.

А все цитаты, которые вы, вроде как нашли, в подтверждение ваших идей — это о merge из ветки в мастер (что как раз вполне нормально: если у вас вливаются в мастер сотни и тысячи коммитов в день, то у вас просто нет шансов без них обойтись).
особенно если они есть из-за того, что для ваших целей чего-то там на master поменяли
Потому что, представьте себе, мир не вертится вокруг вашей задачи
И он, строго говоря, к вашей задаче никакого отношения не имеет — так зачем ему в вашей ветке разрабатываться?

Строго говоря, тогда на master поменяли не для моих целей. Именно из-за того, что мир не вертится вокруг моей задачи и к моей задаче это отношения не имеет. Поменяли для неких общих целей, я именно об этом и сказал.


А все цитаты, которые вы, вроде как нашли, в подтверждение ваших идей — это о merge из ветки в мастер

Про первую цитату согласен, я неправильно ее понял. А во второй явно написано "a merge with an upstream repository".


Вот только разработчики Git'а считают иначе…

Разработчики Git'а и их проекты и есть редкий случай. Фичи в проектах такого уровня, которые тянутся годами, сами являются проектами со своим мастером, даже если их главная ветка называется по-другому. Мержи мастеров конечно могут требовать особого подхода. И ниже еще одна причина.


Или вот это

И там дальше объясняется почему. "Linus is adamant that he would much rather see merge conflicts than unnecessary back merges". Это субъективная причина, а не объективная. То, что ему удобнее делать так, не означает, всем должно быть удобнее делать так же. Тем более при использовании всякой автоматики для тестирования и развертывания.


И далее еще "So what should a maintainer do when there is a conflict between their subsystem branch and the mainline? For especially difficult conflicts, create and push a separate branch to show how you would resolve things." Это примерно то же самое, только вручную — есть merge-коммит мастера и ветки, который не в мастере.

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

Разработчики Git'а и их проекты и есть редкий случай.
Насчёт их редкости можно спорить (да, чисто по количеству их очевидно меньше, но так как, в отличие от продектов-однодневок над ними работают сотни-тысячи людей годами, то их влияние несравнимо выше), но это и неважно: я уже много раз повторял в этой ветке, что если у вас три человека работают, то разводить и обсуждать какое-либо «flow» бессмысленно. На малых масштабах и zip-файлы работают без всяких VCS.

Тем более при использовании всякой автоматики для тестирования и развертывания.
Вот как раз «всякая автоматика для тестирования и развёртывания» и превращает правило «back-merges нежелательны» в требование. Вот тут описаны проблемы с git push, вот тут — видно, что вам могут попросту не дать права на back merge.

И так далее. Back merge рассмативаются как крайняя мера не потому что так левая пятка Линуса захотела.
На малых масштабах и zip-файлы работают без всяких VCS

Кроме малых и больших масштабов есть средние, которых большинство. Там нужны VCS, но не нужны правила, специализированные для больших масштабов. Потому что ситуаций таких нет. И говорить, что не применять на них эти правила неправильно — неправильно.


Вот тут описаны проблемы с git push

Насколько я понял, там описаны пожелания Линуса к сообщениям в мерж-коммитах.


вот тут — видно, что вам могут попросту не дать права на back merge

Разговор был о том, делать ли back merge тем, у кого есть права. Если прав нет, то и обсуждать это нет смысла. То, что у кого-то Gerrit настроен так, не является основанием для того, чтобы в других проектах, где Gerrit вообще может не быть, считать back merge неправильным действием.

Разговор был о том, делать ли back merge тем, у кого есть права.
Разговор был о том, стоит ли вообще их делать. Уже тот факт что такие права в принципе могут оказаться недостуными — говорит о многом. Например о том, что это действие считается опасным — иначе было бы бессмысленно иметь отдельные подобные права.

Кроме малых и больших масштабов есть средние, которых большинство.
Вы так уверенно об этом говорите, как будто у вас есть статистика. Не поделитесь?

И говорить, что не применять на них эти правила неправильно — неправильно.
Почему нет? Если есть подход, который отлично работает на больших проектах (собственно на больших проектах никакие другие подходы и не работают… во всяком случае я таких проектов не видел) и вполне себе применим для проекта с одним контрибьютором — то зачем, вдруг, от него отказываться в какой-то момент, а потом возвращаться? Не проще всегда использовать одни и те же принципы?

Или вы где-то знаете о существовании средних проектов, про которые точно известно, что они никогда не станут большими?

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

Cтоит ли вообще их делать тем, у кого есть права. Если прав их делать нет, то делать их бессмысленно, они останутся только на локальной машине разработчика. И проблем от них не будет.


Вы так уверенно об этом говорите, как будто у вас есть статистика. Не поделитесь?

Так это логично же) Проектов много, больших проектов единицы, для маленьких VCS не нужна. "Много" минус "единицы" получается "большинство".
И на личном опыте основано. Во всех проектах, где я работал, была нужна VCS, но нигде обратный мерж не привел бы к проблемам.


Почему нет?

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

Git — это универсальный инструмент. Да, с git flow он превращается в молоток, а с условным github / gitlab / linux flow — в шуруповёрт. Но чем это плохо-то?

Git — это универсальный инструмент.
К сожалению нет. Если ваша задача — хранить всю историю о том что и когда конкретный Вася сделал — то для этого Git плохо предназанчен. Даже с использованием Git Flow и прочего.

Под это Mercurial изначально затачивался.
> Если ваша задача — хранить всю историю о том что и когда конкретный Вася сделал — то для этого Git плохо предназанчен

Почему?

Не хранит в какой ветке был сделан коммит.

Кстати, с удовольствием использовал бы Mercurial, вот только Гитхаб его не поддерживает. И Bitbucket больше его не поддерживает. В общем, не так уж много вариантов mercurial-хостинга, особенно бесплатных. Так что без Git'а никак. И хотя hg неплохо справляется с git-сабрепами, использовать разные VCS в проекте не очень-то удобно, уж проще использовать лишь git, но по своему усмотрению :-)

Поверх гитлаба сделала heptapod или как-то так

На это могу ответить цитатой из статьи/перевода
Каждая модель ветвления подходит для соответствующих команд, культур и условий. Сторонникам CD подходит модель, максимально упрощающая процесс. Кто-то обожает разработку на основе trunk'ов (trunk-based development) и переключатели функциональности (feature flags).

В CD патчи не нужны — там новые релизы.
И в зрелой CD организации каждый коммит в транк обеспечивается ту же предсказуемость и стабильность, что мерж фиче-ветки в Вашем случае.
В целом, у статьи только название провокационное, а так она вполне себе описывает зону применимости git flow:
Если ваша компания придерживается месячного или квартального цикла выпуска ПО, а команда параллельно работает над несколькими релизами, то Git-flow может стать неплохим выбором.

И заметим, никаких альтернатив в этом сценарии не предлагается.
А было бы интересно…
Ну в идеальном мире любой коммит в транк его не ломает и не приносит багов.
В реальном мире бывает всякое. Тест на это всякое пишется конечно, но после этого всякого.

Реально работающая альтернатива это релизится из фиче веток. Мерджим в мастер только после релиза. У нее есть свои проблемы, но в общем схема рабочая. Сайдэффектов минимум. Очередь на релизы выглядит очень забавно.
UFO just landed and posted this here

На мой вкус ветка удобнее. Ее проще найти, более стандартно выглядит, проще продолжить если надо хотфиксить. Первый и второй хотфиксы делаются одинаково. Не надо думать тег или ветка?


Хотя в общем тоже самое. Дело вкуса.

Если релизы каждый день, то вешать тэги руками будет несколько неудобно. Автоматике значительно удобнее деплоить из релизной ветки по автодетекту ченжей

Затем, что в коробочном софте так и есть. Условная убунта — у тебя в параллель идут ветки 14, 16, 18 версий, т.к. к ним ко всем делают багфиксы на всем протяжении жизни версии.
История с тегами хороша, но она более именно про конкретные релизы.

> В вашем trunk-based development хотфикс сделать невозможно

Возможно: напр. Google и Facebook сидят на trunk-driven development, хот-фиксы вполне себе делаются.
И вы готовы рассказать из первых рук как это работает? Напишите статью, интересно же.

Обычная ситуация:
В мастер постоянно идут мерджи. Выкатили релиз с критичной ошибкой и без обратной совместимости. И что дальше? Фиксим в мастере, быстро катим по пути зацепив все что туда намерджили и молимся. Заодно код ревью игнорируется. Просто некогда, пожар тушим.
Или как?
Фиксим в мастере, быстро катим и молимся. Или как?
Фиксим в мастере, дальше cherry-pick в релизные ветки. Если сильно всё разъехалось — делается два отдельных фикса. Если совсем плохо — закрываем мастер, чиним релиз (но это раз в пару лет бывает).
Вот тут я примерно минуты с 7 по 16 в общих чертах рассказываю, как работает в фейсбуке. Очень много подробностей там опущено, т.к. тема доклада не совсем об этом, но все же должно дать общее представление.

Еще вот тут общее описание, как сайт фейсбука релизится.

> Фиксим в мастере, быстро катим по пути зацепив все что туда намерджили и молимся. Заодно код ревью игнорируется.

В целом, чтоб релиз с критичной ошибкой дошел до 100% публики, должно много плохих событий наложиться. Понятие «зацепили все, что намержили» не очень тут применимо, особенно для сайта, где нет вообще бранчей (в случае релиза мобильных приложений несколько сложнее). Да, вместе с хотфиксом пойдет новая порция изменений, но она бы и без хотфикса прошла бы, раз релиз автоматический.

Очень верное замечание насчёт сайта. Я все хочу сказать, что в моем мироощущении существует два принципиально разных подхода к разработке. Первый — это коробочный софт. По этому пути идут операционные системы, утилиты и все, что предоставляется большому количеству клиентов. И в параллель может существовать несколько версий. И второе — это SaaS сервисы, сайты, которые существует в единственном инстансе, в виде единственной возможно крайней текущей версии

Причём, в коробочном софте вполне нормально выкатить релиз, и отдать его на финальное тестирование перед публикацией, в вебе же — выкатка релиза это и есть публикация, причём сразу для всех. Естественно, что опасность бага во второй ситуации намного выше — пользователи даже не могут откатиться на старую версию. Даже в случае CD для софта — можно выкатывать для публичного доступа новые версии в автоматическом режиме, но обновляться или подождать — пользователь решит сам, и если что — может откатиться.
Спасибо.
Понятно. Выкатываете понемногу, хороший вариант последней проверки для ваших масштабов. Небось есть кнопочка «выключить все железо что на новой версии работает» как совсем последний предохранитель.

Пока фиксили баг прилетели новые фичи. Понятно что оно в прод уйдет, но нам-то сейчас хочется спасти горящий прод, а не новые фичи катить.
Пока фиксили баг прилетели новые фичи. Понятно что оно в прод уйдет, но нам-то сейчас хочется спасти горящий прод, а не новые фичи катить.

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

Пока фиксили баг прилетели новые фичи. Понятно что оно в прод уйдет, но нам-то сейчас хочется спасти горящий прод, а не новые фичи катить.
И ведь фичи даже не оттестированы и вместо того, чтобы пофиксить существующий билд — мы заливаем ещё пригоршню сырых фичей.
В гугле прод деплоится не напрямую из мастера: сначала head должен собраться, потом на этой же сборке гоняют автотесты в изоляции, потом смотрят как оно дружит с другими сервисами, потом выпускают понемногу в прод. Инстансов очень много, так что можно свежую сборку запустить на пару машин и посмотреть что она не крашится и соседей не валит. Если head не собирается, или где-то релиз заело то это повод все бросить и чинить. Ну и есть два способа чинить: часто можно просто откатить плохой коммит, и тогда head соберётся, тесты пройдут и станет хорошо. Или да, черрипикать в релизный бранч и форспушить, и молиться что не сделаешь ещё хуже.

Позвольте поинтересоваться — и сколько времени занимает полный цикл? Ну, вот — тесты прошли, но продакшн сгорел в огне. Надо срочно багфиксить. Наши действия? Ждать, понятно, не можем. Или в Гугле настолько качественный код, что такого не бывает? Но тогда же получается, что они и не могут фичи катить мгновенно. Имеем типичный паттерн, что фичи релмзятся спустя неделю. Или больше

Я не гугл, но но вот в этой ситуции


продакшн сгорел в огне. Надо срочно багфиксить

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

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


https://en.wikipedia.org/wiki/Knight_Capital_Group
https://blog.cloudflare.com/how-verizon-and-a-bgp-optimizer-knocked-large-parts-of-the-internet-offline-today/
а потом следом и сам клаудфлейр
https://www.ciodive.com/news/cloudflare-outage-highlights-the-internets-fragility/558142/


Только не надо говорить, что инфра — это не софт и не подчиняется тем же закономерностям ) IaC, DevOps — во весь рост.

Миграции не роллбечатся"

Я ждал этого замечания :)


Стараемся делать backward-compatible миграции. Это нужно даже безотносительно к факапам. При роллинг-деплое или при сине-зеленом одна и та же база будет обслуживать старую и новую версию приложения.


Ну а если раз в год такой пожар, что надо обязательно потушить, а откатить нельзя, то можно и спец процедуру применить. Сделать хотфикс от стабильного коммита, а не верхушки мастера. И сделать/выкатить билд из этого коммита.


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

к сожалению, это не всегда возможно. Скажем, миграции не роллбечатся.

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


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


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

Иногда откат невозможен. Стейт пересчитали, обновили. Старая версия с новым стейтом не готова работать. Выше написали про постепенную выатку. Когда много серверов можно на немного выкатить и посмотреть. Если что не так просто погасить все что на новой версии.
Старая версия с новым стейтом не готова работать.

Ну так надо писать так, чтобы была готова. В чем проблема?

Это не всегда возможно ) Мир чуточку более сложен, чем "черное и белое".
ОКей. Возможно, что фраза "не всегда возможно" слишком резка, давайте ее заменим на то, что "писать так, чтобы была готова" может быть слишком дорого и, например, стейкхолдеры не готовы за это платить. Так ок ?

Так ок ?

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

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

То есть Гугл живет на классическом гит флоу. Немного адаптированным, но не суть. Есть релизная ветка в которой можно что-то срочно починить.

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

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

А если на препроде находится что-то критическое, то тэг не идёт в продакшен?

Ага, исправляем, увеличиваем patch number (1.1.1 -> 1.1.2), тегируем, выкатываем на препрод, и все по-новой.

Релиз без обратной совместимости — это серьезная ошибка. Если у вас нет обратной совместимости, то у вас нет blue/green, ну и реверта проблемного релиза нет.
У нас решение проблемы тушения пожара делается очередью намерживания в мастер. Т.е. релиз цикл — "мерж от текущей позиции в очереди — деплой — пауза на поиск пожара — очередь следующему". Но наличие обратной совместимости хотя бы на несколько часов (по регламенту — 24 часа) является обязательной.

А как вы разрешаете ситуацию, когда, например, в новом релизе заезжает новая таблица или набор полей в существующую и в эти 24 часа в нее вносятся данные? Блокируете в данном релизе работу с таблицей, пока релиз не будет утвержден или при откате сохраняете данные не выполняя компенсирующей миграции или просто дроп новых данных?
Т.е. кейс именно с теми данными, для которых не было модели в предыдущем релизе.

А новые данные, новые колонки, новые таблицы — никак не мешают работать старому коду. Т.е. мы просто не трогаем эти данные. Возможную неконсистентность связанную с тем, что новые данные перестанут писаться после отката решить обычно не сложно — ну как то планировалось их изначальное появление в базе ;)


А вот удаление или изменение логики — это проблема. Поэтому мы внушаем мысль, что если хочется поменять смысл данных в колонке, переименовать колонку и т.п. — не делай этого, а просто создай новую, а старую удалишь через день, или же, как исключение, учи код работать с обеими схемами данных — новой и старой.


С ddl у нас все проще, ибо там все изменения проводит эксплуатация. Т.е. альтерится все много раньше связанного релиза и тут очевидно, что можно альтерять, а что нет.


С изменением смысла или формата данных тут сложнее, например, разработчик может выкатить код, сохраняющий ключи в новом формате, от чего старый код стал бы падать. Такое было, но буквально раз или два за несколько лет. Тут, имхо, нам помогает то, что сам разработчик проводит релиз своего кода по упрощённой blue-green, т.е. он ясно видит, что несколько минут будет работать и его новый код и старый — это настраивает его думать о возможных проблемах.

Все ли сложные фичи поделить на маленькие тестируемые куски? Наверно правильные ответ такой же как и с паралельной обработкой задачи, где-то можно где-то нет. Если нет точной технической спеки где всё уже описано и нужно только накодить, да и даже со спекой не всегда сработает, если нужно поменять модель данных, а потом поменять и добавить куски кода которые с ней работали/будут работать получается что рабочего кода не будет до тех пор пока всё старое не исправлено, а ведь ещё тесты есть.
Вот так и получается что если фича ещё и сложная которую нужно основательно протестировать то на неё уйдёт несколько недель и живя в отдельном бранче, а не в общем то за эти недели остальная команда накодит столько что хрен вмержишся.
Сам подход в принципе интересен, но хорошо он работал только в фирме где всё покрыто тестами и изменения модели данных минимальные, то-есть в основном идёт добавление новых, но там пострадала сама модель данных и в итоге куча хаков, от разваливания конечно хорошо помогают тесты, но о итеративном рефакторинге даже речь не идёт, проще с нуля написать.

Версионирование и хотфиксы от версии в TBD никто не отменял, не вводите людей в заблуждение

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


git flow как раз показывает, на что подписываются.


Кому-то проще сказать "у нас нет стабильной версии, у нас head и ci/cd". И это живёт ровно до тех пор, пока нет separation of concern. Как только возникает, кому-то становится важнее иметь то, что работает, а не то, что удобно разрабочику сопровождать.

Как только возникает, кому-то становится важнее иметь то, что работает, а не то, что удобно разрабочику сопровождать.
Если они готовы за это платить — то почему бы и нет?

К сожалению огромное количество бизнесов жаждут сидеть на старых версиях, а платить за разработу — как за «у нас head и ci/cd»… И «серебрянной пули» тут нет: либо вы убеждаете их платить за то, что они хотят получить, либо объясняете им что за эти деньги поддержки кучи устаревших версий они не получат.

К сожалению в головах у подавляющего большинства бизнесменов «модель автопарка»: ясно же, что покупать раз в год 10% машин дешевле, чем ежегодно заменять весь автопарк? Ну так и с софтом будет так же!

Причём та же «модель автопарка» показывает почему это не так: в случае с софтом «поставки новых машин» ничего не стоят — а вот ремонт старых… это и есть основные траты. Впрочем и «детские боляки новых моделей» тоже бывают — всё равно как и с автомобилиями… за исключением нулевых затрат на «капиталку».

Но думать на два шага оказывается уже слишком сложно для многих…

… я несколько удивлён, что мыслительный процесс бизнесменов так резко обесценен. Эти люди хорошо умеют считать деньги. И если им выгоднее игнорировать существание проблемы, то они её игнорируют. Не потому, что они глупые, а потому, что умные.


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


… Сравните с такси, у которого сломаны ремни безопасности. Оно деньги зарабатывает? Зарабатывает. И если бы бизнесу было разрешено эксплуатировать машины с сломанными ремнями, они бы их эксплуатировали.


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

Не потому, что они глупые, а потому, что умные.
Они, конечно, умные, но особенно умны они тогда, кому-то можно заплатить рубль, а получить работы на десять.

Да, конечно — если вы на это подписались, то вина не в бизнесменах, а вас.

Если вы не чините сервер с CVE, из-за которой утекают данные клиентов, то этот сервер продолжает зарабатывать.
До того момента, пока там не пропишется криптолокер и он это делать перестанет.

Вам до этого, в любом случае, дела нету — если вы не подписывались на поддержку старых версий и денег за это не получали… то вас просто не должны волновать проблемы бизнеса. Вот и всё, собственно.

Всё верно. Только вот это называется словом не "умные", а "му$аки".


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

Кому-то проще сказать "у нас нет стабильной версии, у нас head и ci/cd". И это живёт ровно до тех пор, пока нет separation of concern

Тогда у нас половина индустрии в этом состоянии ))))

За всеми этими элементами необходимо следить, держать их в уме, учитывать в процессе сборки и выпуска.

Знаю, что полетят камни, но за меня думает Sourcetree в котором Gitflow удобно реализуется в GUI и наглядно представлен.
В терминалах не работал с гитом уже не помню сколько лет)

камень от меня за SourceTree, а не за GitFlow, т.к. это разные вещи.

В смысле? кнопочка GitFlow в SourceTree это не гитфлоу?

SourceTree испортился пару лет назад — глючит, не находит что-то, меню неактивные, хотя должны быть. А лет 5 назад был топ!

Думал что он на Electron и как-то не смотрел раньше. Но оказалось, что это не так.
А вот цена — «Free, $49.99 soon».
Пока что оба бесплатные, но пока.
По поводу изменений в интерфейсе, могли бы конечно сделать галочку для тех, кому старый вариант больше нравился. Мне новый нравится больше, хотя я редко вообще пользуюсь UI клиентами и мне это особо не актуально. Да на экран помещается меньше, но выглядит более читаемо. Я не чтобы поспорить. Это чисто вкусовщина.

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


Они увеличили размеры, чтобы впихнуть иконки со статусом своих пайплайнов, которыми не пользуется большинство пользователей. Могли бы сделать маленькие иконки.

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

Всё на самом деле очень просто и наглядно (хотя, конечно, возможны варианты):
1. есть только 2 главных бранча, живущих всегда: условные девелоп и мастер. С девелопа деплой идёт на тестовый сервер, с мастера на прод
2. все остальные бранчи очень временные, они рождены, чтобы умереть
3. ребейзы никто не отменял, более того, они постоянно нужны, именно через них слияние бранчей и должно работать, потом в родительском бранче чётко видно кто где насрал откуда какой коммит приехал и из-за чего у нас лёг прод
4. при закрытии обычного бранча он заливается только в девелоп, а хотфикс-бранчи льются одновременно и в девелоп, и в мастер
5. релиз-бранчи — это по сути перенос коммитов с девелопа в мастер

при закрытии обычного бранча он заливается только в девелоп, а хотфикс-бранчи льются одновременно и в девелоп, и в мастер

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

От масштабов всё зависит. Одно дело — когда у вас возгорание, которое одним огнетушителем гасится. А другое дело — когда у вас скважина горит или лесной пожар на тысячу квадратных километров.

Когда речь идёт о больших масштабах может несколько дней на планирование уйти. А то можно и людей потерять и пожар не потушить.

То же самое и с хотфиксами. В точности.
От масштабов всё зависит.

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

Посмотрите на ядро Linux: сотни людей, которые что-то пилят, масса разных flow в разных подсистемах (кому что удобнее), но релиз собирается ровно одним человеком, так как конкретно ему удобно… и ничего — работает.

Так что для комманд в пару десятков человек особо и думать не нужно: написали что-то в документ, ознакомили всех — и вперёд и с песней.

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

То есть где-то от тысячи разработчиков и больше.
Если у вас всегда хотфиксы без хотя бы минимальной проверки уходят сразу в прод — то у вас уже всё плохо.
Минимальная проверка делается, но на полноценное тестирование время не тратится.
p.s. Мне казалось это очевидным.

У нас хотфикс мержится в мастер, ставится тег, билдится Докер образ и идёт деплой на препрод, где тестируется. Если все ок, то тот же образ идёт на прод. Если нет, то новый хотфикс. Некоторые теги до продаж никогда не доезжают.

3. ребейзы никто не отменял, более того, они постоянно нужны, именно через них слияние бранчей и должно работать, потом в родительском бранче чётко видно кто где насрал откуда какой коммит приехал и из-за чего у нас лёг прод
Знаете — если у вас «лёг прод» и вам нужно разбираться в том, кто, что и куда «насрал», то вы точно что-то напутали в ваших flow.

Прод должен ложиться только из-за внешних причин, когда вы чего-то не учли в постановке задачи. Но никак не от того, что кто-то куда-то «насрал».

Работаем по гит-флоу с одним продакшеном, но иногда с подготовкой нескольких релизов в фоне. У меня основные вопросы к релиз-бранчам. Вроде понятно их назначение: не останавливать мержи в девелоп (читай — активную разработку) пока релиз готовится, но почему-то очень многие считают, что фиксы в релизную ветку попадают в девелоп только после релиза, через мастер. И какой-то баг может неделями висеть в девелоп. Ну и конфликты при мерже мастера в девелоп неизбежны. И хорошо, если можно всех причастных собрать вместе на их разрешение

Работать с гитом чисто в консоли немножко мазохизм, имхо.

ИМХО. Поэтому спорить смысла нет — это вкусовщина.
Мне для 80% работы графический клиент не нужен, вполне удобно, правда использую кучу алиасов.
После перехода на Fish shell свой вариант, но основанный на этом.
github.com/ohmyzsh/ohmyzsh/tree/master/plugins/git
Как у нас:
Год-полтора назад мы отказались от develop. Вместо нее у нас живут 1..N релизных веток. Чаще всего это именно фичи-ветки, но бывает, что в один релиз входит несколько фич, если они мелкие. Но чаще всего одна фича содержит достаточно много кода, поэтому мы бьем ее на мелкие куски (задачи).

От релиза почкуется ветка задачи, как только задача готова (по разработке), создается PR в релиз и задача переходит к тестировщикам. Разработчик не ждет завершения тестирования, он берет следующую задачу из фичи (почкуется от предыдущей), по завершении создается PR в ветку предыдущей задачи. Если тестирование опаздывает, то может возникнуть «пирамида» задач и PR к ним.

Тестирование всегда работает с задачей, PR с которой идет в релиз. Правка багов всегда идет в ветке задачи. Как только тестирование завершено, тестировщик вливает задачу в релиз. Теперь в релиз «смотрит» PR следующей задачи. Тестировщик делает «обратный» merge (если были правки багов), чтобы актуализировать ветку новой задачи и берет в тестирование следующую задачу.

Как только все задачи по фичи влиты в релиз, идет установка релиза на тестовый комплекс + полная проверка фичи/фич. После чего лелиз вливается в master и удаляется.

у нас две команды работают в одном репозитории: гитфлоу — это меньшее из проблем.
точнее, это вообще не проблема. и никакой сложности там нет. картинка — да, сложная, но она не отвечает реальной картине. все на самом деле проще гораздо. автор (картинки) из тех, кто не смог просто объяснить.
а вот теперь вопрос: какие есть варианты вместо гитфлоу? такие же простые и универсальные.

Gitlab flow пытаюсь внедрить.

UFO just landed and posted this here
Тот факт, что гуи для гита продолжают множится — как раз показатель что проблема растет. Только ее решают совершенно неправильным способом. И тем самым проблема никуда не девается. И тем самым ее продолжают пытаться решить все новыми гуя-ми для гита.

Правильно говорите.


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

А не перебор ли это? Не является ли гит тем самым универсальным элементом? Или думаете, что гит — это всего лишь маленький кирпичик? Но тогда прошу привести примеры, как его можно хорошо встроить в пайпы, т.к. в интернетах обычно пишут либо какие-то базовые вещи (как пользоваться git commit & git rebase, но это уже общее место), либо нытье или рассуждения по поводу того, что гит флоу — чего-то не то

UFO just landed and posted this here
То же самое должно быть с гитом. Названия веток, должны быть шаблонизированы. Ребейс в таких ветках запрещен, в таких — разрешен. Эти ветки принадлежат одним, эти ветки — другим. Эта ветка — бранч от такой-то. Значит и мержить ее можно только в оригинальную или ее потомков.

Согласен. Но проблема отчасти закрывается комбайнами типа GitLab — там все указанное есть и коробки, но с нюансом, что на машине разработчика может быть любой беспредел

UFO just landed and posted this here

Почему бедный? Потому что дух растет из авторства — линуксового бардака :)

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

UFO just landed and posted this here

Ну вот подход github flow практически такую необходимость исключает: фиче и фикс бранчи от мастера и в него же мержи, в никакую другую ветку мержить не требуется специально автору фичи/фикса или релиз инженеру. Остальные просто в рабочем порядке подтягивают мастер в ветки своих задач.

UFO just landed and posted this here

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

UFO just landed and posted this here
UFO just landed and posted this here

Флоу как раз можно отнести к недостаткам инструмента. У сотни команд нейминг без рабора, блин.


И не hg единственным, есть fossil хотя бы. Недовольство самим гитом я бы выразил так — слишком запутанный и сложный, и при этом одновременно слишком тупой для ряда нужных вещей (именно архитектурно).

UFO just landed and posted this here
С Git-flow придется забыть о rebase'ах

Далее читать нет смысла. Автор критики с гитом по-ходу не дружит и ничего сложнее git commit не понимает.

Слишком резко осуждаете ) Действительно, можно критику уничтожить таким аргументом, но от этого git flow, к сожалению, лучше не становится. Эта методика, к сожалению, не натягивается на все возможные концепты. И если она сложна (ментально, а так оно и есть), то проблема точно не в людях, которые пытаются ей следовать. Инструменты должны быть простыми и страховать людей от ошибок, а не наоборот. Опять же — жаль, но гит этому не способствует

Можно было заканчивать на "Git-flow изначально сложна и запутана": сложна в сравнении с чем? запутана для кого?

Я не могу ответить на этот вопрос

Вот ответ из статьи на все подобные вопросы.
А что там упрощать? Моя команда, когда-то, поняла суть за 5 минут объяснений включая джунов. Пользуемся много лет кастомизированным, потому что не получается сделать удобным для всех механизм когда не все из того что готовится к релизу может в этот релиз войти. Некоторые локальные тонкости.

Если разумно построить процессы — пользоваться можно. На самом деле сама схема достаточно проста и, главное, логична. Минусы, конечно есть. Но на свои задачи я ничего лучше пока не нашел. Будет интересно если кто-то предложит альтернативные варианты. Подписался.

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

Расскажите, пожалуйста, что за волшебная кастомизация? Я так и не смог придумать адекватного решения аналогичной проблемы.

Я бы рассказал если бы оно было адекватным… Пока — есть два дополнительных PreReleaseCandidat и ReleaseCandidat в дополнение к Release. Что есть ужасъ, адъ и скрежет зубовный™. Но руки не доходят сесть и хорошо подумать. Все что можно автоматизировал, все привыкли, вроде «и так хорошо». Вот статья стала стимулом, наконец. Может дадут ссылок в комментариях на «новые тенденции» в данной области.

Если (когда) сделаю что-то в этой области, чем не стыдно поделиться — напишу обязательно.

GitLab flow смотрели? Из популярных мне он кажется самым адекватным ситуации, когда фича или фикс в норме проходит несколько стадий тестирования, типа develop->stage->preprod->prod

Смотрел, но так давно и поверхностно, что можно сказать не смотрел. Спасибо, обращу внимание.
Если упростить, то сейчас у нас так — каждая фича в отдельной, простите, фиче. Затем они последовательно по некоторому алгоритму опускаются в preRC, далее в RC и когда уже точно пойдет в релиз — попадает в релиз. После деплоя релиз мерджится в мастер. Т.е. в мастере всегда лежит то, что на данный момент крутится на проде. В релизе всегда то, что уйдет в прод следующим. Разработка в мастере и релизах не ведется. Попадание в релизные ветки только через пуллреквесты из фич. Никаких исправлений прямо там. Хотфиксы бывают так редко, что можно считать их форсмажором. После деплоя релиза все обновляют свои фичи из нового мастера.

Ветка develop, вследствие нашей специфики, практически вообще не используется. Зато там есть все.

Поэтому все новые фичи начинаются с бранча от мастера. Т.е. взял мастер, отпочковал от него фичу, пилишь, двигаешь к релизу. Ну такой сильно-сильно кастомизированный gitflow. Работать позволяет, но… не красиво как-то. Поэтому как руки дойдут буду думать.

Основные инструменты — tfs (devops) + teamcity + много мелочей. Нам более чем хватает.
Поэтому все новые фичи начинаются с бранча от мастера. Т.е. взял мастер, отпочковал от него фичу, пилишь, двигаешь к релизу.

Если ничего не упустил, вы сейчас описали gitlab flow :)


P.S. Хотя нет, там фича мержится в мастер сразу после окончания основной работы над ней, а продакшену соотвествует ветка production

А что сложного? Ребятки пилят веб, у них есть мастер-ветка, ветка для жареных фиксиков, пара-тройка веток для команд разработчиков пилящих новые фичи. С каждой значимой ветки коммиты собираются автоматически, прогоняются автотесты для чего есть и по кнопке развёртываются в тестовое окружение, после чего user story/issue/bug в трекере двигается с In progress в Testing и уже тестировщики тычут что всё красиво, работает как надо и полностью соответствует дизайну. И могут прямо на этом же тестовом хосте показывать кастомерам когда готовы какие-то ключевые вещи, чтобы обсудить что ещё стоит добавить, что лучше переделать, а что лучше выкинуть сразу. Это касается как ветки для жареных фиксиков, так и для разрабатываемых фич. И только потом, когда всё хорошо, нужный функционал готов, код мержится в мастер, вот эта оттестированная версия уходит в прод, статус таски меняется на deployed. Стоимость виртуалки для такого тестового сервера — ноль целых фиг десятых на фоне стоимости разработчиков и стоимости исправлений ошибок.
Основное отличие от приведённой картинки — нет отдельного бранча для релизов только ради маркирования релизов и из мастера нужно регулярно забираться, это гораздо проще чем, например, каждый уже оттестированный и поставленный на прод и вмерженный в мастер (как нам и рекомендует гит флоу) хотфикс каждый будет забирать себе в ветку, долго и больно мержиться с каждой другой веткой и всячески сходить с ума.
А чтобы не содрогаться при слове мерж, ПМ следит чтобы функционал у команд в одном спринте максимально не пересекался. Ну и инструмент стоит выбрать может более удобный под себя, если с консолью не сладили, а IDE даёт только какие-то поверхностные вещи.
GitExtension, Meld в качестве merge tool и хинт для открытия комментариев вида #1234 в таск-трекере по клику люто облегчают жизнь. tig вообще прекрасен даже для тех кто консоль не знает.
Какие-то странные бодания с отлично себя зарекомендовавшими практиками на фоне непонимания как правильно построить процесс, чтобы он, как настоящий мощный инструмент, помогал тебе, а не был для галочки

Адепты и противники git-flow ломятся в открытую дверь с разных сторон.

Окей, моей команде Git-flow не подходит. Что нам использовать?

Я не могу ответить на этот вопрос.


Если бы статья начиналась с этой фразы, мы бы сэкономили кучу человекочасов и возможно даже спасли бы пару пингвинов от глобального потепления.
Делал как-то CD pipeline для git-flow. Сам я сторонник простого зеленого мастера и правила «вмерджил — кати», но там были тестировщики, которые не могли делать регресс на каждый чих. Что я из этого вынес:
  • git-flow не отменяет CI/CD. Для каждой ветки: develop, release и master были заведены окружения develop, release и stage и код туда выкатывался по коммиту.
  • Про микросервисы и множественность репозиториев. Каждый микросервис жил в своем репозитории и по комиту выкатывался на develop, release и stage. Когда наступало время что-то выкатывать, вся актуальная версия stage'а катилась в прод. Если какой-то сервис пару месяцев не обновлялся, то просто несколько раз катилась одинаковая версия. Работало все через навешивание тегов на docker образы. Это гарантированно тестировщикам, что в проде именно тот срез версий, который они только что тестировали стейдже.


  • В git-flow нет ничего сложного. Его нужно просто правильно готовить :)

М-м-м, микросервисы. Проблем из-за того, что разработчики вносили несовместимые изменения в микросервисы не было? Как их избегали?
P.s. поясню, что опыт подсказывает, что половина проблем не техническая, а организационного характера.


В git-flow нет ничего сложного. Его нужно просто правильно готовить :)

Не только. Но и — не пытаться его применять, там, где он очевидно не подходит.

Проблем из-за того, что разработчики вносили несовместимые изменения в микросервисы не было? Как их избегали?

Нет, не было. Была оговорена личная ответственность разработчика за изменения: если он что-то мерджит в develop, он обязуется оперативно исправлять баги при ближайшем релизе, в том числе связанные с интеграцией. Ну и командность работы тоже была, она таки содействовала тому, чтобы разработчики не дрались, а договаривались.
Могу ответить за наш проект:
Проблем из-за того, что разработчики вносили несовместимые изменения в микросервисы не было?

На старте проекта были, потом научились бороться.
Как их избегали?

За последний год полностью всё публичное апи генерируется на основе OPEN-api спек (swagger 3.0, так же пришлось кастомных генераторов написать, ибо стандартный под джаву далеко не всё умеет генерировать, хотя спека вроде как и позволяет это делать), проблема ушла сама собой. Условно репозиторий с апи-спеками один общий на всю систему. Ты завязываешься на product-api v.1.x.x.x и у тебя гарантированно не будет проблем что /api/v1/ вдруг получит потерю обратной совместимости + для всех сервисов генерируются врапперы для вызовов. Да, немного избыточно, но весь код автогенерируется, с точки зрения разработчика нужно написать только yaml со спекой. Если же версия становится v.2.x.x.x просто сборка упадёт, ибо все импорты нужно менять. В этот момент придётся править вызовы апишек и т.д. И да, такой подход заставляет ещё тратить время на проектирование АПИ, перед тем как что-то начинать делать. Оверхэд примерно 10% от общих трудозатрат на задачку. Зато ОЧЕНЬ удобно лиду сформировать совместно с архитекторами апи и отдать на реализацию джуну/мидлу, Который просто не имеет шанса наделать себе в штаны.

Размер приложения: примерно 25 бэкендных микросервисов и около 10 фронтэндов. На фронтах, к сожалению, не генерируем по спекам, ибо оказалось это очень неудобным. Да и в целом, отвал фронтов обычно не является блокером для системы, ибо наши фронты это скорее конфигурационные тулы + парочка бизнесовых.

Спасибо за опыт. Очень интересно. Не подскажете — начиная с какого размера проекта, по-Вашему, имеет смысл заморачиваться на эту автогенерацию контрактов?
Что делаете, когда нужно две апишки — скажем, это публичный интерфейс для интеграций? Реализуете их обе в одном микросервисе или принимаете волевое решение пилить два микросервиса с почти одинаковой функциональностью, но разными версиями апи ?

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

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

Для этих целей мы используем паттерн ESB/SOA. Это вообще отдельный микросервис, который ставится поверх нашего продукта. Так как заказчиков много и у всех разные требования, практически нереально из коробки поддерживать их все. Так что интеграция с внешним миром работает через этот самый микросервис, а под капотом Apache Camel + груви скрипты + небольшая своя поделка для организации EAV-подобной модели поверх рестов. По факту этот слой полностью конфигурируется относительно требований заказчиков и трансформируется внутрь, в наш стабильный апи. Так же есть реализация на GraphQL для заказчиков, которым удобнее с ним работать.

Вот нашли ошибку в релизный ветке. Где её фиксить, надо ли тут же вмерживать в девелоп? На практике с гит-флоу постоянно возникает проблема: релизную ветку вылизали, в мастер вмержили, тег поставили, на прод ушло (у нас ещё препрод сначала, не все теги до прода доезжают), а потом конфликты при мерже мастера в девелоп (если вообще не забыли его сделать). Да и просто баг в девелоп может долго жить, хотя в релизной ветке уже пофиксили.

Могу поддержать статью свои опытом использования git-flow.


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


Во-вторых, исходная модель, хотя и нацелена на поддержание нескольких версий одновременно, ничего не говорит о том, как это делать для нескольких несовместимых версий. В модель должны быть добавлены несколько develop и master (master-1.x, master-2.x, ...), для каждой поддерживаемой версии.


В-третьих, модель в базовом виде создаёт сложности при работе с системами сборки, которые вносят версию в сборку (как, например, Maven сохраняет версию в pom.xml или npm в package.json) в сочетании с требованием QA "мы тестируем конкретный reproducible build", поскольку добавление нового коммита с тэгом генерирует новый билд, который надо заново тестировать.


Какая-то формализация правил для feature и bugfix веток, аналогичная git-flow, разумеется имеет смысл для проектов с большим количеством разработчиков и сложным планом релизов.

В-третьих, модель в базовом виде создаёт сложности при работе с системами сборки, которые вносят версию в сборку (как, например, Maven сохраняет версию в pom.xml или npm в package.json) в сочетании с требованием QA "мы тестируем конкретный reproducible build", поскольку добавление нового коммита с тэгом генерирует новый билд, который надо заново тестировать.

Оченьт здорово, что Вы обратили внимание на этот момент! Странно, что другие его пропустили
P.S. у самого от этого бомбит, но это пока лучшее решение, чем делать как-то по-другому — либо предложите свой подход

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


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

будет необходим способ визуально отслеживать ветви. Чтобы этим не заниматься, придется навсегда забыть о rebase.

что-то я не понял. с flow никогда не было проблем посмотреть на ветку, за то с классической моделью с пул-реквестами — вот уж проблема, особенно если ветка была слита в мастер. считай нет и не было её.

Не понял. Пул-реквесты с git flow несовместимы что ли? Как же мы тогда работаем…

не знаю, не использовали pr с flow. Но суть в том, что я имел ввиду классическую модель.

Пул-реквесты — это уже github/gitlab flow.

То есть мы работаем не по git flow, раз мержим фичи и фиксы в девелоп через пулл-реквесты?

Sign up to leave a comment.