понедельник, 30 марта 2009 г.

Использование WebDAV для доступа к Bazaar-серверу

При совместной работе группы разработчиков над проектом с использованием Bazaar практически всегда необходимо организовывать некоторое центральное хранилище (центральный сервер) для рабочих веток. Имеется несколько вариантов организации такого сервера, поскольку сам Bazaar поддерживает несколько транспортных протоколов для удаленной работы. Кратко рассмотрим имеющиеся варианты.

Варианты доступа к удаленному серверу

  • bzr:// — "умный" (smart) протокол Bazaar. Это наиболее функциональный и производительный протокол удаленного доступа, использующий встроенный в Bazaar сервер. К сожалению, на данный момент, не имеет возможности аутентифицировать пользователей и управлять доступом. По этим причинам не рекомендуется использовать его самостоятельно, а только в связке с SSH или HTTP/HTTPS:
    • bzr+ssh:// — использует bzr:// протокол через SSH-туннель. Совмещает функциональность и производительность протокола bzr:// с безопасностью протокола SSH. Наиболее часто используемый в среде Unix/Linux и наиболее часто рекомендуемый протокол удаленного доступа.
    • bzr+http:// — использует bzr:// протокол совместно с web-сервером Apache и модулем FastCGI или mod_python. Для авторизации пользователей используются механизмы, встроенные в Apache.
  • sftp:// — для доступа используется протокол SFTP, поддерживаемый большинством SSH серверов. Может быть хорошей альтернативой bzr+ssh://, например, в случае отсутствия на сервере Bazaar.
  • ftp://, aftp:// — доступ с использованием пассивного (и соотв. активного) режимов FTP. Позволяет давать доступ на запись, но имеет проблемы с безопасностью.
  • http://, https:// — доступ только для чтения с использованием протоколов HTTP и HTTPS. Хороший вариант если нужен только доступ на чтение.
Из всех рассмотренных выше протоколов только bzr:// (bzr+ssh:// bzr+http://) поддерживают работу с подключаемыми модулями или плагинами (plugins) Bazaar на сервере, т.к. используют встроенный в Bazaar сервер. Остальные же протоколы только предоставляют доступ локальному клиенту Bazaar к данным на удаленном сервере.

Зачем нужен доступ по протоколу WebDAV?

Достаточно часто встречается ситуация, когда для обеспечения политики безопасности, или по другим причинам, нет возможности использовать ни один из перечисленных выше протоколов. Такая ситуация может возникать в случае если нужен удаленный доступ на запись, но нельзя использовать SSH/SFTP, потому что необходимо создавать системные учетные записи. При этом FTP тоже отпадает, поскольку он считается недостаточно безопасным.
Именно для таких случаев был создан плагин для bzr, который позволяет организовать удаленный доступ по протоколу WebDAV.
WebDAV — это набор расширений для протокола HTTP, позволяющий пользователям совместное редактирование и управление файлами на удаленных WEB-серверах. Таким образом, он, как и HTTP/HTTPS, обеспечивает для Bazaar доступ к данным на удаленном сервере, но предоставляет при этом также и возможность их изменения. Одно из основных преимуществ использования WebDAV — это возможность использования стандартных средств HTTP-сервера для управления аутентификацией и доступом пользователей.
Для работы через WebDAV нам понадобится установить плагин на стороне клиента (на локальной машине) и настроить HTTP сервер (в нашем примере Apache) для работы с WebDAV.

Установка плагина WebDAV

Плагин WebDAV для Bazaar можно найти на сайте Launchpad: https://launchpad.net/bzr.webdav. Для получения плагина сделаем копию ветки с Launchpad и затем установим плагин.

Установка только для текущего пользователя

Наиболее просто установить плагин для текущего пользователя. На Unix/Linux системах плагины устанавливаются в каталог ~/.bazaar/plugins/ (на Windows используется каталог C:\Documents and Settings\USERNAME\Application Data\2.0\bazaar\plugins). Перейдите в каталог plugins и выполните команду branch:
$ cd ~/.bazaar/plugins/ $ bzr branch lp:bzr.webdav webdav Плагин будет установлен в подкаталог webdav.

Установка для всех пользователей

В данном случае модуль устанавливается в системной директории для поиска модулей bzrlib/plugins (на Unix системах это может быть /usr/lib/python2.5/site-packages/bzrlib/plugins/).
$ bzr branch lp:bzr.webdav $ cd bzr.webdav/ $ sudo python setup.py install

Проверка наличия плагина WebDAV

Для проверки наличия плагина необходимо использовать команду plugins. Эта команда выведет список всех установленных плагинов, их версий, и краткое описание каждого плагина. В этом списке должен присутствовать плагин webdav:
$ bzr plugins
...
webdav 1.12
  An http transport, using webdav to allow pushing.
...

Настройка сервера Apache

Теперь рассмотрим настройки HTTP сервера Apache. Прежде всего для Apache должен быть установлен модуль mod_dav. Конфигурация для этого модуля будет выглядеть приблизительно следующим образом:
<IfModule mod_dav.c>

  Alias /bzr /var/www/bzr

  <Directory /var/www/bzr>
    Dav On
    DirectorySlash Off
    DavDepthInfinity On

    AuthType Basic
    AuthName "Bazaar server"
    AuthUserFile /etc/apache2/dav.users
    Require valid-user
  </Directory>
</IfModule>
Рассмотрим настройки подробнее:
  • директива Alias устанавливает связь между путем в URL (/bzr) и каталогом /var/www/bzr, где будут хранится ветки;
  • опция Dav On включает WebDAV для /var/www/bzr;
  • опция DirectorySlash Off выключает перенаправление в случае если в конце URL для каталогов не указан '/'. (Такие перенаправления не очень хорошо работают с Bazaar);
  • опция DavDepthInfinity On включает обработку PROPFIND запросов с заголовком Depth: Infinity;
  • оставшиеся опции настраивают простую HTTP авторизацию;

Работа с сервером

После перезагрузки Apache вы сможете работать с удаленными ветками с помощью протокола http+webdav:// следующим образом: $ bzr branch http+webdav://user@a.site/bzr/branch Кроме использования HTTP можно настроить работу WebDAV и по протоколу HTTPS.

Сохранение пароля

Если вы используете на сервере авторизацию и не хотите каждый раз набирать пароль, то можно воспользоваться клиентским файлом конфигурации authentication.conf. Этот файл должен находится в каталоге с файлами конфигурации Bazaar (по умолчанию на Unix - ~/.bazaar). В файле для WebDAV должна быть следующая информация:
[myprojects] scheme = http host = host.com user = ivan password = secret Обратите внимание, что значение параметра scheme должно быть http для http+webdav:// и https для https+webdav://.
Один из минусов использования файла authentication.conf в том, что (на данный момент) пароли хранятся в виде простого текста.

Резюме

Подытоживая, можно сказать, что WebDAV может быть хорошей альтернативой для bzr+ssh://, в случае если вы не хотите создавать системные учетные записи для каждого пользователя и в то же время предоставлять более безопасный доступ (при использовании HTTPS) чем ftp://.

четверг, 26 марта 2009 г.

Работа с ветками: push, pull, merge (Часть 2)

Продолжаем начатую тему работы с ветками. Рассмотрим практическое применение команд push, pull, merge на двух примерах: синхронизация веток между несколькими компьютерами (одиночная работа), совместная работа над одним проектом в небольшом коллективе.

Сценарий №1

Петр работает над своим проектом FuzzyCoding на нескольких компьютерах (например, на домашнем и на рабочем). Перед тем как уйти с одного рабочего места на другое Петр фиксирует сделанные изменения, чтобы можно было продолжить работу на другом компьютере. Петр использует синхронизацию своих веток на разных компьютерах при помощи USB-flash диска. Когда он заканчивает работу, то  копирует новые ревизии из локальной ветки на флеш-диск командой bzr push. Придя на другое рабочее место синхронизирует локальную ветку, копируя новые ревизии с флеш-диска командой bzr pull.

Рассмотрим этот сценарий более детально.

Подготовка USB-flash диска

Петр уже создал новую ветку на своем компьютере и работает в ней некоторое время. Для переноса своей ветки на другой компьютер он решил использовать USB-диск. Петр может просто использовать команду bzr push в своей рабочей ветке, чтобы передать ревизии и рабочие файлы на USB-диск. Базар полностью поддерживает такую работу.

Однако, имеет смысл сделать некоторые подготовительные действия на USB-диске. Дело в том, что команда push не только копирует новые ревизии в другую ветку, но еще и обновляет рабочие файлы в другой ветке в том случае, если ветка локальная. Поскольку подключенный USB-диск практически всегда является локальным диском, то bzr будет стараться создать и обновить ваши рабочие файлы. В то же время для синхронизации веток вам совсем не требуется переносить и рабочие файлы (поскольку они присутствуют в истории и могут быть легко восстановлены). Поэтому с практической точки зрения необходимо исключить рабочие файлы с USB-диска и синхронизировать только историю.

Для одной ветки это можно сделать так: создать новую ветку и удалить дерево рабочих файлов.

E:\USB_sync>bzr init
Created a standalone tree (format: pack-0.92)

E:\USB_sync>bzr remove-tree

Здесь мы создали новую ветку командой init в каталоге E:\USB_sync (E: это наш USB-диск при использовании Windows, на Linux флеш-диски монтируются в /mnt/flash или другое место). А затем удалили рабочее дерево командой remove-tree.

Другим вариантом является создание общего репозитория для веток на USB-диске, новые ветки в котором автоматически будут создаваться без рабочих файлов:

E:\>bzr init-repo --no-trees USB_repo
Shared repository (format: pack-0.92)
Location:
  shared repository: USB_repo

Опция командной строки --no-trees указывает, что по умолчанию для всех веток в этом репозитории рабочие файлы создаваться не будут.

Копирование новых ревизий на USB-диск

Для отправки новых ревизий на USB-диск Петр использует команду push:

C:\work\bzr-day\FuzzyCode>bzr push E:\USB_sync
Pushed up to revision 3.

Создание копии ветки на другом компьютере

Придя на другое рабочее место со своим USB-диском Петр создает копию ветки для работы:

C:\work\bzr-day>bzr branch E:\USB_sync FuzzyCode
Branched 3 revision(s).

Теперь он может продолжать работу со своей веткой FuzzyCode. По окончании работы Петр снова отправляет новые ревизии на USB-диск командой push.

Синхронизация рабочей ветки с USB-диском

Для получения новых ревизий с USB-диска в свою рабочую ветку Петр использует команду pull:

C:\work\bzr-day\FuzzyCode>bzr pull E:\USB_sync
All changes applied successfully.
Now on revision 4.

Рабочая ветка успешно обновлена, можно продолжать работу.

Иногда ветки могут разойтись

Если же Петр забыл синхронизировать рабочую ветку с USB-диском и зафиксировал новые изменения, то при попытке сделать push или pull он получит сообщение, что ветки "разошлись". В этом случае Петр должен объединить ветки командой merge:

C:\work\bzr-day\FuzzyCode>bzr merge E:\USB_sync
+N  dir/
+N  foo.txt
All changes applied successfully.

C:\work\bzr-day\FuzzyCode>bzr commit -m "Объединение рабочей ветки с копией ветки на USB-диске"
Committing to: C:/work/bzr-day/FuzzyCode/
added dir
added foo.txt
Committed revision 5.

После этого команда push позволит синхронизировать копию на USB-диске с рабочей веткой.

Мы рассмотрели простой пример синхронизации веток между несколькими компьютерами. В качестве промежуточной ветки также можно использовать и некоторый общедоступный сервер, например SFTP/FTP.

В следующей части мы рассмотрим сценарий совместной работы над проектом в небольшом коллективе.

понедельник, 23 марта 2009 г.

Работа с ветками: push, pull, merge (Часть 1)

Ранее мы рассмотрели базовую работу с ветками. В дополнение к branch и merge, сегодня мы рассмотрим еще несколько дополнительных команд. В первой части рассмотрим как они работают. Во второй части рассмотрим пример их использования.

Команды

branch
Ветка
Создать новую ветку
merge
Объединить
Объединить изменения из разных веток
pull
Тянуть, втягивать (направление движения: на себя)
Получить (загрузить) изменения из другой ветки в рабочую ветку
push
Толкать, выталкивать (направление движения: от себя)
Передать (отправить) изменения из рабочей ветки в другую ветку
missing
Недостающий, отсутствующий
Просмотр набора ревизий, различающихся между двумя ветками

Графы ревизий

Рассматриваемые команды в первую очередь работают с историей изменений. История хранится в bzr в виде DAG, поэтому в описании работы будем использовать соответствующие графы, помечая знаком "O" отдельные (ключевые) ревизии. Считаем что ревизии растут снизу вверх, т.е. вверху более новые. Рассматривая две родственные ветки, мы можем иметь 4 возможных типа графов:

O Рабочая ветка, другая ветка
|
O
Ветки содержат одинаковый набор ревизий
O Рабочая ветка
|  O Другая ветка
| /
O
|
O
Ветки содержат различный набор ревизий, история "разошлась"
O Рабочая ветка
|
O
Другая ветка
|
O
Рабочая ветка является продолжением другой ветки; рабочая ветка имеет новые ревизии (относительно истории другой ветки)
O Другая ветка
|
O
Рабочая ветка
|
O
Другая ветка является продолжением рабочей ветки; в рабочей ветке отсутствуют новые ревизии (относительно истории другой ветки)

   
Команда branch

Команда branch создает копию существующей ветки. После выполнения этой команды обе ветки содержат одинаковый набор ревизий, что соответствует графу 1.

Команда merge

Команда merge используется в случаях, когда две ветки "разошлись", т.е. имеют различный набор ревизий, что соответствует графу 2. Эта команда объединяет ревизии рабочей ветки с другой веткой. После фиксации объединения граф ревизий будет содержать все ревизии из другой ветки. Другая ветка при этом не изменяется.

Граф ревизий после объединения:

O Рабочая ветка
|\
O \
|  O
Другая ветка
| /
O
|
O

Такой граф уже ближе к графу номер 3, когда рабочая ветка является продолжением другой ветки.

В случаях, когда история еще не разошлась, имеется возможность использовать команды push и pull для синхронизации веток.

Команда push

Команда push используется для синхронизации другой ветки с рабочей веткой. В случае, когда рабочая ветка содержит новые ревизии, которые отсутствуют в другой ветке (как показано на графе 3), пользователь может отправить новые ревизии в другую ветку командой push. После выполнения команды push обе ветки будут синхронизированы (см. граф 1).

C:\work\bzr-day\a>bzr push ../other
All changes applied successfully.
Pushed up to revision 3.

Если обе ветки уже синхронизированы, то команда push сообщит об этом::

C:\work\bzr-day\a>bzr push ../other
No new revisions to push.

В случае, когда история двух веток разошлась, команда выдаст ошибку и предложит сделать merge:

C:\work\bzr-day\b>bzr push ../a
bzr: ERROR: These branches have diverged.  Try using "merge" and then "push".

Команда push чаще всего используется для публикации рабочих веток на общем сервере, чтобы другие участники проекта могли получить к ней доступ. Если ветка еще не существует, то она будет автоматически создана.
Команда pull

Команда pull является полной противоположностью команде push: она предназначена для синхронизации рабочей ветки с другой веткой. В случае, когда другая ветка содержит новые ревизии, которые отсутствуют в рабочей ветке (как показано на графе 4), пользователь может загрузить новые ревизии из другой ветки командой pull. После выполнения команды pull обе ветки будут синхронизированы (см. граф 1).

C:\work\bzr-day\other>bzr pull ../a
All changes applied successfully.
Now on revision 3.

Если обе ветки уже синхронизированы, то команда pull сообщит об этом::

C:\work\bzr-day\other>bzr pull ../a
No revisions to pull.

В случае, когда история двух веток разошлась, команда выдаст ошибку и предложит сделать merge:

C:\work\bzr-day\b>bzr pull ../a
bzr: ERROR: These branches have diverged. Use the merge command to reconcile them.

Команда pull часто используется для обновления локальной копии ветки, которая находится на общем сервере.
Команда missing

Команда missing — это информационная команда. Она позволяет сравнить наборы ревизий в двух ветках и увидеть какие ревизии содержатся в одной ветке и отсутствуют в другой. Команду missing удобно использовать перед запуском команд push, pull или merge, чтобы яснее представлять себе общий граф ревизий двух веток.

Вывод команды missing разделен на 2 части: сначала выводится список ревизий в рабочей ветке, которые отсутствуют в другой ветке; затем список ревизий из другой ветки, которые отсутствуют в рабочей ветке. Вывод списка ревизий аналогичен выводу команды log.

C:\work\bzr-day\b>bzr missing ../a
You have 1 extra revision(s):
------------------------------------------------------------
revno: 3
committer: Базарный день <ru_bzr@googlegroups.com>
branch nick: b
timestamp: Mon 2009-03-23 08:47:47 +0200
message:
  Новая ревизия в ветке b



You are missing 1 revision(s):
------------------------------------------------------------
revno: 3
committer: Базарный день <ru_bzr@googlegroups.com>
branch nick: a
timestamp: Mon 2009-03-23 08:47:39 +0200
message:
  Новая ревизия в ветке a

Здесь мы видим, что история двух веток разошлась после ревизии 2, поскольку обе ветки содержат новую ревизию 3, но в каждой ветке это своя ревизия (см. граф 2).

Если история веток еще не разошлась (см. графы 3 и 4), то команда missing покажет только новые/недостающие ревизии:

C:\work\bzr-day\a>bzr missing ../other
You have 1 extra revision(s):
------------------------------------------------------------
revno: 3
committer: Базарный день <ru_bzr@googlegroups.com>
branch nick: a
timestamp: Mon 2009-03-23 08:47:39 +0200
message:
  Новая ревизия в ветке a


C:\work\bzr-day\other>bzr missing ../a
You are missing 1 revision(s):
------------------------------------------------------------
revno: 3
committer: Базарный день <ru_bzr@googlegroups.com>
branch nick: a
timestamp: Mon 2009-03-23 08:47:39 +0200
message:
  Новая ревизия в ветке a

Обе ветки синхронизированы:

C:\work\bzr-day\a>bzr missing ../a
Branches are up to date.

Итак, в первой части статьи было показано как работают команды push, pull, missing. В второй части этой статьи рассмотрим сценарий работы с использованием этих команд.

воскресенье, 15 марта 2009 г.

Начинаем работу с bzr: базовый набор команд (Часть 2)

В первой части мы рассмотрели работу с одной веткой. Рассмотрим теперь работу с несколькими ветками.
Сценарий работы

Создадим копию ветки для параллельной работы. Изменим некоторые файлы в старой и новой ветках и зафиксируем новое состояние. Объединим изменения в двух ветках.

Для чего нужны дополнительные ветки?

Использование веток — это неотъемлемая часть при распределенной работе. Фактически каждый участник проекта работает в своей ветке на своем компьютере, периодически рабочие ветки объединяются в главную или интеграционную ветку, которая считается основной веткой проекта.

Часто ветки используются, чтобы разделить разработку нового функционала программного продукта и поддержку выпущенных версий. В этом случае выпущенные версии (release — релизы) живут в своих собственных ветках. Как правило в релизных ветках только исправляются найденные ошибки, например, исправления ошибок из основной ветки переносятся (портируются) в релизную ветку. Другой тип веток — функциональные ветки (feature branches). Функциональные ветки используются для работы над одной конкретной задачей: реализации одной новой функции, исправления одного найденного дефекта и т.п.. Функциональные ветки удобно использовать для работы над экспериментальными вещами, про которые заранее неизвестно: выйдет что-либо полезное или нет. Независимо от стиля работы (централизованный или распределенный) или от того, работаете вы в одиночку или группой, использование функциональных веток позволяет более эффективно работать над проектами. Функциональные ветки помогают сфокусировать усилия при работе над конкретными задачами. Когда работа над конкретной задачей закончена, функциональная ветка объединяется с основной веткой проекта. (О пользе функциональных веток подробно излагается в статье Ultimate Quality Development System).
Чаще всего в централизованных системах контроля версий (например таких популярных как CVS или SVN) реализация веток подразумевает именно только работу с релизными ветками, а поддержка работы с функциональными ветками (точнее с многократным объединением изменений между основной и функциональной веткой) реализована хуже. Поэтому их часто критикуют за слабую поддержку веток, имея ввиду именно слабую поддержку объединений в модели работы с функциональными ветками.
Далее в статье мы рассмотрим работу с ветками именно с позиции функциональных веток.

Создать копию ветки

Поскольку bzr хранит всю служебную информацию локально в рабочем каталоге, то мы можем просто скопировать рабочий каталог со всеми файлами. Это вполне корректный вариант, однако рекомендуется все же использовать специальную команду branch:

C:\Temp> bzr branch Test Experimental
Branched 2 revision(s). 

Мы создали копию ветки Test в каталоге Experimental. Сразу после выполнения команды branch обе ветки содержат одинаковый набор ревизий и их история идентична. По мере того, как пользователь будет фиксировать новые изменения в той или иной ветке, история веток начнет различаться.
Будем считать Test — основной веткой, а Experimental — функциональной (или экспериментальной) веткой.
Работа в другой ветке

Работа со второй веткой ничем не отличается от сценария работы рассмотренного в первой части статьи. Новая ветка полностью автономна и независима от своего родителя. Пользователь может просматривать историю, фиксировать изменения в файлах и т.д. Изменим один из файлов и зафиксируем его:  

------Файл goodbye.txt-------- 
До свидания 
------------------------------

C:\Temp\Experimental>bzr commit -m "Скорректирован файл goodbye.txt в ветке Experimental" 
Committing to: C:/Temp/Experimental/ 
modified goodbye.txt 
Committed revision 3.

Вернемся в первую ветку Test и изменим там другой файл:

--------Файл foo.txt----------
bar 
------------------------------  

C:\Temp\Test>bzr commit -m "Скорректирован файл foo.txt в ветке Test" 
Committing to: C:/Temp/Test/
modified foo.txt
Committed revision 3.

Обе ветки теперь содержат по 3 ревизии, но с различными изменениями. История "разошлась".

История веток в bzr представляется в виде ориентированного ациклического графа (DAG), совместный граф для этих двух веток будет выглядеть следующим образом:



Работа в обеих ветках может продолжаться независимо. Как только пользователь посчитает, что работа над функциональной веткой Experimental закончена, можно объединить основную и функциональные ветки.

Объединение веток

Операция объединения веток выполняется командой merge. При этом bzr будет объединять историю и изменения из другой ветки с текущей веткой.

C:\Temp\Test>bzr merge ../Experimental 
M goodbye.txt 
All changes applied successfully.

Как мы видим, объединение изменений прошло успешно. В случаях, когда в обеих ветках были произведены несовместимые изменения, в результате объединения мы получим один или несколько конфликтов в рабочих файлах. (Подробнее о типах конфликтов и методах их разрешения мы поговорим в отдельной статье.)

После объединения команда status будет отображать ревизии, которые мы объединили, но еще не зафиксировали:
 
C:\Temp\Test>bzr status -v 
modified: 
  goodbye.txt 
pending merges: 
  Alexander Belchenko 2009-03-13 Скорректирован файл goodbye.txt в ветке Experimental

Как видно ревизии из ветки Experimental помечены как pending merges (незаконченное объединение). Чтобы закончить процесс объединения мы должны зафиксировать изменения командой commit.

Результаты объединения желательно просмотреть визуально, проанализировав содержимое изменившихся файлов либо просмотреть различия командой diff:

C:\Temp\Test>bzr diff 
=== modified file 'goodbye.txt' 
--- goodbye.txt 2009-03-10 09:06:24 +0000 
+++ goodbye.txt 2009-03-15 07:59:47 +0000 
@@ -1,1 +1,1 @@
-Пока 
+До свидания

Если пользователь согласен с внесенными изменениями, то их нужно зафиксировать как обычно:

C:\Temp\Test>bzr commit -m "Объединение с веткой Experimental" 
Committing to: C:/Temp/Test/ 
modified goodbye.txt 
Committed revision 4. 

Если мы просмотрим журнал изменений для ветки Test, то мы увидим объединенные ревизии в истории основной ветки:
 
C:\Temp\Test>bzr log
------------------------------------------------------------
revno: 4
committer: Alexander Belchenko <alexander.belchenko @ gmail.com>
branch nick: Test
timestamp: Sun 2009-03-15 10:11:30 +0200
message:
  Объединение с веткой Experimental
    ------------------------------------------------------------
    revno: 2.1.1
    committer: Alexander Belchenko <alexander.belchenko @ gmail.com>
    branch nick: Experimental
    timestamp: Fri 2009-03-13 20:04:12 +0200
    message:
      Скорректирован файл goodbye.txt в ветке Experimental
------------------------------------------------------------
revno: 3
committer: Alexander Belchenko <alexander.belchenko @ gmail.com>
branch nick: Test
timestamp: Fri 2009-03-13 20:07:10 +0200
message:
  Скорректирован файл foo.txt в ветке Test
------------------------------------------------------------
revno: 2
committer: Alexander Belchenko <alexander.belchenko @ gmail.com>
branch nick: Test
timestamp: Tue 2009-03-10 15:38:19 +0200
message:
  Внесены изменения для иллюстрации команд status и diff
------------------------------------------------------------
revno: 1
committer: Alexander Belchenko <alexander.belchenko @ gmail.com>
branch nick: Test
timestamp: Tue 2009-03-10 11:06:24 +0200
message:
  Начальное состояние файлов

Объединенные ревизии отображаются под ревизией, в которой объединение было зафиксировано, с небольшим отступом. Соответствующий граф ревизий теперь выглядит следующим образом:

После объединения вся история ветки Experimental содержится в ветке Test. Мы видим ревизию из этой ветки под номером 2.1.1 в ветке Test. Если работа с веткой Experimental закончена, то ее можно смело удалить. Если ветка Experimental понадобится вновь, ее можно восстановить командой branch, указав номер ревизии при помощи опции --revision (-r):
 
C:\Temp>bzr branch Test Experimental -r 2.1.1 
Branched 3 revision(s).

Итак, мы рассмотрели работу с несколькими ветками и научились объединять ветки. В следующих статьях мы рассмотрим другие команды для работы с ветками, а также научимся справляться с конфликтами объединения.

среда, 11 марта 2009 г.

Начинаем работу с bzr: базовый набор команд (Часть 1)

Как вы помните, bzr является распределенной системой контроля версий и не требует никакого специального сервера для своей работы. Поэтому начать работу с ней очень просто: вы можете создать новый репозиторий и новую ветку в любом удобном локальном каталоге на вашем компьютере. Далее мы рассмотрим 8 базовых команд bzr, которые понадобятся для локальной одиночной работы.

Сценарий работы

Инициализируем в локальном каталоге новую ветку для работы. В этом каталоге создадим несколько рабочих файлов. Добавим эти файлы под контроль версий. Зафиксируем начальное состояние файлов. Изменим некоторые из файлов. Просмотрим изменения в файлах. Зафиксируем новое состояние файлов. Просмотрим историю изменений. Создадим копию ветки для параллельной работы. Изменим некоторые файлы в старой и новой ветках и зафиксируем новое состояние. Объединим изменения в двух ветках.

Этот сценарий иллюстрирует типичную работу с локальными ветками. Создавать новые ветки с нуля придется  для каждого нового проекта, который вы хотите поместить под контроль версий, но это относительно редкое действие. Остальные действия  вы будете выполнять в своей работе  достаточно часто.

Команды

В вышеприведенном сценарии работы выделены действия, производимые при помощи bzr. Команды bzr используют английские термины, соответствующие выполняемым действиям:

initИнициализацияИнициализация новой ветки
add
Добавить
Добавить файлы под контроль версий
commit
Зафиксировать
Зафиксировать состояние файлов
status
Состояние
Показать состояние файлов, отобразить имена измененных файлов
diff
Разница
Показать изменения в файлах
log
Журнал
Просмотр журнала изменений, истории изменений
branch
Ветка
Создать новую ветку
merge
Объединить
Объединить изменения из разных веток

Используем команды из таблицы для "перевода" нашего сценария с русского языка на язык команд bzr. В примерах использовался bzr 1.12. Если вы используете другую версию, то сообщения bzr могут незначительно отличаться.

Инициализировать новую ветку

Инициализировать новую ветку в текущем каталоге:

C:\Temp\Test>bzr init
Created a standalone tree (format: pack-0.92)

В качестве аргумента команде init можно указать путь для создания новой ветки, новый каталог будет создан при необходимости.
При инициализации создается служебный каталог с именем .bzr, в котором хранятся служебные файлы и история изменений.
Новая ветка инициализирована — можно добавлять файлы.

Добавить новые файлы

Для примера создадим два текстовых файла в рабочем каталоге:

-------Файл hello.txt---------
Привет
------------------------------

------Файл goodbye.txt--------
Пока
------------------------------

Добавим файлы под контроль версий:

C:\Temp\Test>bzr add
adding goodbye.txt
adding hello.txt

Команда add, запущенная без аргументов, добавит все неизвестные файлы под контроль версий. Вы можете явно указать какие файлы нужно добавлять, если запустите команду add с аргументами (именами файлов для добавления).

Файлы добавлены — можно фиксировать их состояние.

Зафиксировать состояние файлов

Фиксация запоминает текущее состояние файлов. Пользователь должен дать комментарий к фиксируемым изменениям. Этот комментарий затем можно будет увидеть при просмотре журнала изменений. Хорошей практикой является описание цели и сути изменений в комментарии: конкретные изменения можно просмотреть при помощи команд bzr, а вот мотивы и цели изменений знает только автор изменений. Со временем это знание утрачивается, поэтому старайтесь писать четкие комментарии, которые будут понятны и через неделю/месяц/год.

C:\Temp\Test>bzr commit -m "Начальное состояние файлов"
Committing to: C:/Temp/Test/
added goodbye.txt
added hello.txt
Committed revision 1.

Опция -m (--message) используется для указания комментария. Пользователь также может указать имя файла, из которого будет прочитан комментарий (используется опция --file, -F). Либо можно не указывать ничего, в этом случае будет запущен текстовый редактор, в котором вы сможете ввести свой комментарий.

Просмотр изменений

В реальной работе файлы приходится менять, дописывать и корректировать достаточно часто. Закончив очередной логический этап (например, реализована новая функция в программе, исправлена ошибка, или проведен рефакторинг существующего кода) пользователь может проанализировать внесенные изменения и зафиксировать их. Продемонстрируем эти действия на простом примере.

Изменим файл hello.txt и создадим новый файл foo.txt:

-------Файл hello.txt---------
Привет, мир!
------------------------------

--------Файл foo.txt----------
Новый файл
------------------------------

Для просмотра списка измененных файлов (состояние набора рабочих файлов) используется команда status:

C:\Temp\Test>bzr status
modified:
  hello.txt
unknown:
  foo.txt


bzr показал, что файл hello.txt был изменен, а также что появился неизвестный файл foo.txt. Неизвестными (unknown) считаются файлы, которые не находятся под контролем версий и не попадают в список игнорируемых (о списке игнорируемых файлов будет рассказано в других статьях). Поскольку команда commit фиксирует состояние только тех файлов, которые находятся под контролем версий, то нам необходимо добавить новый файл командой add:

C:\Temp\Test>bzr add
adding foo.txt

Теперь status отрапортует о новом файле, как о добавленном:

C:\Temp\Test>bzr status
added:
  foo.txt
modified:
  hello.txt

Для того, чтобы увидеть не только имена изменных файлов, но и сами изменения в них, используется команда diff:

C:\Temp\Test>bzr diff
=== added file 'foo.txt'
--- foo.txt     1970-01-01 00:00:00 +0000
+++ foo.txt     2009-03-10 13:13:56 +0000
@@ -0,0 +1,1 @@
+Новый файл

=== modified file 'hello.txt'
--- hello.txt   2009-03-10 09:06:24 +0000
+++ hello.txt   2009-03-10 13:14:11 +0000
@@ -1,1 +1,1 @@
-Привет
+Привет, мир!

Команда diff отображает разницу между последним зафиксированным состоянием файла и текущим в формате unidiff (изменения показываются в виде групп, знак минус в начале строки индицирует старый удаленный текст, знак плюс в начале строки индицирует новый добавленный текст).
Примечание для пользователей Windows: обычно русский текст в файлах сохраняется в кодировке cp1251 (ANSI), в то время как кодировка консоли cp866 (DOS/OEM). Для того, чтобы увидеть русский текст в выводе команды diff нормально, а не ввиде иероглифов, переключите кодировку консоли командой:

chcp 1251

Обратное переключение осуществляется командой:

chcp 866
Если пользователя удовлетворяют эти изменения, то он может их зафиксировать:

C:\Temp\Test>bzr commit -m "Внесены изменения для иллюстрации команд status и diff"
Committing to: C:/Temp/Test/
added foo.txt
modified hello.txt
Committed revision 2.

Просмотр истории

Для просмотра журнала изменений (зафиксированных ревизий) используется команда log:

C:\Temp\Test>bzr log
------------------------------------------------------------
revno: 2
committer: Alexander Belchenko <alexander.belchenko@gmail.com>
branch nick: Test
timestamp: Tue 2009-03-10 15:38:19 +0200
message:
  Внесены изменения для иллюстрации команд status и diff
------------------------------------------------------------
revno: 1
committer: Alexander Belchenko <alexander.belchenko@gmail.com>
branch nick: Test
timestamp: Tue 2009-03-10 11:06:24 +0200
message:
  Начальное состояние файлов

Для каждой ревизии выводится информация о номере, о том кто и когда зафиксировал изменения (поля committer и timestamp), название ветки (branch nick), а также комментарий (message). Журнал изменений — это важный инструмент для анализа прошлых изменений.

При запуске команды bzr log с опцией --verbose (-v) для каждой ревизии будет выведен список измененных файлов, аналогично команде status. Впрочем, вы можете использовать и команды status и diff для просмотра зафиксированных изменений. У этих команд есть опция --change (-c), которая позволяет просмотреть изменения зафиксированные в определенной ревизии:

C:\Temp\Test>bzr status -c 2
added:
  foo.txt
modified:
  hello.txt

Также можно указать произвольный диапазон ревизий для просмотра внесенных изменений. Например, те же самые изменения во второй ревизии можно увидеть, если указать диапазон ревизий 1..2:

C:\Temp\Test>bzr status -r 1..2
added:
  foo.txt
modified:
  hello.txt


Итак, мы рассмотрели базовый набор команд для работы с одной локальной веткой. Конечно, это далеко не все полезные команды, но это тот минимум без которого работать не получится вовсе.
Во второй части статьи мы рассмотрим совместную работу с несколькими ветками.

среда, 4 марта 2009 г.

Исправление ошибок при работе с Bazaar

Errare humanum est (человеку свойственно ошибаться) — утверждение, с которым невозможно поспорить. Мудрый подход состоит не в том, чтобы пытаться избегать ошибок, а в том, чтобы научиться их исправлять. Собственно, одно из основных предназначений любой системы контроля версий — это возможность исправления ошибок. Используя систему контроля версий вы быстрее сможете понять почему перестала работать последняя ревизия вашего приложения, изучив изменения от предыдущей ревизии, или даже можете вернутся к старой, работающей, ревизии. Кроме этого, распределенные системы, в отличие от централизованных, отделяют момент фиксации изменений от момента их отправки (в обычном режиме работы), тем самым позволяя внимательнее рассмотреть изменения на предмет ошибок. Плюс ко всему этому, Bazaar предлагает свои подходы и команды для работы над ошибками, которые мы и рассмотрим ниже в приложении к типичным ситуациям. Если вы случайно ошиблись при создании ветки Bazaar из дерева исходного кода (с помощью команды bzr init) и превратили в ветку не то дерево, самое простое, что можно сделать - это удалить появившуюся служебную директорию .bzr. Конечно, здесь нужно быть внимательным чтобы не удалить нужную служебную директорию. Другая типичная ситуация - добавление под контроль версий (с помощью команды bzr add) не того файла. Часто в рабочей директории могут находится временные файлы, журналы тестовых запусков, или другие файлы, которые не нужно хранить под контролем версий. Но в случае выполнения команды bzr add без параметров, под контроль версий попадут все неизвестные файлы (исключая файлы указанные для игнорирования). Эту ситуацию можно исправить с помощью команды bzr remove. При этом команда remove без опций не будет удалять неизвестный, или измененный файл:
$ bzr add
$ bzr remove file.tmp
bzr: ERROR: Can't safely remove modified or unknown files:
added:
    file.tmp
Use --keep to not delete them, or --force to delete them regardless.
Здесь мы можем использовать опцию --keep что бы оставить файл как неизвестный и удалить его только из под контроля версий. Или можно использовать опцию --force для полного удаления файла. Но, если файл уже был зарегистрирован и не изменялся, то команда remove удалит его без необходимости указания дополнительных опций, т.к. файл может быть восстановлен на момент предыдущей ревизии с помощью команды revert, которую мы рассмотрим ниже:
$ bzr add TODO
$ bzr commit -m "Добавлен TODO"
$ bzr remove TODO
В случае, если не использовать команды Bazaar, а просто удалить файл с помощью команды операционной системы, то файл автоматически будет удален и из под контроля версий. Теперь представим, что мы решили попробовать какой-то новый вариант в проекте, изменили несколько файлов, но попытка не удалась и хочется просто вернуться к состоянию на момент последней фиксации изменений. В этом случае мы можем использовать команду revert:
$ bzr revert
Эта команда отменит все изменения в рабочей директории с момента последней фиксации (в том числе будут восстановлены удаленные файлы). В этом случае хорошей практикой является предварительное использование команд bzr status и bzr diff, что бы быть уверенным, что при отмене изменений не пропадет что-то нужное. Команда revert также позволяет указывать имена файлов для которых нужно отменить изменения:
$ bzr revert file.txt
При этом все остальные измененные файлы останутся нетронутыми. Еще одна уникальная для Bazaar функция (по крайней мере я не видел в других системах такого простого интерфейса) для работы надо ошибками — команда uncommit. С ее помощью можно отменить последнюю фиксацию и вернуть рабочее дерево в состояние на момент до выполнения фиксации. Незаменимая вещь на случай опечатки в сообщении о фиксации:
$ bzr commit -m "Очепятка"
$ bzr uncommit
$ bzr commit -m "Опечатка"
Кроме этого, с uncommit можно использовать опцию -r для отмены сразу нескольких ревизий:
$ bzr uncommit -r -3
При этом рабочее дерево останется в том же состоянии что и до выполнения отмененных фиксаций. С командой revert также можно использовать опцию -r для возврата рабочего дерева в состояние до указанной ревизии, но ревизии при этом не удаляются:
$ bzr commit -m "Исправления"
(выпуск релиза)
$ bzr revert -r -2
$ bzr commit -m "Отменено исправление"
(выпуск следующего релиза)
Также рассмотрим исправления, связанные с метками. Если вы поставили для ревизии метку с помощью команды bzr tag, но после этого обнаружили, что ее лучше перенести на более позднюю ревизию, то можно воспользоваться опцией --force:
$ bzr tag 1.0
(еще рано для первой версии, нужно сделать несколько изменений)
$ bzr tag 1.0 --force
Метка также может быть удалена с помощью опции --delete:
$ bzr tag 1.0
(еще рано для первой версии, нам пока не нужна метка)
$ bzr tag 1.0 --delete

воскресенье, 1 марта 2009 г.

bzr help: встроенная справочная служба класса "люкс" (Часть 2)

Рассмотрим вывод справочной информации на примере команды branch, и посмотрим какую информацию мы там можем найти.
C:\>bzr help branch
Purpose: Create a new copy of a branch.
Usage:   bzr branch FROM_LOCATION [TO_LOCATION]

Options:
  --stacked             Create a stacked branch referring to the source
                        branch. The new branch will depend on the availability
                        of the source branch for all operations.
  -v, --verbose         Display more information.
  --standalone          Do not use a shared repository, even if available.
  -h, --help            Show help message.
  -q, --quiet           Only display errors and warnings.
  --hardlink            Hard-link working tree files where possible.
  -r ARG, --revision=ARG
                        See "help revisionspec" for details.

Description:
  If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
  be used.  In other words, "branch ../foo/bar" will attempt to create ./bar.
  If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
  is derived from the FROM_LOCATION by stripping a leading scheme or drive
  identifier, if any. For example, "branch lp:foo-bar" will attempt to
  create ./foo-bar.

  To retrieve the branch as of a particular revision, supply the --revision
  parameter, as in "branch foo/bar -r 5".

Aliases:  get, clone
See also: checkout
Здесь:
  • Purpose — назначение команды
  • Usage — командная строка с указанием ожидаемых аргументов
  • Options — опции командной строки
  • Description — подробное описание команды и вариантов использования
  • Aliases — встроенные псевдонимы для команды
  • See also — ссылки на схожие по тематике разделы справки
Аргументы командной строки

Необязательные аргументы отобажаются в квадратных скобках. Если ожидается один или больше аргументов, то вы увидите многоточие после имени аргумента.

Опции командной строки

Опции могут использоваться вперемешку с аргументами, стоять до или после них. Очень удобно.

Опции -v и -q отображаются для всех команд, однако для некоторых команд они не имеют эффекта.

Псевдонимы

Некоторые команды могут иметь псевдонимы. Это сделано для удобства и для имитации поведения других систем контроля версий, чтобы пользователям при переходе на Базар было легче осваиваться. Во многих случаях псевдонимы предлагают более короткую форму записи имени для часто используемых команд. Так например, команда status имеет псевдоним st, а команда diff имеет псевдоним di.

В дополнение к встроенным псевдонимам Базар поддерживает также псевдонимы определяемые пользователем. О них мы расскажем в следующих статьях.

See also (см. также)

Многие справочные разделы (не только справка к командам) дают подсказку и наводку на материалы, схожие по тематике либо отражающие другой вариант использования. Часто так можно найти ценные советы и подсказки.

Итак, теперь вы знаете об использовании справки достаточно, чтобы не растеряться в ответственный момент. Помните, что аргументы и опции можно записывать вперемешку, и что опция -h (--help) выводит справку по команде без запуска самой команды. Так что если вы начали писать команду и вдруг решили перечитать справку по ней, то можете просто дописать -h в конце и нажать Enter. А прочитав справку, вызовите предыдущую команду (в большинстве командных процессоров это делается просто нажатием стрелки вверх) и отредактируйте ее нужным образом.

Также не забывайте, что справка ко многим командам довольно обширна, поэтому помните про использование программ типа more или less.