109

Я использую гит для своего проекта, работаю один.

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

Но зачем мне создавать ветку релиза если у меня в ветке девелоп уже все готово... Я так понимаю, что мне нужно ее сливать в мастер сразу и помечать тегом и продолжать дальше вести проект в дефелопе.

Но у меня локально есть только ветка девелоп и удалено есть девелоп и мастер...

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

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

Посоветуйте как правильно сделать?

Nick Volynkin
  • 34,094
Sirop4ik
  • 10,954
  • 1
    Чего-то не хватает в ответах? – Nick Volynkin Oct 07 '16 at 18:05
  • 6
    @NickVolynkin нет наоборот очень хороший ответ получился, не знаю как тут это работает, но решил привлечь внимание к вопросу, чтоб увеличить поисковую выдачу. Чтоб те кто будут интересоваться таким же вопросом могли без труда найти ответ. – Sirop4ik Oct 07 '16 at 19:19
  • 1
    спасибо. :) кстати, этот вопрос почти вышел на первое место среди всех ваших. – Nick Volynkin Oct 12 '16 at 17:41
  • Если начинаете внедрять методологию Git Flow - рекомендую презентацию на русском языке: https://medium.com/ruopsdev/git-flow-presentation-b80643390888 – CSRedRat Dec 07 '21 at 20:53

7 Answers7

147

Сначала немного теории, чтобы обосновать практические рекомендации. Надеюсь, заскучать не успеете.

Что вообще происходит и откуда взялись ветки develop и release

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

А для команд, которые

  • немногочисленны, примерно до 10 человек;
  • работают по agile и дробят задачи настолько, чтобы они делались за день-два;
  • используют в основном самую последнюю версию продукта и не должны тащить старые версии;

... git flow попросту не нужен. Он создаёт больше проблем, чем решает.

Как сделать проще

Но зачем мне создавать ветку релиза если у меня в ветке девелоп уже все готово

Правильно! Вам и девелоп-то не нужен.

Для небольших команд и соло-разработки больше подходят «легковесные» модели организации рабочего процесса. Самая популярная называется GitHub Flow, от неё отличаются некоторыми деталями и бóльшей глубиной проработки GitLab Flow и Simple Git workflow (Atlassian).

Суть всех простых моделей рабочего процесса

  1. Есть единственная стабильная (постоянная, долгоживущая) ветка master.
  2. Любая фича или исправление бага делается в отдельной ветке, которая ветвится от master.
  3. Как только фича или багфикс готов, прошёл ревью и тестирование, соответствующая ветка мержится в master. Потом ветка обязательно удаляется, чтобы не копить хлам.

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

Как создавать и называть ветки

Принято начинать название feature-ветки с номера задачи в трекере задач.

git checkout master
git checkout -b 123-featurebranch

Вы же где-то ведёте список задач? Начните, если нет, и вот почему:

  1. Чтобы не держать их в голове, т.к. это ненадёжно и съедает ресурсы мозга
  2. Чтобы вы могли их оценивать, планировать, выбирать приоритеты
  3. Чтобы хранить информацию о багах и способах их воспроизвести.
  4. Тренировка для командной работы; вы наверняка не будете всю жизнь работать соло.
  5. Если проект в опенсорсе, то кто-нибудь придёт и заведёт вам задачу-пожелание или задачу-багрепорт. Или возьмёт вашу задачу и сделает, просто так, даром. Нельзя сделать задачу, которая не описана, верно?

Формулируйте маленькие, атомарные задачи, чтобы работа в ветке шла 1-3 дня, не больше. Это важно для работы соло и критически важно для командной работы.

Локальные ветки желательно тоже пушить на удалённый сервер, это хороший способ не потерять код, когда пролил чай в ноутбук, rm -rf /, пожар, кража, метеорит...

git push -u origin 123-featurebranch:

Как мержить ветки

Есть два основных способа:

  1. Ветку можно замержить вручную, локально. В командной строке это так:

    git checkout master
    git merge --no-ff 123-featurebranch
    git push
    
  2. Если вы используете GitHub, GitLab, Bitbucket — можно открыть пулл/мерж-реквест и потом его замержить. При этом фактически мержатся удалёные ветки, потом вам нужно будет подтянуть себе результат мержа (git pull). Этот способ помогает проводить инспекцию кода в команде и разное автоматизированное тестирование, но если вы работаете один, мерж-реквесты почти не нужны.

Особенности:

  • Мержить ветки нужно через --no-ff, чтобы всегда создавался мерж-коммит. Он поможет вам просматривать историю, он помогает найти ветку, в которой был сделан коммит, и точно обозначает место, где эту ветку замержили, его можно отменить с помощью git revert. Любите мерж-коммиты, они вам пригодятся.
  • Не нужно мержить в master то, что не готово, не доделано и т.п. Ветка master священна, в ней всегда должен быть рабочий код.
  • Никогда не нужно мержить ветку master в ветку фичи. Исключения — подтягивание кода из мажорного релиза в долгоживущую ветку, разные ветки для разных тестовых окружений и прочие ситуации, которые почти не встречаются при соло-разработке небольшого проекта.

Релиз

Когда вы готовы сделать релиз, просто возьмите нужный мерж-коммит и повесьте на него тег. Используйте аннотированные (annotated) теги. В них сохраняется дата и автор, как в коммите. Таким образом сохранится информация о том, кто именно и когда принял решение о выпуске релиза.

git tag -a v1.0 -m "Version 1.0"

Чтобы запушить теги на удалённый сервер, делайте так:

git push --follow-tags

Параметр --follow-tags нужен для того, чтобы запушить только аннотированные теги и не пушить легковесные (lightweight), если они у вас вдруг есть.

Не отмечайте релизными тегами коммиты в feature-ветках. Замержили, протестировали результат, отметили тегом полученный мерж-коммит. Всё, что не в master, не может быть релизом.

Для создания номеров версий используйте семантическое версионирование.

Выпускайте релизы как можно чаще

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

Но постарайтесь собрать группу бета-тестеров (начните с себя), для которых вы будете выпускать приложение после каждого мержа ветки в master. Таким образом вы ускорите получение обратной связи, а чем быстрее цикл ОС, тем быстрее развивается ваше приложение и ваши навыки. В этом суть Agile.

Практика

С учётом вышесказанного, предлагаю такой план действий.

  1. Замержить (слить) develop в master.
  2. Повесить на полученный мерж-коммит тег.
  3. Удалить ветку develop и не вспоминать о ней до поры.
RAMe0
  • 688
Nick Volynkin
  • 34,094
  • 13
    Хороший ответ. Если проект делается в одиночку, то я бы еще упростил. Держать постояной только ветку мастер. Работаете над фичей - сделали бранч (локально), все закончили, потестили - мержим в мастер, пушим на сервер. Релиз - делаем тег на мастере, пушим на удаленный сервер. – hardsky Oct 04 '16 at 18:06
  • 2
    @hardsky я вроде бы именно это и имел в виду, и точно так и писал. Если в каком-то месте выглядит не так — ткните пальцем, я перепишу )) – Nick Volynkin Oct 04 '16 at 18:07
  • 1
    А в целом за ответ спасибо! Я вроде так и сделал... Только я сначала создал ветку у себя локально от удаленного мастера git checout -b master origin/master потом на ветку девелоп сделал коммит и повесил таг и слил эту локальную девелоп в локальный мастер. Потом сделал пуш и тагу и ветке мастер. И в итоге удалил локальный мастер... Я уже немного привык когда у меня локально дев ветка и от нее я делаю ветки фичи а удалено мастер и дев... В удаленый мастер я сливаю локальный мастер для сохранения... – Sirop4ik Oct 04 '16 at 18:09
  • 1
    @AlekseyTimoshchenko точно создавали свою ветку master так? Может, при клонировании она сама создалась? – Nick Volynkin Oct 04 '16 at 18:16
  • 1
    @AlekseyTimoshchenko сейчас какие-то уточняющие вопросы или затруднения ещё есть? – Nick Volynkin Oct 04 '16 at 18:26
  • Меня смутил пулл-реквест и merge --no-ff ), для одного человека можно ограничиться локальными бранчами. – hardsky Oct 04 '16 at 18:26
  • @hardsky про мерж-реквесты согласен, поменял порядок. Пускай останутся как ответ на вопрос "можно ли мержить удалённые ветки". А про -no-ff — есть много причин, почему мерж-коммиты нужны. Например, замержил fast-forward ветку из N коммитов, потом следом ещё дважды по N. Оказалось, что первый мерж надо отменить. Теперь нужно вспоминать, где границы ветки, а git revert создаст N реверт-коммитов. Бардак! Куда проще заревертить один мерж-коммит. – Nick Volynkin Oct 04 '16 at 18:32
  • @hardsky про локальные и удалённые бранчи: 1) не будет лишним бэкапить код на remote 2) тренировка для командной работы – Nick Volynkin Oct 04 '16 at 18:38
  • Я просто эту ветку когда то удалил и локально оставил себе только дев ветку... так как мастер у меня только для релизов я решил не держать ее локально и все делать в дев а когда релиз готов отправлять его на удаленный мастер... И вот сейчас пришел этот момент)) И родился вопрос... Но сейчас думаю пересмотреть насчет ветки мастер... так как вы тут все говорите что дев не нужен и только мастером лучше пользоваться – Sirop4ik Oct 04 '16 at 18:59
  • @AlekseyTimoshchenko можно переименовать девелоп в мастер ) – Nick Volynkin Oct 04 '16 at 19:01
  • а скажите еще в чем разница отправки тагов на сервер вашим способом git push --follow-tags и моим $ git push origin --tags? – Sirop4ik Oct 05 '16 at 06:53
  • @Виталий, спасибо за правку )) – Nick Volynkin Oct 06 '16 at 15:16
  • никто не подскажет, как интегрировать git в среду AIDE? Нигде не могу найти –  Oct 07 '16 at 14:55
  • @AlekseyTimoshchenko насколько я помню, разница в том, что так отправляются только аннотированные теги. – Nick Volynkin Oct 07 '16 at 14:55
  • @СергейГрушин это можно задать как отдельный вопрос, хороший вопрос будет. Кстати, через командную строку гит недоступен на андроиде? – Nick Volynkin Oct 07 '16 at 14:56
  • врать не буду, не знаю... я вообще пока что разбираюсь с гитхабом. самое интересное что вся практика и разработка происходит в телефоне :) а недавно отметил свое совершеннолетие))) –  Oct 07 '16 at 14:58
  • А можете еще подсказать насчет семантического версионирования... У меня возник вопрос только к первой цифре которая ставиться как мажорная, написано так МАЖОРНУЮ версию меняют, когда сделаны обратно несовместимые изменения API. А как это возможно в случае с android? На моей практике такое было только когда меняли camera API на camera2API которая поддерживается начиная с lollipop. Но это настолько редко бывают подобные ситуации... Получается что первая цифра +/- никогда не собирается меняться? Или не так? – Sirop4ik Oct 07 '16 at 19:27
  • @AlekseyTimoshchenko рассматривайте это просто как очень большие изменения. Например, с нуля переписали половину приложения, поменяли дизайн. Например, ОС Android в данный момент в шестой мажорной версии. Представьте, сколько человекочасов там вложено в среднем в каждую версию. – Nick Volynkin Oct 08 '16 at 09:38
  • @AlekseyTimoshchenko дополнил про аннотированные теги и --follow-tags – Nick Volynkin Oct 09 '16 at 12:20
  • -1 за абсолютно не аргументированную теорию по применению git-flow. Я его использую как в одиночку, так и в маленьких командах и никаких проблем он не создаёт. – ixSci Oct 12 '16 at 05:24
  • @ixSci ура, конструктивная критика! Согласен, аргументов не хватает. Но у вас-то достаточно знаний и навыков для работы, а новичку сложно сразу осваивать не только гит, но ещё и git-flow. Ок, я подумаю, как написать лучше. – Nick Volynkin Oct 12 '16 at 06:00
  • Новичку лучше вообще меньше использовать готовых скриптов, а делать тот же git flow самостоятельно, чтобы понимать самостоятельно. Плюс, чем раньше он познакомится с разными методологиями, тем проще ему будет дальше(в командах или самому). Т.е. с моей точки зрения, нет ничего плохого, если новичок сразу начнёт учиться тому, как работают большие проекты. И не очень большие тоже. – ixSci Oct 12 '16 at 06:17
  • Не будет ли правильнее мерджить заменить на объединить или слить? И зачем двоеточние при push? – αλεχολυτ Oct 12 '16 at 14:01
  • @alexolut я долгое время использовал в ответах перевод "слияние". Однако, такой перевод встречается нечасто, а в устной речи почти все говорят "мерж". – Nick Volynkin Oct 12 '16 at 17:38
  • @alexolut а двоеточие здесь необязательно, но вообще это синтаксис push что:куда – Nick Volynkin Oct 12 '16 at 17:39
26

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

Можно и так.

Я просто не уверен, что эта концепция правильная

Она одновременно может быть правильной, и не подходящей конкретно вашему проекту.

я не уверен, что можно делать мерж на удаленных ветках...

Нельзя. Вы синхронизируете локальные ветки с удаленными (fetch/pull), мержите, и синхронизируете удаленные с локальными (push). На самом деле даже ветка origin/master тоже является локальной.

Посоветуйте как правильно сделать?

IT - такая интересная область, в которой множество правильных ответов.

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

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

  • 1
    Кстати, плюс за упоминание о том, что ветка origin/master тоже локальная. ) – Nick Volynkin Oct 09 '16 at 18:10
  • @NickVolynkin: Я бы не согласился, что она локальная. Ветка удалённая. Но мы работаем с ней локально: pull - скопировать удалённую ветку локально. Мержим или вносим изменения локально. push - копируем данные обратно сервер. На самом деле origin/master это информация о том, на какой коммит ветка master указывает указывает на удалённом сервере origin. Когда мы делаем push мы просто обновляем указатель origin/master данными из локального указателя master – Eugen Konkov Dec 07 '20 at 11:42
  • @EugenKonkov, тут вопрос в том, на каком уровне абстракции мы рассматриваем этот вопрос. Высокоуровневый (основной) интерфейс git рассматривает их как удаленные, а низкоуровневый - как локальные. – Герман Борисов Dec 14 '20 at 07:43
17

1 создать rc ветку
2 смержить с вашей dev
3 вылить rc ветку

Так делается для того, что в случае креша можно было спокойно переключиться на предыдущую стабильную ветку, пофиксить новую rc ветку и опять зарелизить. Удалять ветки крайне не рекомендую. На практике часто приходиться доставать изменения в других ветках. Но если у вас веток перевалило за N и вы в них уже путаетесь, тогда можно почистить и только локально (git branch -d <ветка>)

  • 1
    Есть несколько вопросов: 1) что значит "вылить ветку"? 2) даже уже замерженные нельзя удалять? 3) на сервере вообще никогда не удалять? – Nick Volynkin Oct 08 '16 at 14:18
  • 1
    Что касается креша — это если мерж не удастся? Есть же reflog, всегда можно из него восстановиться. – Nick Volynkin Oct 08 '16 at 14:19
  • 1
  • вылить означает сделать git pull на проде.
  • Да, представьте ситуацию вы разрабатывали модуль1 в ветке r1 сделали ~50 коммитов. А модуль2 в r2 тоже N коммитов. Смержили. Удалили r1 (полностью на сервере и локально git push origin :the_remote_branch). И вдруг ветка поломалась или модуль2 не нужен. Короче требуется восстановить только rc1. И начинается поиск коммита по хешу, а коммитов непонятно сколько. Но это не предел, представьте ситуацию когда вы помержились потом сделали доработку в rc1 потом в rc2 опять помержились. В этой ситуации ветку искать очень сложно.
  • – Kostiantyn Okhotnyk Oct 08 '16 at 14:37
  • 1
    Рефлог покажет последний коммит. Представьте вы вылили r3которая состоит из 2 веток. Это около 50 коммитов. Появился креш. Что легче сделать git checkout стабильная-ветка или искать хеш коммита и откатывать изменения – Kostiantyn Okhotnyk Oct 08 '16 at 16:50
  • 1
    Так же креш может возникнуть не сразу, после патча, который последует и тогда вообще сложно будет сразу вычислить коммит. Поэтому крайне необходимо делать стабильныве ветки – Kostiantyn Okhotnyk Oct 08 '16 at 17:18
  • Если мерж был с мерж-коммитом, то не составляет труда понять, какой ветке принадлежал тот или иной коммит. Кстати, в ситуации И вдруг ветка поломалась или модуль2 не нужен. Короче требуется восстановить только rc1 вы что будете делать, мержить с нуля и переписывать master или делать git revert? – Nick Volynkin Oct 09 '16 at 12:24
  • Появился креш. Что легче сделать git checkout стабильная-ветка или искать хеш коммита и откатывать изменения - правильно ли я понимаю, что вы храните все релизные ветки, чтобы в случае чего откатиться к предыдущей стабильной версии? А что если отмечать релизный коммит тегом? На него тоже можно git checkout – Nick Volynkin Oct 09 '16 at 12:29
  • И ещё вопрос: 1 создать rc ветку 2 смержить с вашей dev. А от какой ветки нужно создавать rc-ветку? От прошлой rc, от мастера? Вы не подумайте только, что это сарказм или я просто так докапываюсь. Мне действительно интересно, как у вас рабочий процесс устроен, тем более что вы, похоже, с сайтами работаете, а я совсем с другими категориями ПО. – Nick Volynkin Oct 09 '16 at 12:31
  • да, работаю с сайтом, поэтому возможно процессы немного разные. В кратце расскажу как у нас построен процесс. 1 задача 1 ветка. Потом все ветки сливаются в одну rc_версия ветку. И эта ветка идёт на прод. – Kostiantyn Okhotnyk Oct 09 '16 at 19:32
  • На проде git push запрещён. И все ветки хранятся в гите. Иногда производится чистка гита (приблизительно раз в 3 месяца), тоесть старые ветки удаляются из гита полностью (не локально а полностью), но релизные хранятся. – Kostiantyn Okhotnyk Oct 09 '16 at 19:36
  • 1 если поломалась ветка то тут 2 варианта: знаем поломалась после чего - тогда git revert, не знаем - если веток которые сливаются мало - тогда git cherry-pick каждой ветки, если много тогда уже дебажить и смотреть анотации и мержить по новой. – Kostiantyn Okhotnyk Oct 09 '16 at 19:44
  • А от какой ветки нужно создавать rc-ветку? Система такая у вас есть предыдущая rc_1, вы откалываетесь от rc_1 -> rc_2 и все новые ветки сливаются в rc_2. Скажу, что минус такого подхода возникает при мерже, когда таски остались с предыдущего спринта, а нужно мержить с новой веткой, что приводит к тому что разработчик забывает делать, в результате проблемы с мержем. По поводу git tag это вариант хороший, но тут могут быть тоже проблемы. Откатились на проде, пофиксили, залили. Тут возникает человеческий фактор мержа с коммитом там где был креш (чем больше команда чем шансов больше) – Kostiantyn Okhotnyk Oct 09 '16 at 19:59