Начав заниматься разработкой порталов, я стал задавать себе очень много вопросов. Одним из интересных вопросов, на который мне пришлось ответить - это вопрос каким образом мы будем поддерживать проекты? В те времена, когда я работал в студии, мы так и не нашли для себя ответа на этот вопрос - опыта не хватило для понимания. Так и жили без обновлений. В этот раз вопрос потребовалось решить на берегу - проекты гораздо серьезнее, да и нервы надо беречь.
Чтобы ускорить первые шаги новых проектов, мы скомпоновали наиболее общий функционал, присутствующий практически во всех проектах, в некое скелетное приложение, которое копируется в новый проект. Назвать это CMS я не решусь - это скорее конструктор, для сборки которого требуются определенные навыки. Универсальный функционал, не имеющий привязки к конкретному типу проектов, выносится в модули и подключается по необходимости.
Поставив скелет, мы начинаем его модифицировать под нужды конкретного заказчика. Чаще всего модифицируются шаблоны, гораздо реже меняются модели и контроллеры. И очень часто бывает такое, что в ходе работы хочется внести какие-то изменения сразу во все проекты. Например, повысить безопасность и стабильность приложений, усовершенствовать систему кэширования, оптимизировать код. Делать это вручную глупо - слишком велика вероятность ошибки.
Наиболее приемлимым инструментом для обновления кода в нашем случае стала система контроля версий. В любой системе контроля версий уже присутствуют инструменты для наложения изменений (патчей), сделанных в коде одного проекта, на код другого проекта.
Когда мы работали с Subversion, с обновлением кода была масса проблем. Постоянно возникали какие-то косяки с применением патчей. Чтобы решить эту проблему, нам приходилось держать все проекты тупо в виде веток одного репозитория. Это крайне неудобно в плане администрирования и повседневного использования. Работа по такой схеме вызывала натуральную зубную боль - настолько было неудобно.
С переходом на Git проблема поддержки как таковая перестала существовать - обновление скелетного кода перестало отличаться от применения любых других изменений.
Практика
Давайте по шагам рассмотрим, каким образом можно организовать обновление проектов, унаследованных от единой первоначальной версии. Допустим у нас есть исходное приложение mega-cms, размещенное в репозитории git@myhost.ru:mega-cms.git, на базе которого мы создаем проекты.
Создаем новый проект и репозиторий:
mkdir ~/mega-project
cd ~/mega-project
git init
Создан девственно чистый репозиторий. Следующий шаг - заливка кода из базового приложения:
git remote add mega-cms git@myhost.ru:mega-cms.git
git pull mega-cms master
Первой командой мы создаем ссылку на удаленный репозиторий, а второй сливаем из него все изменения начиная с самых первых. Фактически, мы теперь имеем в проекте mega-project точную копию проекта mega-cms.
Теперь давайте зальем эту копию в удаленный репозиторий, чтобы использовать ее для развертывания на сервере:
git remote add origin git@myhost.ru:mega-project.git
git push origin master
Отлично. Теперь давайте внесем какие-нибудь изменения в исходный код mega-project. Например, добавим файл с описанием проекта:
echo "This is readme file for mega-project" > README
git add .
git commit -a -m "Adding README file"
А теперь внесем изменения в проект mega-cms - добавим список задач:
cd ~/mega-cms
echo "Create tasks to automate project update" > TODO
git add .
git commit -a -m "Adding TODO list"
git push
Последняя команда выгружает изменения в проекте в удаленный репозиторий. Теперь самое интересное - нам нужно обновить код в mega-project, чтобы созданный список появился и там:
cd ~/mega-project
git pull mega-cms master
Вуаля! Git автоматически определяет, какие изменения в mega-cms были внесены после копирования и автоматически применяет их к mega-project. Если возникают какие-либо конфликты (например, мы исправляем один и тот же абзац README в mega-project и в mega-cms), то Git попросит нас ручками разрешить спорную ситуацию.
И последний шаг - заливаем примененные изменения в удаленный репозиторий:
git push
Наслаждайтесь :) Я сливаю изменения из проекта в проект по нескольку раз на дню. Даже думать не хочется о том, что это можно делать как-то иначе.
