Коллективная разработка с использованием git и Trac в проекте Midnight Commander
Действительно, в интернете сейчас можно найти достаточно много информации о настройке GIT и работе с ним, но недостаточно освещен вопрос коллективной разработки и "рабочего процесса" отдельно взятого проекта от начала и до конца.
Попробую восполнить этот пробел на примере открытого проекта Midnight Commander, не останавливаясь на вопросах установки необходимого ПО, так как этот момент неплохо описан в интернете, и вы сможете легко найти интересующую вас дополнительную информацию самостоятельно.
Используемые термины и определения
тикет - отчёт об ошибках либо о пожеланиях, улучшениях. Иные названия - багрепорт и т.п.
бранч - ветвь разработки, существующая в системе контроля версий (в git)
апстрим - главная ветвь в системе контроля версий. Для git это обычно ветвь "master"
стабильная ветвь - ветвь отпочковавшаяся от ветви "master" тэгированная и выпущенная в качестве релиза (в дальнейшем сопровождается отдельно)
Исправление ошибок/добавление функционала
Фиксация текущего состояния разработки с помощью Trac
В нашей команде нет как такового лидера проекта, и у нас работает принцип долбанной демократии, т.е. решения принимаются коллегиально, большинством голосов. Чтобы принятие решений не затягивалось на долго, всё общение происходит в джаббер конференции в реальном времени. Кто не успел -- тот опоздал :). Но если решение требует голосов всех активных разработчиков, то заводится отдельный тикет для голосования на Trac-е проекта.
Чтобы не было хаоса в процессе разработки, мы приняли ряд регламентов, оговаривающих непосредственный "рабочий процесс". Процесс сводится к нескольким этапам:
выявление проблемы
создание тикета на Trac-е
принятие разработчиком тикета в работу
публикация работы в виде бранча
обсуждение в комнате найденного решения, проверка работоспособности, аудит кода
утверждение бранча, если необходимое количество разработчиков сочли решение приемлимым
влитие бранча в апстрим
Если один из разработчиков решает исправить проблему, описанную в тикете, или хочет добавить новый функционал - он назначает себя владельцем тикета и в дальнейшем считается ответственным за решение данной проблемы. Теперь он наблюдает за тикетом (общается с постановщиком задачи, следит за тем -- не предложил ли кто то из сторонних разработчиков своего "решения" в виде патчей и т.п.), создает новую ветку (бранч) для последующей работы в ней. Новые ветки обязательно должны следовать правилам наименования: XYZ_<здесь_некоторое_описание>
где XYZ - это номер тикета; описание по возможности должно быть осмысленным и коротким.
Патчи из тикета никогда не применяются непосредственно к ветви "master", а проходят всегда процедуру обсуждения и ревизии в виде отдельной ветви.
После создания ветви и публикации ее в репозитарии ответственный за тикет разработчик выставляет ветвь на ревизию (review) для того, чтобы другие разработчики смогли увидеть что данный тикет готов к ревизии и обсуждению. Если это не сделано и тикет не выставлен на review - ветвь считается нестабильной и подлежит дальнейшей разработке.
В качестве примера приведу тикет #1746, в нем некто bilbo описал суть проблемы со встроенным ftp клиентом и приложил патч устраняющий проблему.
Далее в этом же тикете он сообщает о публикации в репозитории новой ветви 1746_passive_mode_over_proxy и выставлении ее на голосование.
* owner set to bilbo
* status changed from new to accepted
* severity changed from no branch to on review
Created branch 1746_passive_mode_over_proxy
Initial changeset: b32c9e4a2a15cd50a6a07ad85b1a587328bd2cfc
После просмотра кода двое разработчиков проголосовали за данный код и обозначили его как утвержденный (approved).
* votes changed from slavazanko to slavazanko andrew_b
* severity changed from on review to approved
Далее разработчик произвел слияние своей ветви 1746_passive_mode_over_proxy с основной ветвью master и сообщил об этом в тикете:
* status changed from accepted to testing
* votes changed from slavazanko andrew_b to commited-master
* resolution set to fixed
* severity changed from approved to merged
Fixed 2cfed22012ded42c2f4f47a13edc05bf405842db
Работа с кодом под контролем GIT
Работа над кодом с использованием git, в пределах одного тикета, сводится к следующим шагам:
переключение на ветвь "master"
$ git checkout master
получение последних изменений
$ git pull
создание локального бранча, согласно правил наименования этого самого бранча
$ git checkout -b 123_branch_name
Далее разработчик вносит изменения в исходные тексты и коммитит изменения...
фиксация изменений
Так же, как существует руководство по созданию тикетов -- существует и руководство по их обзору.
Основные принципы, которыми мы пользуемся при обзоре кода, хорошо и ёмко изложены в статье, перевод которой опубликован здесь "Я ненавижу тебя: твой код – хлам!".
Разработчик, взваливший на себя ответственность за ревизию кода, должен в процессе обзора получить для себя ответы на следующие вопросы:
является ли патч вкладывающимся в общую концепцию проекта или патч является "хаком"?
аккуратно ли выглядит код?
делает ли код то, что должен делать (что было задекларировано в комментарии к патчу)?
добавляет ли код новые проблемы (ошибки)?
Если патч нравится (выглядит приемлемым), то разработчик-рецензент должен добавить свой голос в поле для голосования (Votes for changeset) в формате <login>, где login - это имя пользователя в Trac. Если же патч не совсем безгрешный, то необходимо написать об этом ответственному за тикет и сменить статус тикета с review на rework
В настоящее время необходимы голоса двух разработчиков чтобы патч был применён к родительской ветви (либо к ветви "master"). Если кто-либо из рецензентов добавляет свой голос вторым, то ему необходимо также сменить статус тикета на approved (утверждено).
В ходе обсуждения в тикете, либо в ходе просмотра патчей разработчики могут убирать свои голоса при возникновении каких-либо проблем.
Идеальный вариант тестирования:
Далее сборка, тестирование, просмотр кода, рецензия.
Применение патчей
После процедуры ревизии и получения необходимого количества голосов за бранч, разработчик может влить свои изменения в основной ствол репозитория. При этом также должны быть соблюдены регламенты:
НИКОГДА(!!!) не производить перебазирование (rebase) стабильной ветки относительно "master", чтобы объединить исправления!
Обязательно в первом описании коммита указать номер тикета в формате, относительно которого был создан бранч, примерно так:
Ticket #123 (ticket summary)
<пустая строка>
add: some text...
fix: some text...
это поможет в дальнейшем связать, через описание первого коммита, влитый бранч с номером тикета на Trac-е.
Обязательно произвести перебазирование своего бранча относительно родительской ветви.
например если бранч основан на ветви "master"
ключ -i указывается если нужно произвести интерактивное перебазирование (если нужно удалить/склеить/переставить отдельные коммиты)
После этого надо обновить ветвь на сервере
$ git push origin +123_branch_name
"+" указывает что нужно произвести принудительное (forced) обновление коммитов в удаленном бранче
NB: Если не сделать перебазирование, то возможна ситуация когда другие разработчики уже влили свои конкурирующие изменения в нашу родительскую ветвь, и в лучшем случае история в ней будет путанной и сумбурной, а в худшем -- родительская ветвь перестанет собираться либо будет работать некорректно.
ключ --log показывает в коммите слияния, список патчей которые вводятся этим слиянием;
ключ --no-ff позволяет сгенерировать коммит слияния даже в том случае, если ветвь является дочерней от вершины родителя (по нему проще отследить, какие патчи были сделаны в рамках данного тикета). Этот ключ значительно упрощает понимание взаимосвязей коммитов.
обновление данных в удаленном репозитарии
$ git push origin master
удаление ветви 123_branch_name на сервере и локально