Система контроля версий (version control system) – это централизованное хранилище и одновременно машина времени для всех ваших цифровых активов. Когда-то контроль версий использовался только большими командами программистов, но сейчас процесс разработки ПО уже невозможно представить без него, и он даже проникает в другие области, такие как Google Docs, который сохраняет историю всех изменений в ваших документах.
Системы контроля версий за годы эволюционировали от CVS до SVN и современной системы Git, наиболее популярной среди разработчиков (а сервис GitHub является одним из крупнейших репозиториев ПО с открытым исходным кодом). Тем не менее основной принцип остается неизменным: обеспечить возможность параллельной разработки как одним, так и несколькими разработчиками, чтобы для этого им не приходилось настраивать отдельные окружения для работы с разными версиями проекта. Представьте, что вы находитесь в середине масштабной разработки новой версии проекта и вам понадобилось исправить ошибку в продакшене. Для этого вам нужен будет исходный код версии, которая работает в продакшене (не содержащий никаких изменений из новой версии), чтобы надежно исправить ошибку и сделать релиз, не опасаясь, что новый код попадет наружу.
Некоторые команды не используют контроль версий. Иногда они хранят старые версии в отдельных папках или в каких-нибудь файлах в формате zip. Предлоги не использовать контроль версий бывают самыми разными – что это просто не нужно, не поддерживается для их языка программирования, замедляет работу, – но все это неправда. Основная проблема в том, что они просто боятся нового.
На верхнем уровне система контроля версий представляет собой набор отдельных репозиториев. Их можно рассматривать как простые папки с файлами, но это неправильно, потому что их возможности несравненно больше. Это скорее компоненты, блоки, из которых строится ваш проект. Каждый репозиторий полон жизни и позволяет вам путешествовать во времени, это настоящая мультивселенная, в которой одновременно доступны все ваши действия, все решения, вся эволюция каждой из частей за всю историю проекта.
Заметки с полей
Цена отсутствия контроля версий
Еще в начале своей карьеры я работал в Риме для Организации Объединенных Наций – мы писали Java-сервлеты для обработки спутниковых фотографий сельскохозяйственных земель в Африке. У них уже были CGI-скрипты, разработанные на Perl, чтобы ученые могли получать доступ к фотографиям в браузере Mozilla, и нас пригласили попробовать новый стандарт Java Servlet и посмотреть, как он будет работать при реальной нагрузке. Я провел там уже несколько месяцев, и в одну из недель усердно трудился над новым модулем, чтобы закончить его до того, как я сяду в самолет и отправлюсь домой на несколько дней. 25 с лишним лет назад у нас не было стандартов или процессов работы с кодом, не говоря уже о контроле версий. По ходу работы я сам сохранял резервные копии в отдельном сетевом каталоге (и думал, что этого более чем достаточно). Я периодически тестировал, что получается, и, в общем, один из процессов в нашем приложении удалял временные файлы (в те дни место на диске было на вес золота). Однако в спешке я что-то напутал, и он удалил все исходные файлы как локально, так и с моего резервного сетевого диска. Восстановить их я не смог, как ни пытался. Я своими руками удалил результат своего же недельного труда, и другого выхода не было, кроме как остаться на выходные и написать все заново. Эта неделя стала для меня настолько поучительной, что с тех пор подобное не повторялось.
Выбор того, что именно выносить в отдельные репозитории, зависит от множества факторов, и универсального ответа тут не существует. Следующие вопросы помогут понять, что может быть отдельным репозиторием:
• Есть ли у этого компонента отдельная функция или роль?
• Требует ли он отдельных специалистов с особым набором навыков?
• Насколько он связан с другими компонентами?
• Как делаются релизы этого компонента и всего проекта?
Старайтесь избегать слишком большого количества репозиториев, но и не стоит использовать только один, в котором лежит вообще все. Если репозиториев много, то накладные расходы, связанные с ними, оказываются слишком велики, а если их мало, становится сложно разобраться в отдельных коммитах. Это классическая дилемма Златовласки: «Не слишком горячо и не слишком холодно»[2].
Подобно тому, как файлы и папки никак не влияют на их содержимое, вложенность и детализацию данных, так же и сама по себе система контроля версий не определяет какой-либо стратегии использования – это просто подход и набор инструментов. Существует, однако, ряд общепринятых и всем понятных методик, и вы можете выбрать ту, которая лучше всего подходит для вашей команды и проекта. Вот пара примеров:
• Gitflow – использует две основные ветки: master (код в ней всегда готов к деплою) и develop. Для разработки каждой новой функции вы создаете из develop новую ветку (feature branch), изменения из которой после проверки вносятся обратно в develop. Чтобы сделать релиз, вы создаете из ветки develop новую ветку (release branch) – это то, что можно деплоить. Все изменения, попавшие в ветку релиза, надо смержить в мастер. Никакие изменения не должны вноситься напрямую ни в master, ни в develop.
• GitHub flow – более простая версия Gitflow, из основных веток в ней используется только master. Для новых функций создаются новые ветки, после ревью и тестирования изменения из них вносятся в master, и их можно деплоить.
При использовании любой методики вы можете сами определить способ интеграции с тикетной системой, правила именования веток, допустимое количество изменений или время жизни для веток, релизный цикл и т. д. Все это нужно выбирать исходя из требований вашего проекта, чтобы вспомогательные инструменты и отчеты, которые вы будете создавать для вашей системы контроля версий, были максимально эффективны.