Необходимо регулярно сверять устройство вашей системы контроля версий с
реальностью процесса разработки и внедрения. В этом документе мы постараемся
изложить краткую схему вопросов, на которые необходимо ответить, чтобы
высветить недостатки и потенциальные проблемы в вашей системе.
Для анализа нам потребуется описание структуры веток, список участников
процесса и область их ответственности, описание потоков изменений. Для
наглядности можно попробовать нарисовать пару диаграмм: граф потоков изменений
по веткам и древовидную структуру потока, развернутую во времени. Мы считаем
более важным (и более простым) первый график, тогда как традиционно во многих
текстах по системам контроля версий используется второй, не так чётко
высвечивающий структуру.
В этом документе описывается только анализ системы. Способы решения проблем,
выявленных при анализе, будут обсуждаться отдельно.
I. Список веток
Выписываем в столбик список веток.
На этом этапе не надо придумывать новых веток, «как хотелось бы».
Просто выписываем в столбик список существующих, даже если она всего одна.
Как оно вообще может быть: примеры. Для тривиальных (или плохо организованных)
проектов этот список состоит из одного пункта: «ствол». Для чуть более
контролируемых проектов появляется ветка «production». Часто используются
ветки под крупную задачу (feature branches): «новый дизайн проекта»,
«рефакторинг системы классов», «эксперимент Б». Некоторые системы контроля
версий способствуют тому, что ветки под задачу могут быть крошечными и
короткоживущими (task branches) — вплоть до одного-двух коммитов. Иногда
используются ветки под девелопера: каждый работает в своей ветке и регулярно
сливает изменения на ствол, убедившись в их качестве. Иногда используются
временные ветки для QA, со своим уникальным процессом.
Долгоживущие ветки выписываются как есть. Временные короткоживущие ветки,
такие как ветки под задачу или qa-ветки, занимают одну строчку во
множественном числе.
Пример списка веток:
trunk
production
ветки под задачу
II. Чеклист по веткам
Для каждой строчки списка из предыдущего ответа необходимо ответить на ряд
вопросов. Ответы на них нужно записать, а результирующий документ вслух
обсудить со всеми участниками, упомянутыми в нём. Это нужно для того, чтобы
быть уверенным в полноте документа и в том, что все с ним согласны.
Все вопросы, на которые нет ответа, либо ответ неадекватен, либо при наличии
несогласия, помечаются. Опять же, на этом этапе не следует вносить исправления
— только анализ.
II.1. Когда, кто, откуда и на какой срок создаёт ветку?
Четыре вопроса: Кто создаёт эту ветку? При каких условиях он её создаёт?
Каково начальное содержимое ветки? Каков срок жизни ветки?
Пример 1:
Пример 2:
Здесь в принципе уже может появиться понимание, что какой-то из аспектов
непродуман. Помечаем вопрос как проблемный и движемся дальше.
II.2. Откуда берутся изменения на ветке?
Для нашего дальнейшего обсуждения давайте различать изменения (changesets) и
коммиты (commits). Будем называть «коммитами» только те изменения, которые
делаются разработчиком руками (грубо говоря, написанный код). «Изменения» — более общее понятие, включающее также автоматические слияния с других веток.
Итак, два вопроса: Кто вносит изменения на ветку? Какова природа этих
изменений?
Основные классы вносимых изменений, которые необходимо различать:
Надо перечислить все источники внесения изменений на ветку, а в конце списка
написать ритуальное заклинание «больше никаких изменений на эту ветку никем не
вносится». При произнесении заклинания убедиться, что эта формулировка не
вызывает протестов у всех причастных к обсуждению.
Пример 1:
Этот пример означает, что даже быстрые фиксы обязаны проходить через транк.
Пример 2:
Пример 3:
II.3. Куда уходят изменения, внесенные на ветку? Кто это делает?
Здесь возможны три варианта:
Пример 1:
Пример 2:
II.4. Кто отвечает за состояние ветки?
Почти всегда, конечно, это те же люди, что вносят изменения. Однако из-за
наличия слияний может получиться так, что в ветку рано или поздно приезжают
коммиты, сделанные другими людьми.
Важно точно убедиться, что человек, вносящий изменения, понимает, что его
работа — это не механическая заливка на ветку свежего тарболла, а некоторая
интеллектуальная работа. Самый простой пример — отслеживание open-source
проекта. Компилируется ли оно? Нет ли в нём известных багов? Вообще, именно
этот вопрос требует максимального объема коммуникации.
Пример 1:
Пример 2:
II.5. Смысл ветки.
Теперь, когда мы точно изучили реальную структуру ветки, можно написать
краткое описание её смысла. Если описание слишком длинное и сложное —
возможно, ветка перегружена и её необходимо расщепить, или перестроить рабочий
процесс. Никакой новой информации в этом описании быть не должно — всё
изложено в предыдущих вопросах.
Пример 1:
Trunk предназначен для текущей слабоструктурированной разработки очередной
версии.
Пример 2:
Feature-ветки предназначены для работы над крупными переделками структуры
кода с большим ожидаемым временем нестабильности.
III. Действующие лица и исполнители.
Для контроля целостности составленного анализа необходимо перечислить всех
упомянутых в нём сотрудников (или групп сотрудников) и для каждого кратко
перечислить:
Формально этот пункт избыточен (вся информация уже собрана ранее), но
требуется для, например, выяснения, не перегружен ли тот или иной сотрудник.
IV. Пример документа, взят с реального проекта
Список веток:
Trunk
Trunk был создан в момент начала проекта ведущим разработчиком с нуля и будет
жить вечно.
Разработчики С. и М. свободно коммитят в trunk; верстальщики С. и Н. свободно
коммитят в trunk; из feature-веток изменения автоматически сливаются в trunk;
больше никаких изменений на trunk никем не вносится.
Изменения с trunk сливаются на ветку «production» одним из разработчиков (по
принципу КПТИП); изменения с trunk сливаются на feature-ветку владельцем этой
ветки.
За качество кода на trunk существует солидарная ответственность. Каждый
разработчик отвечает за свои коммиты. За коммиты, внесенные верстальщиками, не
чувствует своей ответственности никто. (ПРОБЛЕМА!)
Trunk предназначен для текущей слабо формализованной разработки проекта.
Ветка «production»
Ветка «production» была создана в процессе внедрения проекта в эксплуатацию
ведущим разработчиком на основании текущего состояния trunk и будет жить
вечно.
Разработчики С. и М. (в зависимости от того, чья фича выносится), сливают
изменения с trunk в production; больше никаких изменения на production никем
не вносится.
Изменения с production с помощью deploy-скрипта выносятся на staging, а затем
на боевой сервер и становятся доступны широкой публике. Выносит один из двух
разработчиков (в зависимости от того, чья фича выносится).
За качество кода на «production» существует солидарная ответственность.
Выносящий разработчик отвечает за качество вынесенной функциональности
(своей). Как показал опрос, за коммиты от верстальщиков, пробравшиеся на
production, не чувствует своей ответственности никто. (ПРОБЛЕМА!)
Production предназначен для выкладывания стабилизированных изменений.
Feature-ветки
Feature-ветки создаются при крупных переработках сайта (с ожидаемым временем
нестабильности более двух-трёх дней). Ветки создаются разработчиком, которому
поручена задача. Ветки создаются на основании текущей версии trunk. Ветки
будут жить во время работы над задачей и ещё некоторое время после первой
реинтеграции (с повторными реинтеграциями).
Хозяин ветки свободно коммитит в feature-ветку; хозяин ветки может обновлять
состояние feature-ветки, заливая на неё изменения, происходящие в trunk;
больше никто никаких изменений в feature-ветку не вносит.
За качество кода на feature-ветке отвечает её владелец.
Feature-ветки предназначены для временного хранения нестабильных наборов
изменений.
Заключение
В этой схеме видно несколько проблем с процессом разработки.
Вообще говоря, солидарная ответственность за вынос изменений на production
имеет ограниченное применение и быстро становится неадекватной при росте
требований к надёжности сайта.
Кроме того, обнаруженная в процессе аудита проблема того, что коммиты от
верстальщиков регулярно бесконтрольно добираются до продакшена, неприемлема и
должна быть решена.
Методам решения этой и других проблем мы посвятим нашу следующую статью.
P.S.: у нас есть ряд вакансий: http://undev.ru/.
реальностью процесса разработки и внедрения. В этом документе мы постараемся
изложить краткую схему вопросов, на которые необходимо ответить, чтобы
высветить недостатки и потенциальные проблемы в вашей системе.
Для анализа нам потребуется описание структуры веток, список участников
процесса и область их ответственности, описание потоков изменений. Для
наглядности можно попробовать нарисовать пару диаграмм: граф потоков изменений
по веткам и древовидную структуру потока, развернутую во времени. Мы считаем
более важным (и более простым) первый график, тогда как традиционно во многих
текстах по системам контроля версий используется второй, не так чётко
высвечивающий структуру.
В этом документе описывается только анализ системы. Способы решения проблем,
выявленных при анализе, будут обсуждаться отдельно.
I. Список веток
Выписываем в столбик список веток.
На этом этапе не надо придумывать новых веток, «как хотелось бы».
Просто выписываем в столбик список существующих, даже если она всего одна.
Как оно вообще может быть: примеры. Для тривиальных (или плохо организованных)
проектов этот список состоит из одного пункта: «ствол». Для чуть более
контролируемых проектов появляется ветка «production». Часто используются
ветки под крупную задачу (feature branches): «новый дизайн проекта»,
«рефакторинг системы классов», «эксперимент Б». Некоторые системы контроля
версий способствуют тому, что ветки под задачу могут быть крошечными и
короткоживущими (task branches) — вплоть до одного-двух коммитов. Иногда
используются ветки под девелопера: каждый работает в своей ветке и регулярно
сливает изменения на ствол, убедившись в их качестве. Иногда используются
временные ветки для QA, со своим уникальным процессом.
Долгоживущие ветки выписываются как есть. Временные короткоживущие ветки,
такие как ветки под задачу или qa-ветки, занимают одну строчку во
множественном числе.
Пример списка веток:
trunk
production
ветки под задачу
II. Чеклист по веткам
Для каждой строчки списка из предыдущего ответа необходимо ответить на ряд
вопросов. Ответы на них нужно записать, а результирующий документ вслух
обсудить со всеми участниками, упомянутыми в нём. Это нужно для того, чтобы
быть уверенным в полноте документа и в том, что все с ним согласны.
Все вопросы, на которые нет ответа, либо ответ неадекватен, либо при наличии
несогласия, помечаются. Опять же, на этом этапе не следует вносить исправления
— только анализ.
II.1. Когда, кто, откуда и на какой срок создаёт ветку?
Четыре вопроса: Кто создаёт эту ветку? При каких условиях он её создаёт?
Каково начальное содержимое ветки? Каков срок жизни ветки?
Пример 1:
- ветка «production» создаётся в момент, когда общепринято, что проект
готов к внедрению, и разработка стабилизируется;
- ветку создаёт ведущий разработчик;
- ветка создаётся на основании текущего состояния транка;
- ветка живёт «вечно».
Пример 2:
- ветка под задачу создаётся при появлении относительно большой и сложной
задача, которую нецелесообразно разрабатывать непосредственно в
транке;
- ветку создаёт разработчик, которому поручена задача;
- ветка создаётся на основании текущего состояния транка;
- ветка живёт, пока задача не будет в целом сделана (после реинтеграции в
транк доработки по задаче происходят непосредственно в транке).
Здесь в принципе уже может появиться понимание, что какой-то из аспектов
непродуман. Помечаем вопрос как проблемный и движемся дальше.
II.2. Откуда берутся изменения на ветке?
Для нашего дальнейшего обсуждения давайте различать изменения (changesets) и
коммиты (commits). Будем называть «коммитами» только те изменения, которые
делаются разработчиком руками (грубо говоря, написанный код). «Изменения» — более общее понятие, включающее также автоматические слияния с других веток.
Итак, два вопроса: Кто вносит изменения на ветку? Какова природа этих
изменений?
Основные классы вносимых изменений, которые необходимо различать:
- коммиты (код, написанный разработчиком);
- автоматические слияния других веток (указать, с каких);
- ручные слияния отдельных коммитов с других веток (с каких?) (обычно
встречается при багфиксах старых версий на maintenance-бранчах);
- обновление версий внешнего кода (как часто?) (встречается на vendor
branches, tracking branches).
Надо перечислить все источники внесения изменений на ветку, а в конце списка
написать ритуальное заклинание «больше никаких изменений на эту ветку никем не
вносится». При произнесении заклинания убедиться, что эта формулировка не
вызывает протестов у всех причастных к обсуждению.
Пример 1:
- разработчик Вася, отвечающий за продакшен, автоматически сливает на
ветку production изменения с транка;
- больше никаких изменений на ветку production никем не вносится.
Этот пример означает, что даже быстрые фиксы обязаны проходить через транк.
Пример 2:
- разработчик Петя при выходе новой версии nginx заливает в vendor branch
«nginx-orig» его исходники;
- больше никаких изменений на ветку «nginx-orig» никем не вносится.
Пример 3:
- все разработчики проекта свободно коммитят на trunk;
- разработчики, занимающиеся крупными задачами, автоматически сливают
изменения со своих feature branches на trunk;
- больше никаких изменений на trunk никем не вносится.
II.3. Куда уходят изменения, внесенные на ветку? Кто это делает?
Здесь возможны три варианта:
- «наружу» (вынос версии сайта на публику, генерация инсталлятора для
выкладывания на download.com, etc.);
- сливаются на другую ветку (указать, какую);
- выбрасываются (для экспериментальных веток).
Пример 1:
- разработчик Дима с помощью deploy-скрипта регулярно выносит текущую
версию «production» на публику.
Пример 2:
- изменения в feature-ветках при завершении работы над задачей сливаются
в trunk владельцем задачи.
II.4. Кто отвечает за состояние ветки?
Почти всегда, конечно, это те же люди, что вносят изменения. Однако из-за
наличия слияний может получиться так, что в ветку рано или поздно приезжают
коммиты, сделанные другими людьми.
Важно точно убедиться, что человек, вносящий изменения, понимает, что его
работа — это не механическая заливка на ветку свежего тарболла, а некоторая
интеллектуальная работа. Самый простой пример — отслеживание open-source
проекта. Компилируется ли оно? Нет ли в нём известных багов? Вообще, именно
этот вопрос требует максимального объема коммуникации.
Пример 1:
- за качество кода на trunk'е — солидарная нежесткая ответственность.
Ломать сборку запрещено. Коммитить код без тестов или тем более не
проходящий тесты — порицается. Количество багов желательно уменьшать, а
количество фич — увеличивать.
Пример 2:
- за качество ветки «golden», которая
будет записана на компакт-диски в количестве 10 тысяч экземпляров и
отправится в магазины, отвечает лично Релизов Авдотий Валерьевич. Ошибки
на этой ветке наказываются лишением премии, а ошибки, приводящие к выбросу
партии дисков— переводом на младшую должность. Место для подписи:
_______.
II.5. Смысл ветки.
Теперь, когда мы точно изучили реальную структуру ветки, можно написать
краткое описание её смысла. Если описание слишком длинное и сложное —
возможно, ветка перегружена и её необходимо расщепить, или перестроить рабочий
процесс. Никакой новой информации в этом описании быть не должно — всё
изложено в предыдущих вопросах.
Пример 1:
Trunk предназначен для текущей слабоструктурированной разработки очередной
версии.
Пример 2:
Feature-ветки предназначены для работы над крупными переделками структуры
кода с большим ожидаемым временем нестабильности.
III. Действующие лица и исполнители.
Для контроля целостности составленного анализа необходимо перечислить всех
упомянутых в нём сотрудников (или групп сотрудников) и для каждого кратко
перечислить:
- какие изменения в какие ветки он имеет право вносить;
- за какие ветки он отвечает;
- с каких веток он выносит код наружу.
Формально этот пункт избыточен (вся информация уже собрана ранее), но
требуется для, например, выяснения, не перегружен ли тот или иной сотрудник.
IV. Пример документа, взят с реального проекта
Список веток:
- trunk;
- production;
- feature-ветки.
Trunk
Trunk был создан в момент начала проекта ведущим разработчиком с нуля и будет
жить вечно.
Разработчики С. и М. свободно коммитят в trunk; верстальщики С. и Н. свободно
коммитят в trunk; из feature-веток изменения автоматически сливаются в trunk;
больше никаких изменений на trunk никем не вносится.
Изменения с trunk сливаются на ветку «production» одним из разработчиков (по
принципу КПТИП); изменения с trunk сливаются на feature-ветку владельцем этой
ветки.
За качество кода на trunk существует солидарная ответственность. Каждый
разработчик отвечает за свои коммиты. За коммиты, внесенные верстальщиками, не
чувствует своей ответственности никто. (ПРОБЛЕМА!)
Trunk предназначен для текущей слабо формализованной разработки проекта.
Ветка «production»
Ветка «production» была создана в процессе внедрения проекта в эксплуатацию
ведущим разработчиком на основании текущего состояния trunk и будет жить
вечно.
Разработчики С. и М. (в зависимости от того, чья фича выносится), сливают
изменения с trunk в production; больше никаких изменения на production никем
не вносится.
Изменения с production с помощью deploy-скрипта выносятся на staging, а затем
на боевой сервер и становятся доступны широкой публике. Выносит один из двух
разработчиков (в зависимости от того, чья фича выносится).
За качество кода на «production» существует солидарная ответственность.
Выносящий разработчик отвечает за качество вынесенной функциональности
(своей). Как показал опрос, за коммиты от верстальщиков, пробравшиеся на
production, не чувствует своей ответственности никто. (ПРОБЛЕМА!)
Production предназначен для выкладывания стабилизированных изменений.
Feature-ветки
Feature-ветки создаются при крупных переработках сайта (с ожидаемым временем
нестабильности более двух-трёх дней). Ветки создаются разработчиком, которому
поручена задача. Ветки создаются на основании текущей версии trunk. Ветки
будут жить во время работы над задачей и ещё некоторое время после первой
реинтеграции (с повторными реинтеграциями).
Хозяин ветки свободно коммитит в feature-ветку; хозяин ветки может обновлять
состояние feature-ветки, заливая на неё изменения, происходящие в trunk;
больше никто никаких изменений в feature-ветку не вносит.
За качество кода на feature-ветке отвечает её владелец.
Feature-ветки предназначены для временного хранения нестабильных наборов
изменений.
Заключение
В этой схеме видно несколько проблем с процессом разработки.
Вообще говоря, солидарная ответственность за вынос изменений на production
имеет ограниченное применение и быстро становится неадекватной при росте
требований к надёжности сайта.
Кроме того, обнаруженная в процессе аудита проблема того, что коммиты от
верстальщиков регулярно бесконтрольно добираются до продакшена, неприемлема и
должна быть решена.
Методам решения этой и других проблем мы посвятим нашу следующую статью.
P.S.: у нас есть ряд вакансий: http://undev.ru/.