Git workflow для вашего проекта

Коллективная работа над сложным проектом (в декабре мы выпустили первый релиз SkyCover Infrastructure CD-ROM) породила очень много потребностей: надо выпускать релизы, добавлять функционал, делать хотфиксы. Захотелось иметь автоматические nightly-builds…

Казалось бы, для пользователей git и github.com (каковыми мы являемся), эти возможности находятся «на кончиках пальцев» и все должно быть просто. Однако git — лишь инструмент и для достижения хорошего результата требуется следование определенной методологии.

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

Основные ветки

Центральный репозиторий содержит две ветки с бесконечным сроком жизни:

  • origin/master — всегда содержит исходник, готовый к промышленному использованию.
  • origin/develop — в нее добавляются изменения, которые войдут в следующий релиз. Иногда эту ветку называют «integration branch», потому что в ней объединяются изменения разных тематик и от разных разработчиков. Именно из develop делают ночные сборки (nightly builds).

В общем случае, develop — это не место для разработки, а готовый код, который точно войдет в следующий релиз.

Когда develop достигает стабильного состояния, она сливается в master и помечается тэгом номера релиза (git tag) .

Условимся, что изменения, которые в какой-то момент сливаются (мержатся) в master, по определению становятся новым релизом.

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

Вспомогательные ветки

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

Тем не менее, работа с ними подчиняется определенным правилам и можно выделить три типа веток:

  • Feature branches (новые возможности)
  • Release branches (подготовка релиза)
  • Hotfix branches (исправления)

Feature branches — новые возможности

Ответвляется от: develop
Мержится в: develop
Название: любое, кроме master, develop, release-*, или hotfix-*

Ветки новых возможностей (иногда называют «тематические ветки», topic branches) используются для разработки нового функционала. Заранее нельзя сказать, в какой именно релиз войдут эти изменения, поэтому ветка живет до тех пор, пока она не вольется обратно в develop или ее разработка не будет отменена. После этого ветка удаляется.

Тематические ветки обычно находятся в локальных репозиториях разработчиков и не хранятся в origin.

Создание feature branch

$ git checkout -b myfeature develop
Switched to a new branch "myfeature"

Слияние feature branch с develop

$ git checkout develop Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

Флаг --no-ff используется для того чтобы выделить в истории develop участок, относящийся к конкретному слиянию. Сравните:

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

Release branches — ветки релизов

Ответвляется от: develop
Мержится в: develop и master
Название: release-*

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

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

Именно в начале ветки релиза, можно определить новую версию продукта, но не раньше. С этого момента ветка develop станет отражать состояние «следующего релиза», но будет ли это скажем, версия «0.3» или «1.0», и что именно в нее войдет — пока не ясно и станет окончательно ясно только при следующей процедуре релиза.

Создание ветки релиза

Ветки релиза создаются из develop. Например, скажем, версия 1.1.5 — это текущий релиз и мы готовим следующий большой релиз. Состояние develop готово для релиза и мы решили дать ему номер версии 1.2 (а не 1.1.6 или 2.0):

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

bump-version.sh — это некий скрипт для изменения номера версии в файлах релиза. Можете просто подправить руками ;)

Созданная ветка будет существовать в репозитории до момента публикации релиза.

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

А новые функции, напротив, должны сливаться в develop и ждать следующего релиза.

Завершение ветки релиза

Когда релиз готов, он, в первую очередь, сливается в master (помните, мы условились, что это и есть непосредственно релиз).

Далее этому коммиту в master должен быть назначен тэг (git tag) для удобства последующего обращения.

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive. (Summary of changes)
$ git tag -a 1.2

И, наконец, изменения master должны быть слиты обратно в develop, чтобы отразить все исправления, сделанные во время релиза.

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

Это последнее действие может привести к конфликту. В этом случае внесите исправления и выполните коммит.

Теперь все готово и мы можем удалить ненужную ветку релиза:

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

Примечание: Чтобы убрать ветку из удаленного репозитория, например, на github, выполните также:

$ git push origin --delete release-1.2

 

Hotfix branches — исправления

Ответвляется от: master
Мержится в: develop и master
Название: hotfix-*

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

Для этого ветка исправления ответвляется от тэга соответствующего релиза на ветке master. Далее работа над исправлением продолжается в ветке исправления, а разработка продукта идет своим чередом в ветке develop.

Создание ветки исправления

Ветки исправления создаются из master. Например, скажем, версия 1.2 — это текущий релиз и он имеет проблемы. Однако изменения в develop пока что нестабильны. Мы можем создать ветку для исправления:

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

Не забудьте поменять номер версии!

Теперь внесем исправления для решения проблемы:

$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)

Завершаем ветку исправления

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2.1
$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

Тут есть одно исключение: если ветка соответствующего релиза еще существует, то изменения надо сливать в нее, а не в develop.

Наконец, удалим временную ветку:

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).

В завершение

На этом рисунке показана полная картина происходящего.

В высоком разрешении ее можно взять по адресу оригинала http://nvie.com/posts/a-successful-git-branching-model/

Автор оригинала разработал утилиты git-flow для упрощения описанного процесса. Почитать можно здесь http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/
или, в моем пересказе, здесь: Почему вы не используете git-flow?

Разработка

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

captcha

Please enter the CAPTCHA text