Продолжение. Начало в № 2’2010
Денис ШЕхАлЕв
Основы систем управления версиями файлов
на примере Subversion (SVN)
Работа с ветвлениями
При работе над проектом особое внимание уделяется основному направлению разработки (trunk), то есть текущему состоянию проекта. Папки и файлы из trunk используются для отладки и тестирования проекта по месту.
Часто возникают ситуации, когда нужно вести две и более копий одного документа или проекта, отличающиеся между собой деталями. В этом случае если в проекте будет найдена общая ошибка в любой из копий, она потребует исправления во всех копиях.
Также часто возникают ситуации, когда при работе над проектом у вас появляется мысль, реализация и проверка которой займет больше чем день. В этом случае работа в основной ветви может привести к получению нерабочего проекта в ней или к созданию помех коллегам, которые работают вместе с вами над проектом.
Очень распространенная ситуация — это создание готовых слепков: релизов проекта, то есть сохранения состояния проекта в отдельное место, после которого файлы проекта здесь меняться не будут. Можно это сделать с помощью команды Export и хранения проекта в специальном месте, но в этом случае история проекта, которая хранится в SVN, будет оторвана от релиза. И если в релизе будут найдены ошибки, которые не были замечены ранее, потребуется исправить их вручную во всех копиях проекта.
Основная идея ветвления — это создание направления разработки (ветви), которое существует независимо от другого направления, но имеет с ним общую историю. В SVN есть команды, которые помогают сопровождать параллельные ветви файлов и каталогов. Они позволяют создавать ветви, копируя данные и запоминая, что копии связаны друг с другом. Кроме того, эти команды помогают дублировать изменения из одной ветви в другую. Наконец, они могут сделать так, что отдельные части рабочей копии будут отражать состояние различных ветвей, что позволит вам смешивать различные линии разработки.
Репозиторий SVN — это обычное хранилище файлов и папок. Хранить проекты в нем можно, как вам будет угодно. Но если уж использовать SVN, то нужно делать это правильно. Правила хорошего тона призывают
использовать следующую структуру оформления проектов в репозитории SVN:
./ корневой каталог репозитория
Project0
branch ветви проекта Project0
tag метки (ревизии) проекта Project0
trunk ствол (основное направление разработки) проекта
Project0
Project1
branch ветви проекта Project1
tag метки (ревизии) проекта Project1
trunk ствол (основное направление разработки) проекта
Project!
Важное замечание. При создании ветви информация не копируется. Любая ветвь — это всего лишь ссылка на файлы с определенным номером ревизии в репозитории. «Экономить» объем, который занимает репозиторий на жестком диске, — совершенно бессмысленное занятие.
Совет. Помните, trunk/branch/tag — это самые обычные папки, они не предписывают и не ограничивают использование репозитория SVN. Эти папки всего лишь помечают место, которое отводится разработчику для работы над проектом. То есть папка branch — это всего лишь рекомендованное место, где разработчик может проводить свои изыскания, папка tag — это рекомендованное место для хранения релизов проекта. Никто не запрещает вам хранить релизы и проводить изыскания в других папках репозитория, но для его упорядочивания лучше придерживаться правил.
Рассмотрим основные ситуации, возникающие при работе с ветвлениями.
Создание меток и ветвей (tag и branch)
Вернемся опять к нашим разработчикам Васе и Пете. Они закончили свой проект и теперь решили выпустить метку (tag) — релиз данного проекта под номером 1.0. Для этого нужно воспользоваться командой Branch/Tag (рис. 61).
Затем нужно указать полное имя места назначения метки и номер ревизии основного проекта, для которого создается метка. В данном примере метка создается в папке tags/release_1.0, и источником является последняя ревизия проекта demo_project, находящаяся в репозитории (рис. 62).
Создание ветви производится точно таким же образом, но ветви создаются в директории branch (рис. 63). После этих действий
( Ч J* IX JVJ «НА 'ШДГМШ глрв-с
^ ' t / '*** я«* - J X ^ 'ü1
ІМЧІ т'М'.рг!
11>м**ж=-
Рис. 61. Создание ветви/метки проекта в репозитории
_ Ш - ,_Ч., м і--------
ЬиИц І М I I 1
Рис. 62. Диалоговое окно выбора настроек создания метки проекта
Рис. 63. Диалоговое окно выбора настроек создания ветви проекта
OZEE
' Г. fi ‘:Ь— >
И<
->Л XI
»саг I
ft* - 1 trf-H*-.-, 1 lu-,^ [ 1
М J jrrtrM if dn№
И- о W * « -i - *r» py « =1. *=«■ 1£ 23 ЛХ-І =
' Mrn* jw 33 IMTfcrt* ИОІЛМ’І
■_э <*у.
г.
е '_іВН^Ц
_JAk
t
■J 1 J
hrc: гчиКІ: mWtttvM
\rtшЬЬи «гіОБ+П^іШ я/
Рис. 64. Состояние репозитория после создания метки и ветви проекта
состояние репозитория принимает вид, который изображен на рис. 64.
Важное замечание. Перед тем как делать ответвление от проекта, обязательно синхронизируйте свою рабочую копию с репозиторием командой Update. Но если вы внесли множество изменений в основную ветвь и не хотите их фиксировать в ней (например, проект не отлажен), то можно сделать branch, опираясь на состояние рабочей копии, а не репозитория. В этом случае будет создана ветвь, в которой будут зафиксированы все изменения.
Подсказка 1. Если вы выпустили релиз проекта, а в нем обнаружена ошибка, не устраняйте ее в метках (tags). Используйте один из двух вариантов: 1) Если нужно только устранить ошибку, то скопируйте метку (tag) в ветвь (branch). Устраните ошибку, сделайте новую метку, удалите ветвь. 2) Если устранение ошибки совмещено с модернизацией проекта, то выпустите новый релиз проекта.
Подсказка 2. Узнать, к какому репозиторию, проекту и ветви относится папка/файл, можно из свойств папки/файла, которая/который находится под контролем репозитория.
Переключение рабочей копии между ветвями
Переключение между любыми ветвлениями выполняется командой Switch (рис. 65). В качестве параметра следует указать путь к проекту в репозитории, на который нужно сделать переключение рабочей копии (рис. 66). При работе с командой Switch помните о следующем:
1. Файлы, которые находятся под контролем SVN, при переключении ветви заменяются на соответствующие файлы из другой ветви. Если файл присутствует только в одной из ветвей, то, соответственно, он будет автоматически удаляться и появляться (это нормальная работа данной команды, нет повода для беспокойства).
Рис. 65. Переключение рабочей копии на другую ветвь разработки
2. Изменения в рабочей копии обладают приоритетом перед состоянием файлов в репозитории. Если перед переключением вы их не зафиксировали, они останутся в рабочей копии. Если переключения происходят часто, то можно случайно зафиксировать эти изменения не в ту ветвь разработки.
Слияние ветвлений
В процессе работы над ветвлениями проекта возникают ситуации, когда нужно слить изменения, сделанные в одной из ветвей проекта, с изменениями в других ветвях или просто добавить изменения, сделанные в ветви, (например, новые функции) в другие ветви.
Эти действия в SVN выполняются с использованием команды Merge. Слить ветви можно только в рабочей копии одной из ветвей. При этом результат слияния будет в рабочей копии, и в случае ошибок слияния этот результат можно отменить командой Revert.
При слиянии ветвей, естественно, возникает множество конфликтов, подобных конфликтам, которые были рассмотрены в разделе о рабочей копии. Все эти конфликты придется разрешать вручную. Поэтому не стоит допускать так называемого «большого расхождения» ветвей разработки, так как в этом случае слияние ветвей становится сложным и запутанным процессом, который может привести к нежелательному результату.
При слиянии ветвей нужно помнить о следующем:
1. При обычном слиянии файл не замещается другим файлом. Файл рассматривается как набор строк. Итоговый файл составляется из строк файлов, которые участвовали в процессе слияния. Поэтому если бинарный файл будет обрабатываться как текстовый, то результирующий файл будет неработоспособен.
2. Переименование файла в SVN реализовано через механизм Copy/Delete, поэтому новый файл логически не связан со старым (кроме общей истории). И после слияния ветвей в проекте будут оба файла. Избегайте необдуманного переименования файлов и учитывайте переименование при слияниях. Рассмотрим процесс слияния demo_
project1 и его ветви demo_branch. Предположим, что Вася работает с ветвью demo_ branch, вносит изменения в файл hello.py и добавляет к проекту файл define.py. Петя, в свою очередь, работает в основной ветви разработки trunk и вносит изменения в файлы hello.py и bye.py. Состояние рабочих копий Васи и Пети перед слиянием показано на рис. 67.
Важное замечание. При работе с ветвлениями проверяйте, куда именно вы фиксируете изменения, чтобы не «потерять» их.
Рис. 68. Слияние ветвей в рабочей копии Пети
Рис. 69. Диалоговое окно выбора сценариев слияния ветвей
Рис. 70. Диалоговое окно выбора ветви источника для слияния
Вася и Петя фиксируют изменения в репозитории. Вася сообщает Пете, что закончил тестирование новых функций проекта, для которого он сделал ветвь. Петя, который работает в основной ветви разработки, решает сделать слияние ветвей (рис. 68). SVN предлагает три возможных сценария слияния ветвей (рис. 69). Для рассмотрения разницы этих сценариев положим, что А — это ветвь-приемник, в рабочей копии которой делают слияние, В — это ветвь-источник, с которой делают слияние. Сценарии слияния ветвей:
1. Merge a range of revisions. Этот сценарий работает следующим образом. SVN берет начальное и конечное состояние ветви В, вычисляет последовательные изменения в файлах этой ветви и последовательно применяет эти изменения на файлы ветви А. Если эти изменения вызовут конфликт, то его нужно будет разрешить, в противном случае произойдет слияние файлов.
2. Reintegrate a branch. SVN берет текущее состояние ветвей А и В, вычисляет, какие файлы нужно изменить для того, чтобы из А получить В, и сравнивает эти файлы. Если в этих файлах возникает конфликт, то его нужно будет разрешить, в противном случае произойдет слияние файлов.
3. Merge two different trees. Самый простой и в то же время опасный сценарий слия-
Рис. 71. Окно протокола слияния ветвей проекта
I F I - >.ІСІ *1
йм- ''РРП D-4 п*#*+с« г,Ч«-г Сгрнд St
0^1“ г -У ' * S :,ta■s, . Г1те * * **11
W# 1-І Ег .dscv-'&ra jsr,* *J Ё]*ЧН-и
ґім
іІГ
Г***
Я'гіг с-. j"i> > -п ■
fir
Рис. 72. Состояние рабочей копии Пети после слияния ветвей
Jaijsi
.'.‘i j*#«! I
Чим»-— - -----------------------------
К«И.твияз I
Інчри ГИМН ИЛИ І
□ .toe-. nnrj. ndtal
0 -И Ш&мі nm*
О Зил>игчтп9пк: lari
P Vbi!/ V-*-i J
г ■ ы I 1 |Ц І
Рис. 73. Диалоговое окно для задания комментария при фиксации результата слияния меток
ния. Он работает следующим образом: SVN берет текущее состояние ветвей А и В, вычисляет, какие файлы нужно изменить для того, чтобы из А получить В, и делает эту замену в рабочей копии через механизм Delete/Copy. В этом случае не возникает никаких конфликтов, но если в А были какие-либо изменения, то они пропадут.
В нашем случае Петя выбирает второй вариант сценария и указывает, что нужно делать слияние с ветвью demo_branch (рис. 70).
Результат работы команды Merge показан на рис. 71. Естественно, при слиянии возникли конфликты, которые нужно разрешить (рис. 72).
После разрешения конфликтов Петя фиксирует изменения в репозитории и обязательно комментирует свои действия (рис. 73). Как разрешаются конфликты в SVN, мы рассматривали в разделе работы с рабочей копией. Все, слияние ветви demo_branch с основной ветвью разработки выполнено. ■
Окончание следует