От основной ветки разработки можно отделить ветвь являющуюся ее копией на данный момент времени. Этим решаются следующие задачи:
- Фиксация состояния разработки (например выпуск новой версии) к которому можно будет вернуться в любой момент.
- Разработка независимо от основной ветви — актуально когда над проектом работают несколько разработчиков.
В этой заметке будут рассмотрены эти возможности, а также подводные камни работы с ветками и о том как их избежать.
Перед чтением настоятельно рекомендую прочесть введение в Subversion и заметку об организации репозитория. Также следует убедиться, что версия SVN используемая вами не ниже 1.5, так как более ранние версии имеют ряд серьезных проблем в работе с ветками.
Что такое ветка?
Договоримся, что под основной ветвью (стволом дерева) подразумевается директория в репозитории в которой идет разработка (trunk). Тогда сразу же после создания ветки она представляет из себя точную копию trunk, но независимую от своего родителя — ствола дерева. Вы можете независимо работать и с веткой и со стволом, комитить код в репозиторий, при этом история изменений будет своя как для ствола, так и для ветви. Ветви в SVN легковесны, поэтому вы можете создавать их в любом количестве, не особо задумываясь о разрастании репозитория.
Фиксация определенного состояния разработки
Очень удобно фиксировать определенные состояния разработки в ветвях с идентификаторами соответствующими внешней версии программного обеспечения (например 2.4.1) или внутренней (build_534). Эти идентификаторы удобно использовать в системах багтрекинга, документации, внутренней переписке. Можно быть уверенным, что в любой момент времени возможно получить нужное состояние кода, например для исследования причин возникновения проблемы.
Для данных целей служит папка tags в корне репозитория. То есть внутри нее могут находится папки с именами 1.0.0, 1.0.1, 2.0.0 и так далее, которые в свою очередь будут содержать актуальный код на момент создания данной ветви. Работа с ними полностью аналогична работе с trunk. Возможно вносить изменения, фиксировать их в репозитории, но я крайне не рекомендую этого делать, так как концептуально это именно слепки с основной ветви соответствующие определенному этапу!
Использование веток при коллективной разработке
Если над проектом работает более одного человека я рекомендую использовать подход с использованием временных веток. Что я под этим подразумеваю? Например я получаю задание реализовать определенный функционал. Мне необходимо периодически сохранять свой код в репозитории, но если я буду сохранять код в нерабочем состоянии (например временные эксперименты или просто решил отложить работу на завтра), то это приведет к поломке основной ветви разработки и создаст проблемы остальным разработчикам. Поэтому я получив задание, делаю копию ствола во временную ветку, работаю в ней спокойно, зная что моя работа не затронет работы остальных разработчиков, а завершив дело сливаю изменения в ствол и удаляю ветвь. Ветвь удалять после работы нужно, чтобы не увеличивать энтропию в проекте.
Для данных целей я использую директорию branches, таким образом эта директория может содержать временные ветви например такого вида: task_201, task_240 и так далее.
Создание ветви
Создать ветвь просто, для этого надо создать копию основной ветви и закомитить изменения. Например находясь в корне репозитория создадим временную ветвь:
svn copy trunk branches/task_201 svn commit branches/task_201 -m "Task 201. Класс для чтения конфигурации системы из XML" |
Или создадим ветвь соответствующую выпущенной версии 2.4.6:
svn copy trunk tags/2.4.6 svn commit tags/2.4.6 -m "Версия 2.4.6" |
Удаление ветки
Аналогично удалению папки:
svn delete branches/task_201 svn commit branches/task_201 -m "Работа завершена, удаляю ветку" |
Слияние веток
После завершения работы, необходимо слить изменения во временной ветке со стволом. Проще всего это сделать перейдя в директорию с основной веткой разработки (trunk) и выполнить команду merge:
svn merge ../branches/task_201 |
После чего разрешить конфликты (если имелись) и закомитить изменения:
svn commit -m "Слияние с веткой task_201" |
Перед выполнением слияния, во первых надо обновить код командой update, а во вторых очень жедательно посмотреть, что произойдет при слиянии не выполняя его в действительности:
svn merge ../branches/task_201 --dry-run |
Внимание! Иногда, по непонятной для меня причине, при указании короткой формы пути к ветке (../branches/имя_ветки) слияние не работает, поэтому приходится указывать полный путь: svn://server/имя_репозитория/branches/имя_ветки
Проблемы слияния веток в SVN
В случае если в ветке или в стволе файл был удален, переименован или перемещен, возникнет конфликт веток (tree conflict). Автоматически разрешить этот конфликт не получится, придется вручную переместить файл (или наоборот не перемещать), вручную слить два файла и только после этого сказать системе, что конфликт разрешен:
svn resolve --accept=working |
И закомитить изменения.
Еще немного рекомендаций
Из предыдущего пункта можно сделать вывод, что конфликт веток штука крайне неприятная и это действительно так. Отсюда две рекомендации:
- Если вы хотите изменить структуру проекта: переименовать файлы и каталоги, переместить файлы и так далее, то сделайте это в стволе и только после этого создавайте временную ветку.
- Не допускайте сильного расхождения ствола и ветки, это приведет к тому, что слить их вместе станет очень тяжело, если вообще возможно.
- Стремитесь к максимально частым коммитам, пусть даже и всего из пары строк — так даже лучше (но не забывайте, что комит не должен ломать проект). Чем короче цикл между получением последней версии кода из репозитория и последующим комитом, тем меньше вероятность получить конфликты в коде. Это важное правило, отнеситесь к нему серьезно и не думайте, что комит раз в неделю может быть безболезненным.
Спасибо за статью.
Дмитрий
15 января 10 4:26