Например, программист
4,9
рейтинг
26 октября 2010 в 07:55

Разработка → Удачная модель ветвления для Git перевод

Git*
Перевод статьи Vincent Driessen: A successful Git branching model

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



В качестве инструмента управления версиями всего исходного кода она использует Git.


Почему Git?


За полноценным обсуждением всех достоинств и недостатков Git в сравнении с централизованными системами контроля версий обращайтесь к всемирной сети. Там Вы найдёте достаточное количество споров на эту тему. Лично же я, как разработчик, на данный момент предпочитаю Git всем остальным инструментам. Git реально смог изменить отношение разработчиков к процессам слияния и ветвления. В классическом мире CVS/Subversion, из которого я пришёл, ветвление и слияние обычно считаются опасными («опасайтесь конфликтов слияния, они больно кусаются!»), и потому проводятся как можно реже.

Но с Git эти действия становятся исключительно простыми и дешёвыми, и потому на деле они становятся центральными элементами обычного ежедневного рабочего процесса. Просто сравните: в книгах по CVS/Subversion ветвление и слияние обычно рассматриваются в последних главах (для продвинутых пользователей), в то время как в любой книге про Git они бывают упомянуты уже к третьей главе (основы).

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

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

Децентрализованный, но централизованный


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



Каждый разработчик забирает и публикует изменения (pull & push) в origin. Но, помимо централизованных отношений push-pull, каждый разработчик также может забирать изменения от остальных коллег внутри своей микро-команды. Например, этот способ может быть удобен в ситуации, когда двое или более разработчиков работают вместе над большой новой фичей, но не могут издать незавершённую работу в origin раньше времени. На картинке выше изображены подгруппы Алисы и Боба, Алисы и Дэвида, Клэр и Дэвида.

Технически это реализуется несложно: Алиса создаёт удалённую ветку Git под названием bob, которая указывает на репозиторий Боба, а Боб делает то же самое с её репозиторием.

Главные ветви



Ядро модели разработки не отличается от большинства существующих моделей. Центральный репозиторий содержит две главные ветки, существующие всё время.
  • master
  • develop

Ветвь master создаётся при инициализации репозитория, что должно быть знакомо каждому пользователю Git. Параллельно ей также мы создаём ветку для разработки под названием develop.

Мы считаем ветку origin/master главной. То есть, исходный код в ней должен находиться в состоянии production-ready в любой произвольный момент времени.

Ветвь origin/develop мы считаем главной ветвью для разработки. Хранящийся в ней код в любой момент времени должен содержать самые последние изданные изменения, необходимые для следующего релиза. Эту ветку также можно назвать «интеграционной». Она служит источником для сборки автоматических ночных билдов.

Когда исходный код в ветви разработки (develop) достигает стабильного состояния и готов к релизу, все изменения должны быть определённым способом влиты в главную ветвь (master) и помечены тегом с номером релиза. Ниже мы рассмотрим этот процесс в деталях.

Следовательно, каждый раз, когда изменения вливаются в главную ветвь (master), мы по определению получаем новый релиз. Мы стараемся относиться к этому правилу очень строго, так что, в принципе, мы могли бы использовать хуки Git, чтобы автоматически собирать наши продукты и выкладывать их на рабочие сервера при каждом коммите в главную ветвь (master).

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


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

Мы используем следующие типы ветвей:
  • Ветви функциональностей (Feature branches)
  • Ветви релизов (Release branches)
  • Ветви исправлений (Hotfix branches)

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

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

Ветви функциональностей (feature branches)


Могут порождаться от: develop
Должны вливаться в: develop
Соглашение о наименовании: всё, за исключением master, develop, release-* или hotfix-*

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

Ветви функциональностей (feature branches) обычно существуют в репозиториях разработчиков, но не в главном репозитории (origin).

Создание ветви функциональности (feature branch)

При начале работы над новой функциональностью делается ответвление от ветви разработки (develop).

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


Добавление завершённой функциональности в develop

Завершённая функциональность (фича) вливается обратно в ветвь разработки (develop) и попадает в следующий релиз.

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Отчёт об изменениях)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop


Флаг --no-ff вынуждает Git всегда создавать новый объект коммита при слиянии, даже если слияние может быть осуществлено алгоритмом fast-forward. Это позволяет не терять информацию о том, что ветка существовала, и группирует вместе все внесённые изменения. Сравните:



Во втором случае невозможно увидеть в истории изменений, какие именно объекты коммитов совместно образуют функциональность, — для этого придётся вручную читать все сообщения в коммитах. Отменить функциональность целиком (т.е., группу коммитов) в таком случае невозможно без головной боли, а с флагом --no-ff это делается элементарно.

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

К сожалению, я ещё не нашёл, как можно настроить Git так, чтобы --no-ff было поведением по-умолчанию при слияниях. Но этот способ должен быть реализован.

Ветви релизов (release branches)

Могут порождаться от: develop
Должны вливаться в: develop и master
Соглашение о наименовании: release-*

Ветви релизов (release branches) используются для подготовки к выпуску новых версий продукта. Они позволяют расставить финальные точки над i перед выпуском новой версии. Кроме того, в них можно добавлять минорные исправления, а также подготавливать метаданные для очередного релиза (номер версии, дата сборки и т.д.). Когда вся эта работа выносится в ветвь релизов, главная ветвь разработки (develop) очищается для добавления последующих фич (которые войдут в следующий большой релиз).

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

Очередной релиз получает свой номер версии только в тот момент, когда для него создаётся новая ветвь, но ни в коем случае не раньше. Вплоть до этого момента ветвь разработки содержит изменения для «нового релиза», но пока ветка релиза не отделилась, точно неизвестно, будет ли этот релиз иметь версию 0.3, или 1.0, или какую-то другую. Решение принимается при создании новой ветви релиза и зависит от принятых на проекте правил нумерации версий проекта.

Создание ветви релиза (release branch)

Ветвь релиза создаётся из ветви разработки (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 number). В нашем примере bump-version.sh — это вымышленный скрипт, который изменяет некоторые файлы в рабочей копии, записывая в них новую версию. (Разумеется, эти изменения можно внести и вручную; я просто обращаю Ваше внимание на то, что некоторые файлы изменяются.) Затем мы делаем коммит с указанием новой версии проекта.

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

Закрытие ветви релиза

Когда мы решаем, что ветвь релиза (release branch) окончательно готова для выпуска, нужно проделать несколько действий. В первую очередь ветвь релиза вливается в главную ветвь (напоминаю, каждый коммит в master — это по определению новый релиз). Далее, этот коммит в master должен быть помечен тегом, чтобы в дальнейшем можно было легко обратиться к любой существовавшей версии продукта. И наконец, изменения, сделанные в ветви релиза (release branch), должны быть добавлены обратно в разработку (ветвь develop), чтобы будущие релизы также содержали внесённые исправления багов.

Первые два шага в Git:

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Отчёт об изменениях)
$ git tag -a 1.2


Теперь релиз издан и помечен тегом.

Замечание: при желании, Вы также можете использовать флаги -s или -u <ключ>, чтобы криптографически подписать тег.

Чтобы сохранить изменения и в последующих релизах, мы должны влить эти изменения обратно в разработку. Делаем это так:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Отчёт об изменениях)


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

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

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


Ветви исправлений (hotfix branches)


Могут порождаться от: master
Должны вливаться в: develop и master
Соглашение о наименовании: hotfix-*

Ветви для исправлений (hotfix branches) весьма похожи на ветви релизов (release branches), так как они тоже используются для подготовки новых выпусков продукта, разве лишь незапланированных. Они порождаются необходимостью немедленно исправить нежелательное поведение производственной версии продукта. Когда в производственной версии находится баг, требующий немедленного исправления, из соответствующего данной версии тега главной ветви (master) порождается новая ветвь для работы над исправлением.

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

Создание ветви исправлений (hotfix branch)


Ветви исправлений (hotfix branches) создаются из главной (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(-)


Закрытие ветви исправлений

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

Прежде всего надо обновить главную ветвь (master) и пометить новую версию тегом.

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Отчёт об изменениях)
$ git tag -a 1.2.1


Замечание: при желании, Вы также можете использовать флаги -s или -u <ключ>, чтобы криптографически подписать тэг.

Следующим шагом переносим исправление в ветвь разработки (develop).

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Отчёт об изменениях)


У этого правила есть одно исключение: если в данный момент существует ветвь релиза (release branch), то ветвь исправления (hotfix branch) должна вливаться в неё, а не в ветвь разработки (develop). В этом случае исправления войдут в ветвь разработки вместе со всей ветвью релиза, когда та будет закрыта. (Хотя, если работа в develop требует немедленного исправления бага и не может ждать, пока будет завершено издание текущего релиза, Вы всё же можете влить исправления (bugfix) в ветвь разработки (develop), и это будет вполне безопасно).

И наконец, удаляем временную ветвь:

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


Заключение


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

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

Прим. переводчика: статья не новая, ссылка на оригинал уже появлялась на хабре. Этот перевод — для тех, кому английский ещё даётся не так легко (а также для моих коллег, среди которых я занимаюсь пропагандой, хехе). Для автоматизации описанных в статье процедур автор создал проект gitflow, который можно найти на github.
Перевод: Vincent Driessen
Андрей Хитрин @zloddey
карма
112,0
рейтинг 4,9
Например, программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (104)

  • +1
    Огромное спасибо за труд. Спасибо, что в примечании указали ссылку на хабра-ссылку на оригинал. Интересно, что помешало оформить хабра-переводом?
    Стоит отметить, что предлагаемая модель ветвления подходит не исключительно для Git, но и Mercurial, а скорее всего и большинству распределенных систем контроля версий
    • +1
      Да, модель явно не заточена конкретно под Git, с другими DVCS, скорее всего, проблем не должно возникнуть.

      Не совсем понял насчёт хабра-перевода. При создании топика я указал, что это перевод, и иконка перевода (Z->Я) рядом с названием отображается. Или Вы имели в виду что-то другое? Ткните носом в ссылку, если не трудно.
      • 0
        я например иконку опять не заметил и опять досмотрев до конца увидел что это перевод…
      • +1
        Мои извинения. Картинка из кэша пропала. Ссылку Vincent Driessen не разглядел. Включил картинки, каюсь, горе мне, горе.
        • +1
          Извинения принимаются :) А я ещё было подумал, что хабра-перевод — это какая-то программа или веб-сервис специальный для перевода. Что-то типа translated.by Вот и попросил ссылку на этот случай.
    • +1
      Стоит отметить, что предлагаемая модель ветвления подходит не исключительно для Git, но и Mercurial, а скорее всего и большинству распределенных систем контроля версий

      Если смотреть со стороны управления конфигурациями проекта, то ветвление это средство, а vcs — инструмент. От vcs нужна возможность работы с бранчами, а распределенность не играет большой роли. Просто так получается, что в распределенных управление бранчами реализовано лучше. scm-notes.blogspot.com/2010/09/branch-per-task-workflow-explained.html.
  • +2
    Мне одному кажется, что давно пора перейти от описания удобности технологии к описанию связки технология-инструмент?
    Потому как сама по себе технология ни чего не значит, а удобный инструмент для конкретной технологии уже большой плюс к нему (например, C# — хороший и удобный язык программирования. Но без удобнейшей Visual Studio он бы ни когда не достиг такой популярности, т.к. хороших языков много).
    Это я к чему веду: при описании GIT все работают с командной строкой. Нет, я согласен, что это удобно в определенных случаях, но далеко не всем.

    Опишите наконец инструмент для работы с GIT, скажем TortoiseGit (да, да, под винду), разбавляя это теорией как в данной статье.

    Лично для меня ключевым выбором той или иной технологии стало не ее возможности/продвинутость, а удобство работы.
    • +2
      P.S. спасибо за интересную статью.
      P.S.S. да, я понимаю что это перевод и попрошу автора не принимать высказывание на свой счет ;)
    • +6
      с гитом все работают в командной строке, т.к. для линукса это нативный способ User Interaction, а для винды гит до сих пор собирается через зад^W Cygwin
      • –1
        Да, я понимаю что для продвинутых линукс-пользователей командная строка проблем не составляет.
        Но у многих не столь продвинтых или переходящих возникают проблемы. Да и давно уже прошли времена, когда знание консоли было необходимым условием использования linux.
        • 0
          да я не агитирую за консоль. я сам по большей части виндузятник (дома), но на работе вся работа только в линуксе и 99% в консоли. хочешь не хочешь, а привыкнешь. Но так же можно привыкнуть и к графическим интерфейсам и хорошо себя с ними ощущать. Так что консоль онли — это не мои слова
        • +2
          Git сам по себе просто очень удобно использовать именно через командную строку из-за кучи опций. Под виндой можно использовать cygwin + bash_completion для автодополнения.

          В своей практике я применяю zsh (автодополнение, менюшки, и имя бранча в PS1), через GUI – делаю интерактивный стейджинг (когда надо закоммитить часть файла, а не весь, все забываю соответствующий флаг консольной версии), смотрю визуально дерево бранчей (на вещах типа linux-hnd весьма удобно). Изредка читаю диффы во внешнем редакторе (если много файлов и скроллинга). И очень редко открываю внешний EDITOR для написания коммит-сообщения. Это все под OSX: GitX, Araxis Merge/Kaleidoscope, TextMate.
        • 0
          wuake (консоль, вызывается, как в quake — по win+~) и cygwin — и никаких gui не надо. Обычно людей, перешедших с SVN, в командной строке страшит относительно сложное добавление отдельных файлов и коммит части изменений. В отличии от SVN (и других централизованных систем), где это — достаточно частая операция, в git и mercurial мне это не приходилось делать вообще (в основном, благодаря легкому созданию бранчей), почти всегда делаешь коммит всех изменений с автоматическим добавлением не добавленных файлов (git commit -a -m «message») — и все. Потому очень важно правильно понять саму идею распределенных систем — а это статья объясняет очень хорошо.
          • 0
            Я не против консоли.
            Я против вырабатывания новых привычек в работе, под каждую технологию отдельно.
            При переходе на новый продукт я хочу чтобы было «как в старом, только лучше».
            А в случае с git мне надо фактически заново переучиваться для работы с ним через консоль.

            Поэтому я и говорю: напишите тоже самое, но с примерами как это делать не через консоль, а через TortoiseGit. И тогда множество пользователей TortoiseSVN без проблем воспользуются статьей и поймут в чем удобство git.
            • 0
              Ну, заново переучиваться — это естественно при использовании принципиально отличающейся технологии. Или вы на C# в процедурном стиле пишете?
              • +1
                «Принципиально отличающаяся»?
                90% взаимодействия разработчика с системой контроля версий не различаются ни в Git, ни в SVN — коммит, апдейт, создание веток, слияние веток — у Git и Hg получше с ветками и производительностью, у SVN — с чекаутом репозитория с долгой историей. Они не настолько отличаются по возможностям, чтобы использовать различные программы.

                Воспользуюсь вашей аналогией — для любого программирования в любом стиле на любом языке прекрасно подходят одинаковые текстовые редакторы и даже IDE (Eclipse, например).
                • +4
                  Внешне — разницы почти нет. Идеологически — очень даже есть.

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

                  Если не учесть этого изменения — нет смысла вообще куда либо переходить с SVN.

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

                  Как было сказано выше, одному удобно в Tortoise работать, другому — из Far'а, третьему — вообще из IDE (которых из широкоизвестных минимум три с разными вариантами интеграции) — в сумме минимум пять клиентов, их каждый описывать?
                  • +1
                    Unix-way. Отделение механизма от политики.
                    В данном случае механизм — это консоль и Тортилла, они есть и в СВН и в DVCS, а политика — это «идеология». Так вот, политика не должна затрагивать механизм — пользоваться инструментом должно быть одинаково полноценно и удобно как через консоль, так и через Гуи.
                    Так вот, в СВН оба механизма сбалансированы, а в Гит — еще нет.
                    • +3
                      Еще раз: без знания технологии вопрос «какой инструмент выбрать» вторичен.
                      Т.е. если не знать, как работает SVN — неудобно будет пользоваться как тортиллой, так и командной строкой.

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

                      • 0
                        в командной строке в большинстве случаев почти невозможно

                        что именно невозможно?
                        • 0
                          Удобно работать =)
                          • 0
                            мне вот удобно. Что я делаю не так?
                    • 0
                      * «как работает SVN» — имелось в виду, что такое бранч/тэг/когда это использовать/как происходит процесс слияния/зачем он нужен и т.п., а не детальное знание внутренних механизмов.
              • –2
                Работа с GIT через консоль и TortoiseGit — это 2 принципиально разных подхода.
                Да, при этом по сути TortoiseGit передает все управление консоли.
                Но работать с TortoiseGit у многих проблем не вызывает — это «привычный» подход.

                Кстати, стоит вспомнить, что 1е компиляторы C++ (тогда еще «C with Classes») транслировали сначала в C, а потом компилировали его.

                P.S. на мой взгляд, процедурный и объектный подход представляют по сути одно и тоже. Значительно различаются идеологии подходов, но не их суть. Но это тема отдельного разговора ;)
                • +3
                  Создавать ветку при начале работы над каждой задачей или не создавать — вот два принципиально разных подхода. Набрать «git commit» или ткнуть правой кнопкой мыши в Explorer и выбрать «Commit» — не принципиально.

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

                  И да, статья про идеологию, если что.
          • 0
            >Обычно людей, перешедших с SVN, в командной строке страшит относительно сложное добавление отдельных файлов и коммит части изменений. В отличии от SVN (и других централизованных систем), где это — достаточно частая операция, в git и mercurial мне это не приходилось делать вообще (в основном, благодаря легкому созданию бранчей)

            а можно мысль развить — почему их это пугает? и при чем тут бранчи?

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

            откройте для себя git add -i — из всех изменений даже одного файла можно сформировать несколько отдельных коммитов
      • +1
        поясните мысль… я например пишу код в FAR, коммичу набирая git add <ctrl-enter> <ctrl-enter> <ctrl-enter>
        git commit -s
        открывается редактор фара и там пишу текст комментария к коммиту. для меня это удобно
        • 0
          ок, а в чем неувязка с моими словами? правда у меня гит почему-то не запускается из виндовой консоли, хотя в PATH прописан. надо открыть гитовский шелл и уже оттуда коммитить. может это я что-то не так делаю?
          • 0
            я не вам ответил, извиняюсь :)
          • 0
            гляньте тут habrahabr.ru/blogs/Git/74839/ я описывал основные нюансы работы с git под windows

            и да, у меня в путях есть C:\Program Files\Git\bin\
        • +1
          Как понимаю, комментарий для меня...
          Я не призываю отказаться от консоли вообще.
          Кто-то к ней привык, кому-то она удобней. Такие люди есть и будут. Но тем не менее их мало.
          Для меня лично удобней в IDE правой кнопкой по проекту -> commit.
          Для других — в консоли привычней и удобней.
          Для третьих — в консоли скрипт по автоматической сборке проекта набросали, а сами через GUI работают.

          Для выработки схемы работы с технологией существуют обзорные статьи по этим инструментам.
          Но для популяризации надо все-таки ориентироваться на наиболее широкий круг пользователей.
          • 0
            >Для меня лично удобней в IDE правой кнопкой по проекту -> commit.
            тут же возникает вопрос коммит чего, нескольких новых файлов, текущего файла, или нех которые были исправлены с последнего коммита.
            • 0
              Работая в IDE (или через GUI) я и не задумывался, что это разные вещи. ;)
              Коммит на папке означает «измененные + новые», а по файлу — внесение изменений в конкретном файле или внесение нового фала в репозиторий.
              • 0
                в том то и дело что git вам позволит сделать и так и так, укажете git add. — добавит для коммита все новые изменения, укажете git add — добавит для коммита указанные файлы, мне последний вариант гораздо удобнее, т.к. часто нужно закоммитить не один файл, а все имеющие отношение, к текущему изменению состояния системы.
                • 0
                  Вопрос не в том, чтобы найти аналог в git.
                  Я говорю о том, что видя необходимость работать с консолью, встречая при это кучу разных параметров, многие из которых могут значительно повлиять на процесс выполнения, я вероятнее всего не полезу в справочник по командам и не буду выносить пометки по работе с git на листочки вокруг себя.
                  Вероятнее всего что я просто закрою статью и останусь при инструментах, может не таких продвинутых, но удобных и привычных.
                  Даже если я захочу попробовать нового, непривычность к работе с консолью сводит на нет все желание.
                  Именно поэтому я и делаю акцент не на технологии так таковой, а на средствах работы с ней.
                  • 0
                    Эта статья была так написана её автором, поэтому переводчик вряд ли может помочь.
                    Тем более, что посвящена статья не самому гиту, а ветвлению в гите, следовательно ориентирована на пользователей этой системы, а не новичков, выбирающих инструмент. Описание какого-то GUI привело бы к тому, что большинству пришлось бы мысленно переводить команды меню и прочие действия, специфичные для данного конкретного GUI в параметры командной строки «канонического» git.

                    GUI — вещь часто удобная, даже для меня, и статья по различным «фронтэндам» для git была бы очень полезна IMO.
                • 0
                  хм… только сейчас заметил что парсер отъел часть моего поста…
                  «git add .» добавит все изменённые файлы
                  «git add file1 file2 fileN» добавит для коммита указанные файлы…
      • 0
        Я сижу под линуксом, но пользуюсь git-cola. В консоли с git мне лично неудобно работать.
      • 0
        PHPStorm\ItellyJ IDEA вполне себе хорошо работают из коробки с гитом.
      • 0
        не согласен совершенно. :) если я пью кофе каждое утро, не значит что все пьют кофе каждое утро. так что не надо обобщать.
        Работаю под MacOS X. Я использую git в разработке уже несколько лет. Отлично с повседневными задачами справляется SourceTree, иногда я захожу в консоль что-то сделать, но только иногда.
        Раньше я использовал GitX и пару его форков, тоже не жаловался.
    • +3
      все просто — у гита миллион фронтендов и каждый из них описывать неразумно. достаточно один раз понять какие консольные команды для чего нужны, а потом у фронтенда посмотреть через какую менюшку они вызываются. и всё.
      я использую gitextensions и в ежедневной работе комстроку не трогаю практически — только если нужно что-то нетривиальное или при деплое на сервер.
      • –2
        Я не предлагаю описывать все.
        Тот же C# имеет туеву кучу IDE, инструментов и т.д.
        Я предлагаю описать 1, причем для переходящих с SVN (где на винде популярен TortoiseSVN) удобен будет именно TortoiseGit.
        • +2
          кмк просто описанием кнопок не решить проблему перехода. переходящие должны сначала понять концепцию dvcs, а после этого кнопки выучить будет тривиально.
          • +1
            Согласен, вопрос перехода не решается нажатием кнопок.
            Но и обзорные статьи «повторяй в консоли за мной» тоже не способствуют ни переходу, ни понимании концепции.
            Если поискать «TortoiseGit» здесь, на хабре, то мы ни одной статьи не найдем с ним. А вот комментариев достаточно. Причем половина ответ на «а если не в консоли?», а 2я половниа — «спасибо за совет».
    • 0
      В примечании есть ссылка на gitflow, реализующий данный способ управления проектом. Хотя, согласен, сам gitflow тоже работает через командную строку.

      Для данной модели идеальным вариантом, наверно, был бы плагин для того же TortoiseGit, который поддерживал бы gitflow. Но его пока не существует в природе.

      Кстати, удобство работы — это вопрос индивидуальный. Мне удобно работать с Git через командную строку даже в Windows (открыто окно с git shell). Очень ускоряют процесс автодополнение по табу и возможность делать очередь команд.

      Но получается так, что одни люди стараются не отрывать руки от клавиатуры, а другие от мышки. И в разработке Git явно доминируют первые. :)
    • 0
      Лично для меня достаточно того, чтобы IDE подсвечивала измененные файлы, показывала diff'ы. Ну, иногда коммитить удобнее, чем из консоли. Но все возможные действия перекладывать на плечи IDE бессмысленно.
    • +1
      Не понимаю почему вы считаете, что интерфейс командной строки чем-то плох или не удобен. Ведь именно это и есть основной интерфейс работы с git. Зачем разбирать какой-то графический клиент, если им никто не пользуется? Зачем вообще пользоваться графическим git клиентом. По-моему выгода от того, что вы будете тыкать мышкой, а не набирать команды нулевая.
      • 0
        потому что привычки менять очень тяжко, да и переучиться работать из gui в консоль не всегда хочется.
      • 0
        Лично мне он не удобен и непривычен. Я не говорю за всех. Но многие со мной согласятся.

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

        А если новая будет «как старая, только лучше» — вот на это я согласен.
        • 0
          Здесь ситуация как с ядром. Есть консольный git и его подразумевают по-умолчанию. Если хочется приключений, то используйте графическиую обёртку, но будьте готовы что вас могут не понять, потому что большинству удобен git из консоли. Не думаю что вы чем-то принципиально чем-то отличаетесь от этого большинства.
          Может git — просто не то что вам нужно?
          • +1
            > большинству удобен git из консоли.
            А большинству, которому не удобна консоль просто не перешли на git.
            Вот и получаем что большинство на консоли, потому как кроме консоли ни чего нет или не было в момент когда они переходили (ну или о GUI просто не афишируют).

            Честно, я не считаю что это в пользу git говорит. Потому как популярные инструменты имеют GUI, какими бы они продвинутыми в консоли не были. Лично для меня появился сейчас TortoiseGit, что дает мне возможность «пощупать» и сравнить с SVN.
            Появись статья, подобная этой, но с TortoiseGit вместо консоли — желающих «пощупать» (а затем и перейти на работу с ним) прибавилось бы значительно.
            • 0
              Это прекрасно, когда люди используют инструменты которые удобны им. Кому-то не удобен консольный git и он использует TortoiseSVN. И это хорошо. Каждый может выбрать инструмент себе по душе, благо выбор есть.

              Вы же расцениваете пользователя git не как человека сделавшего свой осознанный выбор, а как человека которых пытается переползти на TortoiseGIT с TortoiseSVN.
              Можно писать статьи для людей не способных запомнить пару команд, но если их никто не пишет, видимо, они никому не нужны.
              • 0
                Скажите, что я ошибаюсь и статья по переходу на TortoiseGIT с TortoiseSVN не нужна.
                habrahabr.ru/blogs/development_tools/106916/
                Как показал опрос, очень даже нужна.
                При этом я рассматриваю пользователя git как сделавшего сознательный выбор (по другому выбор обычно не делается, только если навязали, но о выборе здесь говорить не приходится).

                Я говорю о том, что много желающих работать с GIT просто даже и не будут пробовать — потому как вместо привычных меню и диалогов увидят консоль.
                А на TortoiseSVN я остановился потому, что он популярный для SVN. При наличии аналога в лице TortoiseGIT переход на GIT может оказаться намного проще, чем многим думается.
                • 0
                  По ссылке совсем другой опрос. Там ни слова о переходе с одного Tortoise на другой.

                  • 0
                    Там статистика использования систем управления версиями, которая показывает что пользователей SVN значительно больше пользователей GIT.
                    • 0
                      Вы говорите, что из этого опроса следует, что необходима статья о переходе на TortoiseGIT с TortoiseSVN. Из этого опроса такой вывод не следует.
                      Нужна такая статья или нет — мне всё равно. Лично мне она не нужна.
                      Не пора ли нам прекратить этот бессмысленный спор?
            • 0
              По-моему TortoiseHg достаточно развитый продукт, более интересный, нежели TortoiseGit
    • +2
      Почему-то никто не упоминает TortoiseGit — просто волшебнуй гуй для гита, работающий из контекстного меню проводника. Очень, очень мощный и удобный.

      А под маком CtrlCtrl, и команду, благо что большинтво команд очень краткие, ключи вообще очень редко нужны.
    • 0
      • +1
        уупс, не то ._.
        progit.org/book/ru/ — тут хорошее описание, только опять же с консолью.
        • 0
          А я думал, хотите меня с TortoiseSVN познакомить...
          Спасибо за книгу, некоторые аспекты в обзорных статьях обычно не пишут.

          Проблема не в GIT так таковом, а в том, что надо переучиваться работе с консолью как с основным средством работы с репозиторием.
          • 0
            не, не надо ;-) достаточно понять идеологию, а с гуём разобраться не сложно
    • +1
      Я не считаю git технологией, я считаю git готовым инструментом.
    • 0
      А вы привыкайте, насколько я знаю даже под виндой есть консоль для git
      • 0
        Конечно есть, она везде есть. А где не было — порт сделали ;).
        Тот же TortoiseGit через консоль по сути работает.
  • 0
    Cпасибо за перевод. Оригинал давно появился в закладках — когда-то, именно он помог догнать как эффективно работать в команде.
  • +2
    Схема не учитывает модель, когда необходимо поддерживать более одной продакшн ветки (разные версии продукта). А остальное все действительно великолепно. Более общий вариант: www.infoq.com/articles/agile-version-control
    • 0
      Просто делается больше одной продакшн-ветки =)
      На самом деле, я бы даже при одной версии продукта вел разработку в master, а под продакшн завел бы соответствующую ветку. Но тут кому как больше удобно уже.
      • 0
        Согласен. Сам использую 3 основные ветки, production, master и testing. Потому что так повелось что в master были разные дев плюшки. Вобще пост весьма хорош, т.к. описывает простую логику ведения проекта в нескольких ветках и если разобраться зачем это делается, то работать становится проще и мержить руками надо меньше.
  • +1
    В таких статьях всё красиво и понятно, но как обстоят дела на практике?

    >>Ветви исправлений (hotfix branches)
    Допустим, обнаружили серьёзный баг в ветке master, делаем hotfix, исправление бага затрагивает один файл/класс, пару методов в нём.
    Но в то же время над этим файлом/классом идёт работа в ветке develop — например, его рефакторят, или частично меняют логику работы.

    >>Когда баг исправлен, изменения надо влить обратно в главную ветвь (master), а также в ветвь разработки (develop), чтобы гарантировать, что это исправление окажется и в следующем релизе. Это очень похоже на то, как закрывается ветвь релиза (release branch).

    Что будет конкретно с этим файлом? Он перепишется и тем самым похерится пару недель работы в ветке develop?
    Или Git предложит вручную слить develop- и hotfix-версии файлов?

    Понятно, что в случае пары методов проще переписать их с учётом исправления бага, но что если в реале баг может потребовать изменения десятков файлов, сотен строк кода из ветки master, которые уже частично и значительно изменены в ветке develop относительно master? Что сделает Git, если сказать ему
    $ git checkout develop
    Switched to branch 'develop'
    $ git merge --no-ff hotfix-1.2.1
    • 0
      попробует смержить автоматически, не получится — надо будет мержить вручную
    • +1
      не знаю как git, но mercurial будет вам показывать три файлика: базовый (который был одинаковым в обоих версиях), то, что вы наисправляли в фиксе и то, что наменялось в текущем девелопменте. Вы везде выбираете (в случае конфликта) то, что в девелопмент-ветке, но в то же время мимо вас не проходит ни одно изменение хотфикса. Если код куда-то переехал вы видите что конкретно надо зафиксить, идете туда, куда оно переехало и руками добавляете фикс. И так с каждым конфликтом. СВН, конечно, в пролете в таких ситуациях.

      Или я чего-то не допонял?)
      • 0
        То же самое и в git'е.
  • 0
    А кто может мне внятно объяснить, зачем удалять бранчи? Имхо, пусть себе лежат. В одной из компаний, где я работал, создавался бранч под каждый баг или реквест в багтреккере. Соответственным образом подбиралось имя ветки. Потом легко было найти, как тот или иной баг фиксился.
    • 0
      не надо плодить лишних сущностей. а чтобы найти как фиксился баг — коммит месседжи надо внятные писать, с номером таска/бага из трекера
    • 0
      Чтобы найти как фиксился баг — нужно писать к багу комментарии вида «Исправлено в [21] ревизии» (в данном случае используется синтаксис Trac)
    • 0
      Согласно статье ветки удаляются из локального репозитория, в центральном этих веток нет. Поэтому и удалять оттуда нечего :)
    • 0
      1. выше уже правильно указали — в коммитмессадже явно указывайте номер тикета, который этот коммит закрывает. Редмайн, увидев такое, статус тикета поменять может к примеру на Need feedback и в тикете укажет, что к нему имеет отношение такой-то коммит.
      2. ставьте тэг, раз так надо запомнить, а то в ветках запутаетесь.
  • 0
    а .NET-проекты можно туда пихать?
    • 0
      Можно даже .bat-файлы и конфиги =)
    • 0
      можно даже бложек
      gitwrite.com/
      • +2
        А я использую git для синхронизации многочисленных конфигов на нескольких компьютерах: ~/sync/ (который под гитом) содержит сами конфиги, а, к примеру, ~/.vimrc — симлинк на ~/sync/vim/vimrc, ~/.muttrc -> ~/sync/mail/muttrc.

        Плюсы — если меняются файлы на двух или более машинах, то при мерже с ручной правкой сразу видно что и как было изменено.
        Дополнительный плюс — если даже конфиг был удалён, он останется в истории :)
        Если куплю новый компьютер/установлю новую систему, то надо будет просто выполнить git clone ssh//segoon@XXX:sync && cd sync && ./scripts/update-links.
        Если задолбает история, то можно будет сделать rm .git && git init && git add. && git commit -m 'After armageddon'
  • 0
    >Технически это реализуется несложно: Алиса создаёт удалённую ветку Git под названием bob, которая указывает на репозиторий Боба, а Боб делает то же самое с её репозиторием.

    Не очень понятно, как именно это несложно делается. Допустим, Алиса в Самаре, а Боб в Европе. В svn все понятно — делается ветка в центральном репозитории, и в ней работают и Алиса и Боб, позже производится слияние с trunk. Собственно, именно так мы и делаем. Какой легкий способ для этого есть в git?
    • +1
      самый простой способ такой:
      git checkout master             #переключаемся на то от чего хотим отбранчеваться (в данном случае от мастера)
      git pull                        #получаем последние изменения
      git checkout -b 1234_editor_redo_feature #создаем локальную ветвь
      git-punlish-branch                       #публикуем её
      

      • 0
        Получается, что разработчики создают ветки для задач в центральном репозитории. Понятно, но почему эта технология не описывается в git-литературе, в том числе и в этой статье? Тут же какой-то другой способ подразумевается.
        • 0
          да, только не обязательно в центральном, это могут быть любые (не локальные) репозитарии т.е можно на гитхаб создать свой реп и рассказать о нем Алисе (дать ей прав на него) и она туда будет коммитить, или подключиться к её репу и забрать из него нужную ветвь и смерджить со своим репом.
          • 0
            «это могут быть любые (не локальные) репозитарии». А что мешает расшарить локальные репозитории?
            • 0
              Недоступность из вне локального репозитория, например.
            • 0
              Упс, видимо, не так понял вопрос. К локальному репозиторию любого разработчика можно обращаться, при условии наличия ssh-доступа к целевой машине и к папке с репозиторием — это из коробки. Плюс, можно настроить у себя какой-нибудь gitosis, и дать доступ другим разработчикам к нему (тогда ssh-доступ не нужен).
              • 0
                нет-нет, это не было вопрос, просто человек так явно указал что репозитории должны быть не локальными, как будто есть какая-то проблема с расшариванием локальных.
                • 0
                  конечно есть проблема :) если bob сидит за 3-мя файрволами и наружу для него открыт только 80/443 порт. Легко и непринужденно как с github не получится пробиться к локальному репозиторию Боба…
                • 0
                  что вы имеете ввиду под расшариванием? публикация локального репа на общедоступном ресурсе или пробивку туннеля?
  • 0
    Скажите а возможен ли такой сценарий: у меня есть ветка фичи feature1, я над ней работал, реализовал что нужно и потом слил ее в девелоп ветку, прошло немного времени и появилась необходимость еще кое-что доработать в этой фиче. Могу ли я опять перейти на ветку feature1, доработать что нужно и снова влить ее в ветку девелоп? Т.е. получается вот так:
    $ git checkout develop
    $ git merge --no-ff feature1
    $ git push origin develop
    (прошло время...)
    $ git checkout feature1
    (какие-то изменения...)
    $ git checkout develop
    $ git merge --no-ff feature1
    $ git push origin develop


    Так можно делать?
    • 0
      удалось выяснить?
      • 0
        Да. Можно.
        • –1
          А как можно?
  • 0
    По поводу gitflow, про который вскользь сказано. Привожу перевод примера использования.

    # Создание веток master/developer/release/hotfix
    $ git flow init
    
    # Начинаем работать над функционалом feature1 (ответвление от develop)
    $ git flow feature start feature1
    # делаем изменения
    $ git add ...изменения...
    $ git commit -m "изменения для feature1"
    
    # Эта команда сделает слияние feature1 с develop и удалит ветку
    $ git flow feature finish feature1
    
    # Давайте начнём работу над релизом
    $ git flow release start release1
    # делаем изменения
    $ git add ...изменения...
    $ git commit -m "release1"
    
    # Эта команда сделает слияние release1 с master
    $ git flow release finish release1
    


    Видеоролик по теме

    vimeo.com/16018419
  • 0
    Для автоматического --no-ff пользуюсь такими строчками в кофиге:
    [merge]
        ff = false
    

    (Не знаю, с каких версий гита эта фишка работает, но точно есть в git version 1.7.2.5)
  • 0
    Я ветки функциональности и фиксов называю по номеру таски, например issue_123.
  • 0
    Дайте, пожалуйста, консультацию, потому что я не понимаю, что происходит с файлом проэкта, если его редактируют одновременно два девелопера, и потом push'ат изменения в master?
    • +1
      Если изменения произведены в разных местах, то git автоматически применит оба изменения. Если же изменения пересекаются, то возникнет конфликт, который уже потребуется исправлять руками одному из авторов.
      • 0
        Cпасибо!
  • 0
    расскажите, как разрешается следующая ситуация:
    появляются новые feature-branches (fb) из dev-branch (dev). Но изменения в одной из них влияют на работу и реализацию в другой (т.е. функционально они слабо связаны, но тем не менее взаимное влияние у них имеется, например, использованием новой версии протокола, которое в одной fb обкатано, но функциональность из другой ветки может поломаться при вливании их обеих в dev). Что в таком случае делать? По описанию feature-branches друг в друга не вливаются, только лишь из/в dev. Допустим, влили мы обе fb в dev, что-то сломалось, порождается новая fb из dev типа «латание косяков после слияния fb1 и fb2» или же каждая из fb (или какая-то одна) забирает изменения из dev и латает косяки у себя с последующим возвратом изменений в dev?
    • +1
      Не нужно смотреть на предлагаемый workflow как на жёсткий шаблон, от которого невозможно отступить. Это всего лишь общая рекомендация, как вести себя в «обычном случае», а с различными нестандартными ситуациями часто проще всего разбираться, используя весь доступный арсенал команд git. Если есть ощущение, что в этом случае будет удобно слить две feature-ветки — договоритесь об этом с командой и сливайте. Если есть ощущение, что лучше перекинуть один-два коммита из одной ветки в другую с помощью git cherry-pick — договоритесь об этом с командой и перекидывайте. Если есть ощущение, что лучше слить ветки независимо, а потом править возможные дефекты в новой fix-ветке — делайте так. Всё зависит только от Вас.

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