Perforce: еще одна система управления версиями

Эта статья является логическим продолжением серии материалов под заголовком "Системы управления версиями для программистов и не только" (см. КГ №№ 12-16). Тогда я рассказывал об идеях, легших в основу систем управления версиями (СУВ), и почему они так важны. Не забыл я и о практике, рассказав об одной из известнейших СУВ — svn.

Сегодня я продолжаю рассказ об СУВ и посвящаю его еще одному известному продукту — Perforce. Нельзя сказать, что perforce в корне отличается от svn: в основе их обоих лежит модель Copy-Modify-Merge. Для каждой из систем есть множество отличных визуальных инструментов (да-да, больше никакой командной строки). Также доступ к репозиторию в обоих случаях можно получить через веб- интерфейс. История развития каждой из систем насчитывает несколько лет, и за это время все ошибки были найдены и вычищены. В конце концов, в большинстве своем мы работаем с СУВ не через командную строку или отдельный графический клиент, а используем некоторую среду разработки (eclipse, idea… photoshop или даже word), к которой есть плагины, добавляющие новое меню или панель кнопок с операциями над репозиторием. Так что вам почти не придется выходить из вашего любимого редактора, чтобы в конце рабочего дня сделать commit проекта на сервер.

В идеале хороший плагин скрывает особенности используемой СУВ, так что переход с SVN на perforce (или наоборот) будет почти незаметным. Теперь закончим с затянувшимся вступлением и перейдем ближе к делу. Так же, как и для SVN, "сердцем" perforce является сервер, на котором размещен репозиторий (в терминологии Perforce — depot). Первое отличие в том, что если для работы с SVN мы могли не запускать какой-то специальный сервис, а работать напрямую с файловой системой svn, то для perforce сервер должен быть. В практике это не очень большое различие, т.к. СУВ используются в основном для поддержки коллективной работы, а там без выделенного сервера никак. Второе отличие важнее: на стороне клиента Perforce ничего не хранит. К примеру, когда я извлекал из svn-репозитория проект, то к каждой папке проекта был добавлен служебный каталог с именем ".svn". В этом каталоге хранится информация о том, из какого репозитория были взяты данные (соответственно, куда их помещать). Там же хранились Pristine copy (оригинальные копии файлов после их извлечения из репозитория). Так мы могли в любой момент времени сказать "diff" или "revert", чтобы увидеть то, какие изменения были внесены в рабочую копию файлов, или затем отменить эти правки. Для Perforce эти операции невозможны без постоянного подключения к серверу. Это отличие диктует и некоторые особенности рабочего цикла "взять файлы из хранилища — исправить — поместить обратно", но об этом чуть позже и на примерах. Прежде всего, вам нужно с сайта сайт загрузить сервер perforce (в одной "упаковке" вместе с сервером идут и клиентские утилиты: как консольные, так и графические). Там же вы можете найти плагины perforce для интеграции с photoshop или office. После установки у вас в меню ПУСК появится несколько утилит. Во-первых, утилита p4diff, которая служит для сравнения текстовых файлов и поиска различий между ними (очень неудобный инструмент). Затем утилита P4Merge, служащая также для сравнения файлов, определения различий и последующего слияния. Сравнению подлежат два файла, созданных на базе одной общей версии, таким образом, что новый файл должен содержать правки, выполненные во всех этих файлах (а этот инструмент как раз очень удобен). Похожа на p4merge и утилита p4winmerge (ее отличие в том, что интерфейс p4merge будет одинаковым для различных операционных систем, а p4winmerge работает только для windows). Непосредственно для работы с хранилищем используются утилиты p4 (консольная утилита — мы ее использовать не будем), P4V (именно эту утилиту я буду использовать) и P4Win (отличие от предыдущей только в интерфейсе).

При первом запуске p4v нас попросят ввести параметры подключения к Perforce-серверу. В графу Server вводится имя сервера (если вы работаете локально, то оставьте поле пустым). Затем в графе Connect as нужно ввести имя пользователя и его пароль. При первом запуске очевидно, что никаких пользователей нет, и их нужно создать с помощью расположенной на этом же диалоговом окне кнопки New (если вы не купили лицензию на perforce, то можно создать не более двух учетных записей). Следующий шаг: в графе Open workspace мы должны либо выбрать, либо создать новое рабочее окружение. Как только вы нажмете на кнопку New, в появившемся окне нужно ввести название Workspace, а затем — самое интересное — нужно настроить workspace, указав правила доступа к нему и правила отображения имен. Во-первых, в графе Host указывается, с какой машины в сети вы будете иметь право доступа к workspace (если поле пустое, то со всех). Затем графа Root — в ней указывается путь к каталогу на вашем компьютере, куда будут загружаться файлы из репозитория. В случае, когда доступ к репозиторию выполняется с нескольких машин сети, не всегда возможно сделать так, чтобы пути к workspace совпадали. Например, на первой машине я указал Root путь H:\docs_xp\My temps\perf_jim, а на второй машине диска H: нет вообще. К счастью, есть понятие Альтернативных путей: введите второй путь в графу AltRoots, и все заработает. Следующим идет набор checkbox'ов, управляющих поведением perforce (оставьте их как есть). Последний параметр View служит для создания правил отображения путей в хранилище (depot'е) на локальную файловую систему. Каждое правило записывается с новой строки и состоит из двух частей разделенных проблем: "путь-в-хранилище" и "путь у нас". Дело в том, что в depot'е может храниться огромное количество файлов, и не все из них нужны для просмотра (а к некоторым файлам доступ нужно вообще закрыть). Например, вот эта строка (я создаю workspace с именем jim):

//depot/... //jim/...
Говорит, что все содержимое репозитория (путь должен начинаться с символа "//", а символы "…" означают все, что находится внутри) должно быть отображено в корень папки Root для workspace с именем "jim". Можно действовать и более избирательно:
//depot/project/manual/... //jim/files/documents/...

А вот еще пример, в котором идет отображение не всего, что находится внутри папки manual, на папку documents, а только файлов (но не вложенные подпапки).
//depot/blz/project/* //jim/blz/files/*

Есть еще вариант синтаксиса, когда некоторому пути предшествует знак "-". Это значит, что часть дерева репозитория будет недоступна (две последние строки запретили отображение файлов в каталоге depot и подкаталога docs):
//depot/blz/project/... //jim/blz/files/...
-//depot/blz/project/docs/... //jim/blz/files/docs/...
-//depot/blz/project/* //jim/blz/files/*

Сразу советую создать нормальную структуру каталогов в depot'е подобную той, которую мы использовали при работе с SVN:
//depot/projects/notepad/trunk/... //jim/trunk/...
//depot/projects/notepad/branches/... // jim/branches/...

А еще лучше для каждого проекта создать собственный depot. Для этого нужно из командной строки выполнить:
p4.exe depot notebook

Как только вы запустите эту команду, появится окно блокнота — сразу закройте его, не внося никаких правок. Теперь при создании нового workspace укажите в строке View следующий код:
//notebook/trunk/... //jim/trunk/...
//notebook/branches/... //jim/branches/...

Теперь, создав и настроив workspace, давайте попробуем положить на сервер пару документов. Внешний вид окна клиента perforce показан на рис. 1. Условно окно разделено на две области: "файлы где-то там" и "всякое разное". Внизу окна находится окошко, куда выводится журнал выполняемых операций. Советую посматривать на него одним глазом, т.к. в случае, если вы хотите выполнить некоторую операцию (например, добавить в depot файл), и эта операция завершается ошибкой, никаких всплывающих окон с надписью "бум, perforce поломался" не будет. Вместо этого в журнал просто добавится строка с сообщением об ошибке, и ее легко пропустить, не заметив. Теперь разберем устройство клиента p4v подробнее — сначала "файлы где-то там". Левая панель состоит из двух закладок: Depot и Workspace. В них, соответственно, отображаются файловые деревья того, что находится на сервере в Depot, и того, что находится на вашем компьютере в workspace. Все файлы имеют специальные иконки, показывающие состояние файла, синхронизирован ли он с Perforce. Так, файлы, не помещенные в perforce, не имеют никаких пометок, а те, которые синхронизированы с хранилищем, имеют пометку в виде небольшого зеленого кружка и т.д. Для работы с файлами используется контекстное меню. Давайте попробуем сделать типовой цикл: "извлечь — изменить — сохранить". И тут же нас ждут неожиданности: контекстное меню выглядит несколько странно… нет знакомых нам функций update, commit, а команда удаления файла аж в трех экземплярах. Дело в том, что идеология работы perforce отличается (пусть и не очень сильно) от той, с которой мы знакомились в svn, плюс есть отличия в используемой терминологии. Так что придется начать с начала: во-первых, добавим в папку workspace текстовый файл X.txt (именно туда, т.к. операция добавления файла не удастся, если файл не будет внутри workspace). Затем в закладке Workspace вызываем контекстное меню и функцию mark for Add (если все хорошо, то должен поменяться внешний вид иконки файла). Затем я хочу отправить изменения на сервер — для этого можно либо снова вызывать контекстное меню, выбрав именно тот файл, который вы пометили для добавления в depot, и затем меню Commit. В появившемся окне осталось только ввести текст примечания для отправляемых изменений (см. рис. 2).

Второй вариант работы с commit'ами более удобен: нужно вызывать меню view -> pending changelist. На правой панели окна p4v должно появиться дерево с единственным узлом default, внутри которого хранятся имена файлов, помеченные мною для добавления в depot. В Perforce введено новое понятие changelist: все выполненные вами изменения помещаются внутрь специального объекта changelist так, чтобы вы могли в любой момент времени просмотреть запланированные правки и иметь возможность либо послать их на сервер (контекстное меню, операция Submit), либо отменить (контекстное меню, операция Revert). Более того, если вы вызовете контекстное меню, то увидите, что мы можем создать еще один объект changelist, а затем с помощью перетаскивания наполнить его собственными операциями. Не важно, будете ли вы использовать один changelist или несколько, perforce выполняет все операции commit'а атомарно. Это значит, что, если changelist состоит из нескольких шагов, и один из шагов не удалось завершить (например, из-за конфликта правок), то и все остальные шаги в составе changelist будут отложены.

После того, как changelist был отправлен на сервер, он попадает в категорию Submitted. Если вызывать меню View -> submitted changelists, то вы увидите окно, в котором перечислены в форме таблицы все ранее отправленные на сервер изменения. Для каждого изменения можно просмотреть комментарий к нему, список задействованных файлов, а при двойном клике по файлу увидеть и его содержимое. Для быстрого поиска изменений, выполненных конкретным человеком, используйте расположенное вверху окна текстовое поле Filter by user (можно фильтровать и по workspace'у, из которого была инициирована операция commit'а). Для каждого из файлов можно просмотреть историю внесенных в него правок (контекстное меню на имени файла и пункт File History). Для файла будут выведены все changelist'ы, в которых был задействован текущий файл. Так вы узнаете, кто и когда выполнил модификацию файла, а также каково было его содержимое на определенном шаге. Пока отличия в иделогии svn-perforce невелики, но вот на стадии правки содержимого файла нас ждут первые сюрпризы. Когда мы извлекли проект из svn, то могли редактировать файлы в любой момент. Фактически мы вспоминали о том, что файлы управляются СУВ только тогда, когда уже хотели уходить домой и делали завершающий commit. В Perforce все по-другому: если выполнить двойной клик по файлу в workspace, то откроется его редактор, но сохранить изменения будет невозможно. Дело в том, что сразу после извлечения содержимого из depot'а всем файлам будут поставлены флажки readonly. И когда вы пытаетесь после правки сохранить файл, то типовой редактор (вот именно, типовой) это сделать вам не даст. Для правильного редактирования файлов в perforce вам нужно вызвать в контекстном меню на файле пункт Check out. После чего с файла будет убран флажок readonly, и вы можете изменять файл без проблем (тут же, не дожидаясь завершения правки файла, в текущий changelist будет добавлен новый элемент — задание отправки файла обратно на сервер). Перед отправкой данных бывает полезно просмотреть выполненные изменения в тексте некоторого файла — для этого вызовите контекстное меню на нем и выберите пункт Diff. В появившемся окне с настройками сравнения файлов (можно сравнивать не только две различные ревизии одного файла, но и два совершенно разных файла), поставьте отметки радиокнопок напротив Workspace revision и Lastest revision. Кроме функции сравнения содержимого файлов, diff умеет сравнивать и каталоги (просто вызовите контекстное меню не на файле, а на папке). Так вы увидите красивое окошко, где показано, какие файлы и каталоги были добавлены/удалены/изменены между ревизиями (см. рис. 3).

Теперь перейдем к рассмотрению методик работы с тегами и ветками. Во-первых, терминология Perforce и здесь отличается от терминологии SVN. Напоминаю, что основная идея ветвей была в возможности параллельной работы над проектом, над основным стволом разработки и экспериментальными версиями. Например, работа ведется одновременно над версией 1 и версией 2. Однако поддержка ветвей и тегов малополезна без средств для слияния изменений (перенос правок, выполненных в одной ветви, в другую). У Perforce при работе с ветвями есть два термина: intergrate и resolve. Первый означает то, что мы создаем копию ветви разработки (после integrate проекты развиваются параллельно). Завершает же процесс resolve, который сливает изменения в единое целое (также resolve используется, когда возникает конфликт из-за одновременной модификации одного и того же файла). Разветвить (создать копию можно как отдельный файл, так и целый каталог или весь проект). В любом случае сначала нужно выделить тот файл или каталог, который вы хотите разветвить, затем вызвать через контекстное меню integrate. Если вы разветвляете файл, то на первой закладке нужно ввести путь, куда файл будет скопирован. Так, я для файла //notebook/trunk/1.txt указал путь местоназначения //notebook/branches/mono2/1.txt". Если разветвляете каталог, то переключитесь на вторую закладку, затем кнопка New, и в появившемся диалоговом окне я ввел название ветки и правило копирования:
//notebook/trunk/... //notebook/branches/bra001/...

В любом случае после завершения команды integrate нужно выполнить отправку на сервер запланированных изменений. Все ветки показываются в окне workspace и depot'а, редактирование их выполняется без предварительного (как было в svn с командой switch) переключения между ветками. Если вы хотите посмотреть, как изменялся файл во времени (история ревизий), то выделите его и вызовите контекстное меню revision graph (см. рис. 4). Для того, чтобы выполнить обратный процесс переноса правок из ветки в основной ствол разработки, снова используйте функцию integrate, только теперь укажите направление, обратное первому. Наверняка в ходе слияния возникнет конфликт — тогда нужно для конфликтующих файлов вызвать контекстное меню и пункт Resolve. Ну, а дальше дело практики: в окне редактора merge с окошками: общая версия до разветвления и две версии измененные (в основном стволе и в ветке) — нужно собрать один общий файл (со всеми правками) и отправить его на сервер. На этом все.

black-zorro@tut.by, black-zorro.com


Компьютерная газета. Статья была опубликована в номере 24 за 2008 год в рубрике программирование

©1997-2024 Компьютерная газета