среда, 28 марта 2012 г.

bzr 2.5.0 и локализация интерфейса

Одним из нововведений в релизе bzr 2.5 стало добавление поддержки локализации выводимых сообщений. Я только что обновил у себя bzr из инсталлятора https://launchpad.net/bzr/2.5/2.5.0/+download/bzr-2.5.0-2-setup.exe и увидел, что русская локализация уже работает:

C:\>set LANGUAGE=ru

C:\>bzr
Bazaar 2.5.0 -- a free distributed version-control tool
http://bazaar.canonical.com/

Базовые команды:
  bzr init           превратить директорию в ветвь системы версий
  bzr branch         создать копию другой ветви

  bzr add            добавить файлы или директории к системе контроля версий
  bzr ignore         игнорировать файл или шаблон
  bzr mv             переместить или переименовать файл в системе контроля версий

  bzr status         вывести краткие изменения в рабочей копии
  bzr diff           вывести подробные различия

  bzr merge          принять изменения из другой ветви
  bzr commit         сохранить некоторые или все изменения
  bzr send           переслать изменения по электронной почте

  bzr log            показать историю изменений
  bzr check          проверить целостность

  bzr help init      подробные сведения например по команде init
  bzr help commands  вывести список всех команд
  bzr help topics    вывести список всех разделов справки

Что само по себе уже приятно.

Можно пробовать, о найденных проблемах сообщать в багтрекере bzr (или в группе ru_bzr, хотя я не участвовал в переводе). Радует, что нашлись активные добровольцы. Однако переведено далеко не всё, и вы тоже можете помочь с переводом: https://translations.launchpad.net/bzr и не только на русский, но и на другие языки, которыми вы свободно владеете.

Enjoy!

воскресенье, 14 августа 2011 г.

Inside .bzr: что внутри служебного каталога .bzr: Часть 2: shared repository

В первой части мы рассмотрели как внутри выглядит ветка и отметили, что у самостоятельных веток (standalone branch) репозиторий свой. Посмотрим, что изменится при работе с shared repository.
(Далее)

понедельник, 8 августа 2011 г.

Inside .bzr: что внутри служебного каталога .bzr. Часть 1: просто ветка

В своей книге Version Control by Example Эрик Синк (Eric Sink) пишет:
Version control tools are more like cars than clocks. 
Clock users have no need to know how a clock works behind the dials. We just want to know what time it is. Those who understand the inner workings of a clock can’t tell time any more skillfully than the rest of us. 
Version control tools are more like cars. Lots of people, including me, use cars without knowing much about how they work. However, people who really understand cars tend to get better performance out of them.
Мне нравится это сравнение. В самом деле, если вы понимаете как внутри системы вертятся колесики, вы сможете более осознано управлять ею.

В документации к bzr вопросам внутреннего устройства системы уделяется меньше внимания, чем могло быть. Отчасти потому что разработчики bzr исходили из посылки, что для успешного использования bzr знания о внутреннем устройстве необязательны (в отличие от git, где без знания как устроен репозиторий  вы не имеете права использовать его).

Предлагаю рассмотреть внутреннее устройство служебного каталога .bzr, и что там живет внутри, это даст вам понимание о разнице между веткой, разделяемом репозитории (shared repository) и различным типам checkouts.
(Далее)

пятница, 5 августа 2011 г.

Bazaar уверенно удерживает третье место

Ни для кого ни секрет, что bzr не является самой-пресамой популярной DVCS по состоянию на 2011 год. По моим личным наблюдениям первое место уверенно держит git, я думаю не в последнюю очередь благодаря GitHub.

На блогах Microsoft опубликованы результаты опроса (через Twitter) предпочтений разработчиков Open Source проектов. Насколько эта выборка репрезентативна -- вопрос спорный. Однако она достаточно хорошо на качественном уровне показывает тенденции: git > hg > bzr.

Выбрав цифры только для тройки git/hg/bzr и беспощадно усредняя их можно прийти к такой средней температуре по больнице:
  • git ~77%
  • hg ~18%
  • bzr < 5%
Почему все еще имеет смысл использовать bzr? может спросить кто-то.

С моей точки зрения причины к этому могут быть следующие:
  • вы и ваша команда более чем удовлетворены работой bzr и у вас нет причин менять проверенного коня. (По моему личному мнению каждая система из тройки имеет свои недостатки, с которыми придется мириться)
  • Вы предпочитаете работать в централизованном стиле не теряя плюсов DVCS
  • вам нравится GUI интерфейс к bzr -- QBzr и/или Bazaar Explorer, и вы не хотите их потерять при переходе на другую систему. Я не раз и не два получал отзывы от различных людей, даже от (увы) бывших пользователей bzr о том, что QBzr очень хорош. И я с этим согласен
  • вам нравится использовать Launchpad для хостинга своих открытых проектов.
  • вы используете bzr для работы с svn через bzr-svn. Плюшки в виде QBzr/Explorer прилагаются и здесь.
Собственно других веских причин я затрудняюсь назвать. Я строго убежден, что лучшая DVCS еще не написана, и что у hg просто нет шансов подняться до более-менее паритета с git. Хотя на Windows платформе у hg много преимуществ, учитывая, что git на Windows -- это весьма тяжкое испытание.

вторник, 6 апреля 2010 г.

Использование bzr-externals или компонентный подход

При работе над крупными проектами часто возникает потребность выделить часть проекта в отдельный подпроект, как самостоятельную сущность. Такой подпроект может представлять собой некоторую библиотеку, которая используется в разных проектах. Для работы с составными проектами, которые включают в себя дополнительные библиотеки, в bzr задумана функция под названием nested trees (в git для этого есть submodules, а в hg — subrepos). К сожалению разработка функции nested trees пока не завершена, поэтому вместо нее можно использовать плагины bzr-externals или bzr-scmproj. Я попросил автора плагина bzr-externals Евгения Тарасенко рассказать про работу с плагином. В данной статье описывается работа с плагином версии 1.3.
Автор: Евгений Тарасенко

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

В Bazaar работа с общими компонентами пока еще не доведена до ума, поэтому пришлось написать небольшой плагин bzr-externals. Надо отметить, что существует еще один похожий плагин bzr-scmproj, но в отличие от первого, в нем для работы с компонентами используются отдельные команды, а это означает, что работа возможна только из консоли и такие инструменты как Bazaar Explorer, QBzr и TortoizeBzr остаются не у дел.

Основная же идея bzr-externals — использование только стандартных команд, чтобы пользователю не нужно было делать лишних телодвижений для работы с компонентами.

Итак, нам понадобится плагин bzr-externals, который можно скачать с http://launchpad.net/bzr-externals или взять прямо из репозитория lp:bzr-externals, о том как это сделать можно узнать из этой статьи.

Проектом может быть любая ветка. Для добавления нового компонента в проект как внешней ссылки нам все же понадобится консоль, но так как это делается только один раз, то я думаю ничего страшного. Формат команды добавления компонента следующий:
bzr externals-add URL  DIRECTORY [--revision REVISIONSPEC]
Здесь URL может быть относительным, так же как и в svn:externals. Например, следующие команды делают почти одно и тоже, но разными способами, не считая использования конкретной ревизии в первом варианте (eadd — встроенный псевдоним команды):
bzr eadd bzr://example.com/repos/common/foo  common/foo -r revno:100
Если доступ к хранилищу возможен по разным протоколам (например, http или bzr+http), то для компонента имя протокола можно опустить, будет использоваться тот же протокол, по которому вы получите главный проект
bzr eadd //example.com/repos/common/foo  common/foo
Если ваш проект хостится на разных серверах, но с одинаковой структурой каталогов, то имя сервера также можно опустить, будет использовать сервер главного проекта
bzr eadd /repos/common/foo  common/foo
И наконец возможен доступ относительно каталога главного проекта в репозитории
bzr eadd ../../common/foo  common/foo
Каталог, в котором должен размещаться компонент, DIRECTORY указывается относительно корня проекта. Если такого компонента еще нет в рабочей папке проекта, то будет выполнен branch/checkout, в зависимости от типа главного проекта, иначе pull/update.
REVISIONSPEC — необязательный параметр, и должен использоваться, только если вам нужна конкретная версия компонента.

В результате выполнения команды externals-add будет добавлен компонент в рабочую директорию, а также в корне проекта появятся конфигурационные файлы:
.bzrmeta/externals
.bzrmeta/externals-snapshot
Первый файл используется для хранения параметров всех компонентов и может быть отредактирован пользователем; например, чтобы привязать компонент к конкретной версии или просто удалить компонент из проекта. Второй файл создается автоматически при каждом commit в проекте и предназначен для создания "снимка" используемых ревизий компонентов, чтобы впоследствии, при откате на какую-либо ревизию, можно было точно восстановить все дерево проекта (чего, кстати, не умеет делать subversion).

Формат обоих конфигурационных файлов одинаков и незатейлив:
URL DIRECTORY REVISIONSPEC
Итак, компонент добавлен в ваш проект, и теперь, казалось бы, надо описать, как нам работать с ним, но тут вступает в силу главный принцип плагина – никаких дополнительных команд. Поэтому всё, что вы делаете с основным проектом, будет повторяться и для всех компонентов. Вот список поддерживаемых команд для версии 1.3:
  • branch [--revision]
  • checkout [--revision]
  • commit
  • pull
  • push
  • update.
Однако, если вам все же не хватает этих команд, то есть два пути: первый — просто зайти в директорию с компонентом и делать с ним что угодно, так как по сути это обыкновенная ветка Bazaar. И второй путь — использовать вторую дополнительную команду externals-cmd или кратко ecmd, чтобы выполнить любую команду Bazaar для всех компонентов проекта и для самого проекта тоже. Например, посмотреть последнюю ревизию для всех:
bzr ecmd -- log -r -1
Работа с Bazaar может быть организована различными способами, в том числе с использованием feature branch, когда сначала делается локальная копия удаленного репозитория, а уже от нее делается ветка для конкретной фичи, плагин поддерживает и такой режим работы.

Рассмотрение плагина подошло к концу, дополнительную информацию можно получить с помощью:
bzr help externals

среда, 24 марта 2010 г.

Командная строка и bzr: "ленивые" опции

Следующий совет может оказаться полезным для тех, кто использует bzr из командной строки на постоянной основе или даже время от времени. Как вы помните, многие команды bzr имеют встроенные псевдонимы, а также пользователь может задавать свои собственные пользовательские псевдонимы при помощи команды alias. Так вместо status можно использовать st, а вместо commit ci. Однако эти самые команды зачастую имеют обширный набор опций для тонкого управления поведением каждой команды. Все эти опции имеют основную форму вида --имяопции, и могут иметь короткую форму вида -X где X — это одна буква латинского алфавита. Для того, чтобы узнать какая короткая форма у определенной опции, просматривайте информацию об использовании команды. Например, опция --revision имеет короткую форму -r (о чем вы наверняка знаете).

Однако это еще не всё. Движок, используемый для обработки опций и аргументов команд bzr позволяет использовать сокращенную запись для основной формы. Сокращать допускается до того состояния пока bzr сможет однозначно понять, что вы имеете ввиду, обычно достаточно оставить 2-3 первых буквы. Например, опцию --revision можно сокращать до --rev, а опцию --force до --fo. Тогда pull --remember можно вызывать как pull --rem, а push --overwrite как push --over, и т.д. И поскольку не все опции имеют короткую форму из одной буквы, то часто бывает полезно знать эту возможность.

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

C:\work\bzr-day\options-for-lazy>bzr pull --re lp:foo
bzr: ERROR: ambiguous option: --re (--remember, --revision?)

В данном случае bzr не смог понять какую именно опцию вы имели ввиду: --remember или --revision.

Механизм поддержки сокращений для опций работает для всех опций самой команды, но не работает для глобальных опций самого bzr, таких как --no-plugins, --no-aliases и т.п. Полный список глобальных опций можно увидеть запустив команду bzr help global-options.

воскресенье, 21 марта 2010 г.

Использование внешнего редактора для команды bzr shelve

Одной из очень полезных функций в bzr является пара команд shelve/unshelve. Эти команды позволяют временно удалить из рабочих файлов часть изменений, чтобы зафиксировать остальные изменения без них. Часто это бывает нужно для логического разделения разных правок. Например, вы начали реализовывать новую функцию в своей программе и попутно обнаружили и исправили старый баг. Имеет смысл зафиксировать исправление ошибки отдельно и затем продолжить работу над новой функцией. В этом случае помогает shelve/unshelve.
Подобная функциональность присутствует в других системах контроля версий. Так, в git для этого используется команда stash, а в hg для этого используется расширение shelve.
Подробный рассказ об использовании shelve/unshelve заслуживает отдельной статьи. Вкратце процесс отбора изменений для удаления их "на полочку" выглядит следующим образом:
  • вы запускаете команду shelve, опционально указывая список файлов, в которых нужно отобрать изменения.
  • для каждого файла с изменениями bzr вам показывает отдельные блоки изменений (diff hunks), аналогично тому как блоками показывает изменения команда diff.
  • для каждого блока вы указываете: хотите ли вы убрать это изменение "на полочку" либо оставить в рабочей копии.
  • после того, как вы ответите на вопрос по каждому блоку каждого файла с изменениями, отобранные изменения удаляются из рабочей копии и сохраняются в специальном хранилище ("на полочке").
Подробнее об использовании shelve смотрите справку по этой команде.

Одним из неудобств при использовании shelve является гранулярность отбора изменений. Вы не можете так просто удалить одну строку с изменениями из целого блока (hunks). Вам приходится или убирать весь блок или оставлять весь блок. Что было не очень удобно.

Однако, к нашей радости, в bzr 2.1.0 у shelve появилась новая функция: теперь можно использовать внешний редактор для правки и отбора изменений. В качестве редактора имеет смысл использовать программу для просмотра и редактирования изменений в 2х файлах. Например, vimdiff, WinMerge и проч.

Для того, чтобы использовать внешний редактор в команде shelve его следует предварительно задать в файле конфигурации bazaar.conf. Для этого в секции [DEFAULT] добавьте строку вида:
change_editor = vimdiff -fo @new_path @old_path
Здесь: @new_path @old_path — это специальные параметры, вместо которых в реальности bzr будет подставлять полный путь к редактируемому файлу (@new_path) и полный путь к файлу с последним зафиксированным состоянием (@old_path).

Так, например, я для использования WinMerge указал следующую строку в bazaar.conf:
change_editor = '"C:/Program Files/WinMerge/WinMergeU.exe" @old_path @new_path'
После того, как вы настроите change_editor, при вызовах shelve в строке выбора для каждого блока изменений вам будет доступен дополнительный выбор ("e"). По нажатию на клавишу "e" (editor) будет запущена указанная вами программа для редактирования текущего файла. Ваша задача: отредактировать @new_path до состояния, в котором вы хотите, чтобы он был на диске. Команда shelve сама определит какие изменения нужно убрать из текущей рабочей копии конкретного файла, чтобы в итоге получилось то, что вы хотите.

Приятной работы!

четверг, 18 февраля 2010 г.

Использование плагина bzr-pipeline для "вечных" локальных правок

Иван Сагалаев описал один из вариантов работы с плагином bzr-pipeline. Иван пишет:
...хочу поделиться bzr-специфичным решением одной практической ситуации, возникающей при групповой работе над проектом.
Работая над общим кодом на локальной машине, иногда бывает нужно делать в нём строго локальные правки: пути к файлам, адреса серверов, отладочное логирование. При этом эти правки никогда не должны попадать в основной бранч проекта.
Часть из них можно и нужно вынести в отдельные локальные конфигурационные файлы, которые просто заигнорировать. Но вот с упомянутым отладочным логированием так не получится — это произвольный код, временно раскиданный по файлам. Ещё один пример такой правки — полное вырезание куска кода, который не критичен для работы, но не даёт проекту завестись с локальном окружении.
В bzr для этой проблемы мне известны два решения: одно прямое, другое — более удобное, с помощью плагина bzr-pipeline. Беда только в том, что в его документации описан несколько другой юзкейс, и я с первого раза вообще не понял, как оно мне поможет. Потом разобрался и решил восполнить пробел.
Читать целиком: http://softwaremaniacs.org/blog/2010/02/18/local-patches-in-bzr-pipeline

среда, 17 февраля 2010 г.

Новая стабильная версия Bazaar 2.1.0

Спустя полгода после выпуска стабильного релиза bzr 2.0.0 разработчики Bazaar представляют новую стабильную версию Bazaar 2.1.0 (февраль 2010 года).

Новая версия содержит в себе много разных улучшений и исправлений дефектов, однако ничего революционного (вроде нового формата репозитория) не несёт. Список отдельных улучшений просто огромен (более 200 пунктов), поэтому рассмотрим только ключевые и заметные для пользователей моменты.
  • Значительно уменьшено потребление памяти для выполнения операций (уменьшение почти в два раза). Это значит, что с ветками с большой историей работать будет быстрее и комфортнее.
  • Добавлен новый хук для объединения файлов. Теперь становится возможным для файлов разных типов определять различные алгоритмы объединения изменений. Для использования этой возможности необходимо будет написать соответствущий плагин.
    В качестве примера такого плагина вместе с bzr поставляется плагин news_merge, который должен облегчить процесс объединения изменений в файле NEWS в исходном коде самого bzr. (Файл NEWS в bzr редактируется очень часто, поэтому конфликты возникают очень часто).
  •  В файле .bzrignore теперь можно задавать шаблоны для отключения игнорирования специфичных файлов. Для этого используйте восклицательный знак (!) в начале шаблона.
    Например, игнорируем все файлы кроме *.py:
    * 
    !*.py
  • Функция shelve: теперь имеется возможность использовать внешний редактор для редактирования изменений, которые должны быть отложены "на полочку". Для этого нужно указать редактор в файле конфигурации как опцию change_editor, например:
    change_editor = vimdiff -fo @new_path @old_path
    
    здесь @new_path и @old_path специальные макросы для подстановки пути к текущей версии файла и зафиксированной его версии.
  • Новая опция unshelve --preview для просмотра отложенных изменений
  • Для checkout теперь можно сделать switch --revision, update --revision
  • При указании ревизии опцией --revision (-r) теперь можно использовать более простой синтаксис в стиле "делай то, что я имею в виду" (DWIM). Т.е. вместо -r tag:foo можно использовать просто -r foo, а вместо -r date:today просто -r today. Префиксы по прежнему можно использовать, и они могут понадобиться в случаях, когда bzr не сможет угадать правильный вариант (например тег 1.1.1 может совпадать с номером ревизии 1.1.1).
  • На Windows в командной строке поддерживаются маски для имен файлов, как на Linux. Раньше такая поддержка существовала в специфичном виде только для команды bzr add, теперь же она реализована в общем виде для всех команд. Поэтому теперь для добавления маски *.obj в файл .bzrignore командой bzr ignore вам нужно позаботиться о том, чтобы аргумент *.obj был взят в кавычки.
  • Поддержка знака тильды (~) как домашнего каталога пользователя в URL вида bzr+ssh://host/~
  • Появился новый раздел в документации: Bazaar System Administrator’s Guide 
  • Значительно переработана документация по плагинам. Кроме основных сведений также содержит автоматически сгенерированную документацию по всем публичным плагинам.
Кроме изменений в самом bzr множество изменений в сопутствующих инструментах и плагинах. Так GUI для bzr Bazaar Explorer меньше чем за 9 месяцев доросло до версии 1.0, с чем мы и поздравляем его автора Йена Клэтворси (Ian Clatworthy).

Разработчики bzr объявили, что предыдущая стабильная версия bzr 2.0 (текущий релиз по состоянию на февраль 2010 — это 2.0.4) будет поддерживаться и далее, но настоятельно рекомендуют переходить на 2.1. Серия 2.1 будет поддерживаться в течение года (как минимум), она же будет включена в дистрибутив Ubuntu Lucid.

Сморите также:

воскресенье, 7 февраля 2010 г.

Уникальные идентификаторы файлов в bzr

Как я уже упоминал в статье "одна ветка = один каталог" bzr унаследовал из baz такую особенность как уникальные идентификаторы файлов. В этой статье рассмотрим идентификаторы подробнее.
В примерах использовался bzr версии 2.1.

Для чего нужны идентификаторы файлов

Для каждого файла, каталога или симлинка Bazaar использует внутри некий уникальный идентификатор, аналогично уникальным идентификаторам ревизий. Присвоение каждому версионированному объекту идентификатора упрощает отслеживание переименований/перемещений файлов и каталогов. Таким образом операция получения журнала ревизий для одного файла, а также операция объединения изменений в разных ветках, — эти операции работаю гораздо эффективнее поскольку им не требуется отслеживать все прошлые переименования. Чтобы получить копию файла из прошлой ревизии через команду
bzr cat -rN file
вам не нужно задумываться о том,  были ли переименования и какое имя было у файла в той ревизии: bzr использует идентификатор файла и сам найдет нужные данные.

Уникальные идентификаторы назначаются в момент добавления файлов/каталогов под контроль версий командой add и затем в течении жизни файлов/каталогов уже не меняются.

Уникальные идентификаторы файлов можно посмотреть с помощью команды bzr ls --show-ids:
$ bzr ls --show-ids
bar.txt    bar.txt-20100207052407-e0zzku5zxmzfsso8-1
foo/       foo-20100207052337-rv090vn2o3x0m720-1

Проблемы с идентификаторами файлов

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

Текущая реализация идентификаторов файлов в bzr страдает следующими недостатками:
  1. Один и тот же файл добавленный в разных ветках одного и того же проекта будет иметь разный идентификатор. Что при последующем объединении веток приведет к проблеме: bzr будет считать эти два файла абсолютно разными. В результате вы получите конфликт объединения и вам придется выбрать какой файл оставить, а какой удалить (и соответственно потерять историю изменений). Изменения между версиями из разных веток придется объединять вручную.
  2. Если вы отмените контроль версий для файла командой bzr remove file а затем передумаете и снова добавите его командой bzr add file, то команда add назначит файлу новый уникальный идентификатор, соответственно история файла прервется и начнется с нуля.
  3. Текущая реализация уникальных идентификаторов в bzr препятствует реализации функции создания копий файлов (аналогично svn copy или hg copy).
Озвученные недостатки являются неприятными, но не критическими. Большинство проектов эти недостатки может и не заметить. Однако замалчивать их в этом блоге я не буду.

В теории эти недостатки можно преодолеть, и главные разработчики bzr даже имеют определенные планы на этот счёт. Но по состоянию на версию bzr 2.1 эти планы еще не реализованы и сложно сказать когда они все-таки будут реализованы.

Проблемы 1 и 2 из списка выше возможно решить в текущей версии bzr с помощью определенных техник.

Использование bzr add --file-ids-from

Поскольку bzr назначает уникальный идентификатор во время выполнения команды bzr add, то для частичного преодоления проблемы номер 1 из списка выше (один и тот же файл добавленный в разных ветках будет иметь разные идентификаторы) можно воспользоваться опцией --file-ids-from команды add. Эта опция в качестве своего аргумента принимает путь к другой ветке и для всех новых файлов, имена которых совпадают с именами файлов в той другой ветке, используются уникальные идентификаторы из другой ветки. Таким образом можно избежать расхождения идентификаторов.

Пример:

C:\work\bzr-day\file-ids>bzr init a

C:\work\bzr-day\file-ids>bzr mkdir a/foo
added a/foo

C:\work\bzr-day\file-ids>bzr commit -m1 a
Committing to: C:/work/bzr-day/file-ids/a/
added foo
Committed revision 1.

C:\work\bzr-day\file-ids>echo > a/bar.txt

C:\work\bzr-day\file-ids>bzr add a
adding bar.txt

C:\work\bzr-day\file-ids>bzr ls a --show-ids
a/bar.txt    bar.txt-20100207052407-e0zzku5zxmzfsso8-1
a/foo/       foo-20100207052337-rv090vn2o3x0m720-1

Теперь создадим копию ветки а для ревизии 1 и также попробуем добавить файл bar.txt:

C:\work\bzr-day\file-ids>bzr branch a b
Branched 1 revision(s).

C:\work\bzr-day\file-ids>echo > b/bar.txt

C:\work\bzr-day\file-ids>bzr add b
adding bar.txt

C:\work\bzr-day\file-ids>bzr ls b --show-ids
b/bar.txt    bar.txt-20100207052932-m88m6b14qvdroa2s-1
b/foo/       foo-20100207052337-rv090vn2o3x0m720-1

Как мы видим уникальные идентификаторы для файла bar.txt в разных ветках различаются.

Повторим те же действия, но файл будем добавлять с опцией --file-ids-from:
C:\work\bzr-day\file-ids>bzr branch a c
Branched 1 revision(s).

C:\work\bzr-day\file-ids>echo > c/bar.txt

C:\work\bzr-day\file-ids>bzr add c --file-ids-from a
adding bar.txt w/ file id from bar.txt

C:\work\bzr-day\file-ids>bzr ls c --show-ids
c/bar.txt    bar.txt-20100207052407-e0zzku5zxmzfsso8-1
c/foo/       foo-20100207052337-rv090vn2o3x0m720-1

Теперь файл bar.txt добавлен с тем же самым уникальным идентификатором.

Восстановление контроля версий для файла после команды bzr remove

Выше указывалось, что вторым недостатком уникальных идентификаторов является то, что файл удаленный из-под контроля версий командой bzr remove при последующем добавлении командой bzr add получит новый уникальный идентификатор. Как следствие для такого файла прервется история. Если вы не хотите терять историю, то вместо использования bzr add для восстановления файла вам необходимо использовать команду bzr revert. В этом случае файл будет восстановлен в последнем зафиксированном состоянии с правильным уникальным идентификатором.

Даже если вы удалили файл несколько ревизий назад, то используйте команду bzr revert -rN file, где N — это номер ревизии, предшествующей удалению файла.

пятница, 15 января 2010 г.

Работа с bzr в централизованном стиле

Наш читатель и автор плагина bzr-externals Евгений Тарасенко рассказывает о работе с Bazaar в централизованном стиле (а-ля svn). Передаю ему слово.

Централизованный стиль

В данной статье я хотел бы обратить внимание на еще один вариант организации работы с системой контроля версий Bazaar, о котором часто забывают в пылу погони за ветками и DVCS. Я говорю о централизованном стиле работы, который используется в Subversion, но в отличии от последнего Bazaar предоставляет намного более гибкий и главное понятный инструмент разработчику. Так в нашем распоряжении оказываются: понятная история ветвлений (попробуйте bzr qlog), локальные фиксации, откат и много других приятных мелочей. Также не стоит забывать что Bazaar расширяемая система и если вам там чего-то не хватает, то можно попробовать написать это самому!

Итак, чем хорош централизованный стиль:
  • во-первых, вся работа ведется в одной директории что очень актуально для многих IDE, которые забывают про мелкие настройки при переходе в другой каталог
  • во-вторых, если вы используете С++ компилятор то количество дополнительных файлов просто съест ваше время и место на жестком диске при каждом новом построении, а при работе с ветками неизбежно придется компилировать и отлаживать сначала ветку, а после слияния и trunk
  • ну и в-третьих, иногда бывает нужно зафиксировать небольшое изменение (одну ревизию) и тут у вас просто меньше лишних телодвижений в отличии от стилей с feature branch или с переключением веток.

Про TortoiseBzr

Для начала, я хотел бы обратить внимание на тот факт, что при установке Bazaar под Windows по умолчанию отключен модуль TortoiseBzr, скорее всего это связано с его некоторой задумчивостью при обновлении статуса иконок файлов, частенько бывает нужно пару раз F5 нажать, чтобы он сообразил что к чему. Поэтому если вы любитель работы из проводника проверьте, что он у вас установлен.

Базовый набор команд

Поскольку Bazaar поддерживает различные псевдонимы (алиасы) для команд, то вы можете выбрать для себя наиболее удобный вариант использования:

checkout, co, qgetnew — извлечь рабочую копию
commit, ci, qcommit, qci — фиксировать изменения
update, up, qupdate, qup — обновить рабочую копию

Я думаю, общая идея понятна, хочу только отметить что префикс "q" обозначает команды с GUI интерфейсом, предоставляемые плагином QBzr.

Извлечение проекта из хранилища

Команда:
bzr checkout bzr://server/project/trunk project
или из контекстного меню проводника: 'Bazaar Checkout/Branch…'



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

Внесение изменений

После внесения локальных изменений (непосредственно программирования) у нас есть два пути.

Путь первый. Если ваши локальные изменения невелики, то вы можете их сразу отправить в хранилище, также как это делает Subversion. Для этого сначала обновляем нашу рабочую копию до последней ревизии находящейся в хранилище:
bzr update
Обратите внимание что слияние ваших изменений и новых ревизий из хранилища произойдет автоматически, без дополнительного bzr merge, что в большинстве случаев является оправданным при правильном распределении задач между разработчиками, иначе придется редактировать конфликты.

И фиксируем наши изменения в хранилище:
bzr qcommit
Путь второй. Если же ваши изменения более значительны и разработка займет какое-то время, что обычно и бывает, то в процесс разработки добавляется новая команда фиксации промежуточных локальных изменений:
bzr qcommit --local
либо через контекстное меню 'Bazaar Commit…' и выбором пункта 'Локальная фиксация'



Команда выполняется столько раз, сколько требует логика разработчика, обычно стараются делать одно функциональное изменение = одна фиксация, но это уже из области best practice.

После окончания разработки и последней локальной фиксации, действуем по схеме 1:

bzr update

И вот тут происходит самое интересное, запустите:

bzr qlog




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

Тестируем наши объединенные изменения и если все нормально фиксируем в хранилище:

bzr qcommit

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

Как отменить merge сделанное в результате bzr update

Хочу предупредить, если после update у вас что-то пошло не так или вы просто передумали объединять ваши изменения, то не спешите использовать команду revert. Эта команда отменит неоконченное объединение и ваши изменения. Ваши локальные ревизии никуда не исчезнут, они останутся в хранилище истории локального дерева файлов. Но вы не вернетесь к своей локальной истории, а напротив останетесь с историей из основной ветки.

Для возвращения к локальной истории вам необходимо узнать идентификатор последней ревизии в вашей локальной истории. Проще всего это сделать при помощи GUI команды qlog, но можно и воспользоваться командой heads из плагина bzrtools.

В случае использования qlog выделите ревизию, помеченую ярлыком Pending Merge и затем в нижнем левом окне в первой строке с версией найдите подстроку вида revid:xxxx, в нашем примере это revid:_-20100111130959-gd9bfn7z2mxxixx3. Выделите ее мышкой и скопируйте в буфер обмена.


Затем закройте qlog и выполните следующие команды:
bzr revert
bzr unbind 
bzr pull . --overwrite -r revid:_-20100111130959-gd9bfn7z2mxxixx3
bzr bind 
Команде pull вы должны передать идентификатор ревизии локальной истории, тот самый, который мы скопировали из окна qlog.

Идентификатор ревизии локальной истории можно также получить при помощи команды heads из плагина bzrtools. Для этого запустите следующую команду:
bzr heads --dead-only
В ответ она выведет информацию следующего вида:
C:\work\bzr-day\Centralised\trunk>bzr heads --dead
HEAD: revision-id: _-20100111130959-gd9bfn7z2mxxixx3 (dead)
  committer: Базарный день
  branch nick: trunk
  timestamp: Mon 2010-01-11 15:09:59 +0200
  message:
    локальная фиксация №2
В строке "HEAD: revision-id:" показан нужный нам идентификатор. Опять же копируем его и запускаем те же действия:

bzr revert
bzr unbind 
bzr pull . --overwrite -r revid:_-20100111130959-gd9bfn7z2mxxixx3
bzr bind 

Даже если вы сделали revert до того, как посмотрели идентификатор локальной ревизии через qlog — не паникуйте, а используйте второй способ с командой heads.
Замечание редакции: если вы используете локальные фиксации, то перед выполнением команды bzr update убедитесь, что все ваши изменения зафиксированы командой commit, либо отложены "на полочку" командой shelve. Иначе вы их легко потеряете при выполнении команды revert. Однако, вместо локальных фиксацией всё-таки более безопасно использовать либо отдельную ветку либо отдельную рабочую копию.

Заключение

Итак, если вы до этого пользовались Subversion и хотите получить небольшой fun от использования системы контроля версий, то смело переходите на Bazaar. Если при этом вам захочется большего, я имею ввиду полный контроль над ветками, то Bazaar умеет и так работать, при этом не придется ломать уже налаженный стиль работы остальных. В общем Bazaar это настоящий швейцарский нож для разработчика с весьма дружественным интерфейсом.

воскресенье, 13 декабря 2009 г.

Модель "одна ветка = один каталог" в bzr

Немного истории

Современная система контроля версий Bazaar имеет свои корни в другой распределенной системе: GNU Arch. У системы Arch было несколько форков (разновидностей), одни из которых также назывался Bazaar (baz). Arch критиковали за излишнюю сложность интерфейса и трудность в освоении. Собственно современный Bazaar (bzr) появился как замена старому baz, и главной целью разработки нового bzr было именно упростить интерфейс пользователя системы, сделать систему удобной и лёгкой в использовании.

По большей части новый bzr добился своей цели (удобства использования). Однако при этом некоторые особенности модели системы Arch перекочевали в том или ином виде в новый Bazaar (bzr). И это накладывает свой отпечаток на работу самой системы и на работу пользователей с системой.

Следует заметить, что старый baz и новый bzr — обе эти системы разрабатывались и разрабатываются в основном за счет финансовой помощи компании Canonical Ltd, широко известной благодаря своему дистрибутиву Linux: Ubuntu.

Также следует отметить, что разработка нового bzr была задумана в ноябре 2004 года и официально началась в февраля 2005 года, на несколько месяцев ранее начала работ над git и hg. До первой половины 2006 года bzr развивался совершенно самостоятельно, как продолжатель baz. После стали очевидны успехи новых систем git и hg, особенно в плане показателей скорости, в результате чего внутренние алгоритмы bzr и форматы хранения данных в репозитории стали постепенно оптимизировать и улучшать в плане скорости работы. Однако несколько фундаментальных особенностей, унаследованных из baz/Arch, остались и до сегодняшнего дня. Понимание этих особенностей поможет вам более эффективно использовать bzr.

Унаследованные особенности

Основные особенности, унаследованные из Arch:
  • модель "каждая ветка живет в отдельном каталоге",
  • доступ к веткам возможен без специального сервера,
  • использование уникальных идентификаторов для файлов внутри системы.
Об уникальных идентификаторах файлов мы поговорим в другой статье, сейчас же рассказ пойдёт о модели "ветка=каталог", о её достоинствах и недостатках.

Каждая ветка живет в отдельном каталоге

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

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

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

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

Рассмотрим внимательно минусы. Они известны давно и для их нивелирования существует ряд методик эффективного использования bzr. Все указанные проблемы (каждая ветка занимает много места, долгое создание новой ветки, разделение одной рабочей копии) эффективно решаются при использовании разделяемого (или общего) репозитория (shared repository). Таким образом указанные минусы нивелируются использованием shared repository и остается лишь маленький недостаток: по умолчанию разделяемый репозиторий не создается сам по себе, его нужно создавать явно, командой init-repository.

Будем предельно честными: bzr позволяет эффективно работать с ветками, но по умолчанию создает обычные ветки. Это недостаток, который особенно сильно влияет на восприятие системы новичками, пришедших в bzr из других систем (git/hg), в которых всегда ветки живут в едином каталоге и представляют собой лишь виртуальные имена для разных линий истории проекта.

Из-за непонимания этого факта bzr много и не всегда оправданно критикуют.

Эффективное использование bzr: разделяемые репозитории

Что такое разделяемый репозиторий (shared repository)?

Для того, чтобы понять, что такое shared repository (разделяемый или общий репозиторий), сначала рассмотрим внутреннее устройство bzr-ветки. Каждая ветка содержит указатель на последнюю зафиксированную ревизию, что однозначно определяет всю историю ветки, поскольку история имеет вид направленного графа. Каждая ветка должна иметь репозиторий, в котором хранятся зафиксированные ревизии и состояние всех файлов ветки для каждой ревизии. Также ветка может иметь рабочую копию (а может и не иметь).

Для обычных веток репозиторий находится в том же каталоге, что и сама ветка. Однако это не обязательно. Репозиторий может находиться и за пределами каталога с веткой, в одном из родительских каталогов. Такой отдельный репозиторий может хранить зафиксированные ревизии и состояния файлов для нескольких веток, находящихся внутри репозитория. А поскольку история веток по большей части совпадает, то в результате место расходуется гораздо более экономно, чем в случае когда каждая ветка хранит полную копию всего репозитория. Каждая ветка, создаваемая внутри разделяемого репозитория, автоматически находит и начинает использовать этот репозиторий.

Поэтому такой репозиторий (shared repository) является общим для нескольких веток, либо можно сказать, что несколько веток разделяют (совместно используют) один и тот же репозиторий.

Следует запомнить фундаментальную разницу между ветками и репозиториями в bzr и репозиториями в git/hg. В bzr под репозиторием в большинстве случае понимают именно разделяемый репозиторий, каждая ветка внутри него — это отдельный каталог. В git/hg в одном каталоге живет и репозиторий, и ветки, и присутствует рабочая копия.

Локальная работа с ветками в репозитории

Для локальной работы рекомендуется создавать разделяемый репозиторий командой:
bzr init-repo PATH
После чего создавать копию главной ветки с сервера внутри репозитория:
cd PATH
bzr branch bzr://server/project/trunk
А уже для конкретной работы над новыми функциями создавать новую ветку на основе локальной копии trunk:
bzr branch trunk new-feature
cd new-feature
При такой работе каждая ветка будет иметь собственную рабочую копию, что позволит легко переходить между разными ветками и объединять изменения между ними. Такая методика работы подробно описывалась в наших предыдущих статьях (базовый набор команд и работа с ветками, см. оглавление).

Использование репозитория на сервере

Для хранения веток на сервере также полезно использовать разделяемые репозитории. Но зачастую сервер выступает просто хранилищем ревизий, поэтому рабочие копии для веток создавать не требуется. Это достигается командой:
bzr init-repo --no-trees URL
Опция командой строки --no-trees указывает, что по умолчанию рабочая копия для веток создаваться не будет.

Остальные операции с ветками можно производить как обычно.

Разделение одной рабочей копии между несколькими ветками

Как уже упоминалось выше в git/hg по умолчанию несколько веток живут в одном каталоге, который называют репозиторий, и в этом же каталоге присутствует рабочая копия, которую совместно используют все ветки. В каждый конкретный момент рабочая копия отражает состояние только текущей активной ветки. Будем называть такую модель работы "git-стиль".

Несмотря на то, что по умолчанию bzr использует другой стиль, однако мы может использовать и git-стиль, если так удобнее.

Для этого нужно создать отдельный репозиторий с указанием флага --no-trees, чтобы локальные ветки в этом репозитории не создавали ненужные рабочие копии. А затем нужно создать отдельную легковесную рабочую копию (lightweight checkout), не содержащую истории. Такая легковесная рабочая копия может быть создана даже за пределами репозитория.
bzr init-repo --no-trees PROJECT
bzr init PROJECT/trunk
bzr checkout --lightweight PROJECT/trunk work
В результате выполнения этой последовательности команд bzr создаст репозиторий в каталоге PROJECT, внутри репозитория создаст ветку trunk, и затем создаст рабочую копию в каталоге work.

Для создания новой ветки и одновременного переключения рабочей копии на нее можно использовать команду:
bzr branch --switch trunk new-feature
Переключение рабочей копии между ветками осуществляется командой switch:
bzr switch trunk
При переключении можно указать опцию --create-branch (-b), чтобы автоматически создать новую ветку:
bzr switch -b bugfix-123
Для получения списка веток в репозитории используйте команду:
bzr branches PROJECT
из плагина bzrtools.

Более подробный рассказ о нюансах работы с bzr в git-стиле будет дан в виде отдельной статьи.

Заключение

В этой статье я попытался описать как и почему в bzr используется модель "одна ветка в одном каталоге", привести доводы за и против такого подхода, а также показать пути эффективного использования bzr.

Как вы могли убедиться, bzr — это очень гибкая система, и она позволяет достичь намного большего при умелом использовании. Однако требует несколько большего времени на освоение.

Недостатком можно назвать лишь то, что по умолчанию bzr работает в не самом оптимальном режиме, поэтому для достижения эффективности требуется сделать несколько больше телодвижений. Следует ли это считать смертельным недостатком? Уверен, что нет.

Впрочем, каждому решать самому. Помните лишь, что каждая из современных распределенных систем (git/hg/bzr) имеет как достоинства, так и недостатки. Однако очень часто значимость как плюсов, так и минусов, не абсолютна, а относительна, и зависит от конкретного проекта и предпочитаемого стиля работы. И часто одни недостатки компенсируются другими достоинствами.

пятница, 11 декабря 2009 г.

Уборка мусора: команда bzr clean-tree

Часто во время работы над некоторыми функциями в рабочем каталоге оседают какие-то дополнительные материалы, тестовые данные или скрипты. Всё, что относится к текущей работе и может быть безболезненно выброшено потом. Такие данные могут быть добавлены в список игнорируемых файлов, а могут и не быть, поскольку носят временный характер.

И вот когда приходит время удалять это барахло, что вы делаете? Удаляете вручную?

Есть более удобный способ: использовать команду clean-tree (начиная с версии bzr 1.13 эта команда доступна в самом bzr, ранее эта команда жила в плагине bzrtools). Эта команда показывает вам список неизвестных (неверсионированных) файлов и предлагает их удалить. Просто и без затей.

Также эта команда имеет удобный ключ командной строки: --ignored. С этим ключом clean-tree будет удалять только игнорируемые файлы. Такая функция тоже бывает полезной, особенно если у вас нет make clean.

Приятной уборки!

вторник, 8 декабря 2009 г.

Управление кодировкой файла при работе с QBzr (GUI для bzr)

QBzr — это кросс-платформенный GUI плагин для bzr, использующий библиотеку Qt4/PyQt4. Мы рассмотрим вопрос управления кодировкой файлов для их корректного отображения в окнах QBzr.

QBzr и кодировки

Поскольку [Py]Qt4 ориентирована на использование unicode для отображения текстовых данных, то возникает небольшая проблема с файлами, содержащими неанглийские тексты (например, русский или японский). Для корректного отображения таких текстов QBzr необходимо знать кодировку, в которой был сохранен текст.

По умолчанию, QBzr предполагает, что текст имеет кодировку UTF-8 (с автоматическим переключением на Latin-1, если текст невозможно отобразить как UTF-8). Кодировка UTF-8 довольно популярна и используется на многих современных дистрибутивах Linux и Mac. Однако на Windows часто используется кодировка ANSI (например, cp1251 для русского текста), а на старых платформах — исторически сложившиеся кодировки (например, koi8-r для русского текста). Поэтому некоторым пользователям приходится указывать кодировку вручную одним из 3х способов:
  • указать кодировку в командной строке
  • указать кодировку в конфигурационном файле
  • указать кодировку непосредственно в диалоговом окне с отображаемым текстом
Рассмотрим эти методы подробнее.

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

Большинство команд, непосредственно отображающих содержимое файлов, таких как qdiff, qannotate, qcat и qviewer, имеют опцию командной строки --encoding. Эта опция позволяет напрямую задать кодировку файла из набора поддерживаемых библиотеками Python (полный список). Часто используемые кодировки для русского языка:
  • cp1251 (Windows ANSI)
  • cp866 (DOS/OEM)
  • koi8-r (Unix)
Для украинского языка аналогично: cp1251, cp866, koi8-u.

Настройки в конфигурационном файле

Кодировка, указанная опцией --encoding, либо выбранная непосредственно (см. ниже), сохраняется в конфигурационном файле текущей ветки (файл .bzr/branch/branch.conf) как опция:
encodng = xxx
Сохраненная кодировка будет использоваться по умолчанию при следующем запуске соответствующей команды QBzr.

Если вы постоянно работаете с одной и той же кодировкой (например, cp1251), то ее можно указать как кодировку по умолчанию для всех веток, прописав в главном конфигурационном файле bazaar.conf:
[DEFAULT]
email = Vasya Pupkin <vasya@pupkin.ru>
encoding = cp1251
Более тонкой настройки можно добиться при использовании конфигурационного файла locations.conf.

Эти настройки будут использоваться для отображения всех файлов. К сожалению, по состоянию на декабрь 2009, bzr и qbzr не имеют возможности сохранять выборочные настройки для отдельных файлов. Однако, такая функциональность может появиться в будущем.

Непосредственное управление

Благодаря Наоки Инада (Naoki INADA) в QBzr 0.17 появилась возможность управлять кодировкой файла прямо из соответствующих диалоговых окон. В окнах для отображения diff, annotate, cat появился элемент (выпадающий список), позволяющий выбрать нужную кодировку. Это очень полезное улучшение, особенно для пользователей TortoiseBzr и Bazaar Explorer, поскольку эти программы никак не передают данные о кодировках в диалоговые окна QBzr.

Diff:




Annotate:





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

Новая версия QBzr 0.17 с показанным элементом выбора кодировок будет выпущена в середине декабря 2009. Однако уже сейчас эти улучшения доступны в ветке trunk2a.

пятница, 4 декабря 2009 г.

Строгий контроль со стороны bzr

Хороший инструмент не только помогает нам выполнить работу качественно, но и помогает предотвратить ошибки, обусловленные человеческим фактором. Рассмотрим пару примеров, когда bzr может помочь вам избежать таких ошибок.

Ситуация

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

Собрав всю волю в кулак, вы находите подозрительные места, дорабатываете код, добавляете новый модуль, фиксируете изменения, запускаете, проверяете и ура? Нет, снова что-то не так... ах вот же она опечатка. Последние изменения, всё работает. И вы запускаете команду bzr push и передаете свою работу на сервер.

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

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

Ошибка №1: забыли добавить новые модули под контроль версий

Достаточно частая ситуация, когда фиксируются изменения в коде старых файлов и при этом забывают добавить новые файлы под контроль версий командой bzr add. В результате зафиксированное состояние дерева файлов и реальный набор файлов в рабочем каталоге будут отличаться. Что приведет к частичной или полной неработоспособности вашего кода.

В большинстве случаев подобного рода ошибки можно поймать внимательным просмотром вывода команд bzr status (до и/или после фиксации) и bzr diff. Но в пылу сражения может случиться всякое, особенно если вы фиксируете только часть изменений.

commit --strict

В таких ситуациях bzr может помочь если вы будете использовать опцию --strict для команды commit. Данная опция делает невозможным успешную фиксацию, если в рабочем каталоге присутствуют неизвестные файлы, которые не помещены под контроль версий командой add, и не соответствуют маскам игнорируемых файлов.
C:\work\bzr-day\strict>bzr ci --strict -m foo
Committing to: C:/work/bzr-day/strict/
aborting commit write group: StrictCommitFailed()
bzr: ERROR: Commit refused because there are unknown files in the working tree.
При использовании пользовательских псевдонимов вы можете включить эту опцию по умолчанию:
bzr alias commit="commit --strict"
bzr alias ci="commit --strict"

Ошибка №2: последние изменения не зафиксированы, push передает на сервер неокончательный код

С этой ситуацией более-менее понятно. Push работает на уровне зафиксированной истории ветки, поэтому состояние рабочих файлов для него проверять не обязательно.

Опять же внимательный просмотр вывода команды bzr status поможет поймать такого рода ошибки.

push --strict

К счастью, начиная с версии bzr 1.17 команда push автоматически проверяет рабочее дерево файлов на наличие незафиксированных изменений, включая неоконченное объединение. И отказывается работать, если таковые обнаружатся:
C:\work\bzr-day\strict>bzr push ../foo
bzr: ERROR: Working tree "C:/work/bzr-day/strict/" has uncommitted changes (See bzr status). Use --no-strict to force the push.
Как видно, эту проверку можно отключать, указывая опцию --no-strict.

push --no-strict

Если подобная проверка вам почему-то не по душе, то не спешите заводить новый пользовательский псевдоним для команды push, а используйте опцию push_strict в файле конфигурации bazaar.conf или branch.conf. Например:
push_strict = False

Заключение

Мы рассмотрели две встроенные функции bzr для контроля и предотвращения некоторых распространенных ошибок при выполнении операций commit и push. Как указывалось, такие ошибки можно отловить при внимательном анализе вывода команды status. Но в том-то и дело, что подобные ошибки случаются когда смотрят не внимательно или не смотрят вообще.

Дополнительные проверки, специфичные для конкретного проекта, можно осуществлять через функции-хуки, например хуки для событий pre_commit или pre_change_branch_tip. В качестве примера pre_commt хука см. плагин checkeol, который может осуществлять проверку концовок строк в фиксируемых файлах.

среда, 2 декабря 2009 г.

Статьи про bzr в блоге Kash Farooq

Kash Farooq (Каш Фарук), .NET разработчик из Великобритании, опубликовал в своем блоге ряд статей про bzr.

Затрагиваемые темы: работа с Subversion при помощи плагина bzr-svn, описания настроек внешних GUI утилит для объединения изменений и решения конфликтов, операции объединения и переименования в bzr.
__________________

Я считаю, что будет полезным делать обзоры и маленькую рекламу блогам, которые более-менее регулярно пишут про работу с bzr (чуть по более, чем заметка в стиле "я вчера поставил bzr и мне понравилось").
Если вы знаете такие блоги или сами регулярно публикуете материалы на эту тему, то оставляйте ссылки в комментариях либо присылайте электропочтой.

понедельник, 30 ноября 2009 г.

Пользовательские псевдонимы команд bzr (aliases)

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

Отличие пользовательских псевдонимов от встроенных псевдонимов команд

Большинство стандартных команд bzr и даже команд, добавляемых плагинами, имеют заранее предопределенный набор альтернативных имен (псевдонимов) для вызова этих команд. Так, команда commit имеет псевдонимы ci и checkin, а statusst и stat, и т.п. Эти псевдонимы выводятся при запросе справки на конкретную команду (bzr xxx --help или bzr xxx --usage).

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

Как работают пользовательские псевдонимы

Пользователь может определить псевдоним, как некоторое имя, и связать с этим именем существующую команду bzr и дополнительно какие-то опции и параметры. Тогда при вызове команды как:
bzr имя_псевдонима [опции аргументы]
вместо имени псевдонима будет подставляться значение псевдонима: определенная ранее реальная команда bzr + дополнительные параметры.

При этом опции псевдонима могут переопределяться в конкретной командной строке: просто укажите новое значение и bzr будет использовать последнее определенное значение опции при запуске команды. Для отмены действия булевой опции используйте префикс no, например: --short => --no-short.

У псевдонимов есть еще одно интересное свойство: вы можете в качестве имени псевдонима использовать имя существующей команды bzr. Это особенно полезно в тех случаях, когда вы хотите "навсегда" поменять поведение какой-то команды по умолчанию. Например, чтобы вывод команды status имел компактный вид применяется опция --short или -S. Если вы предпочитаете всегда использовать такую форму вывода информации, то можете определить псевдоним
status = status --short
Следует однако помнить, что все встроенные альтернативные имена команд (о которых упоминалось ранее) автоматически не переопределяются при переопределении команды. Поэтому если вы определили псевдоним для status как описано выше, то запуск bzr st будет производиться обычным (не переопределенным) способом.

Как определить свой псевдоним

Определения пользовательских псевдонимов хранятся в файле bazaar.conf (~/.bazaar/bazaar.conf на Linux и C:\Documents and Settings\USERNAME\Application Data\bazaar\2.0\bazaar.conf на Windows) внутри секции [ALIASES]. Определения псевдонимов имеют простую форму:
имя_псевдонима = имя_команды [опции]
Для определения новых псевдонимов или редактирования старых вы можете как напрямую редактировать файл bazaar.conf, так и использовать встроенную команду alias, либо воспользоваться GUI диалогами из плагинов QBzr (команда qconfig) или bzr-gtk (команда gpreferences).

Использование команды bzr alias

Запуск команды bzr alias без параметров выведет список уже определенных вами псевдонимов.

Для определения нового псевдонима используйте синтаксис:
bzr alias имя_псевдонима="значение"
(Не забывайте использовать кавычки если значение псевдонима состоит из имени команды bzr и набора опций по умолчанию).

Например:
bzr alias st="status --short"

Для удаления ранее определенного псевдонима используйте опцию --remove:
bzr alias st --remove

Примеры псевдонимов

Кроме уже упомянутого ранее псевдонима для status --short рассмотрим еще несколько примеров полезных псевдонимов.

Получать вывод команды missing в формате в максимально сжатом виде (1 ревизия на строку):
miss = missing --line
Получить список десяти последних ревизий в компактном виде:
last = log -l10 --short
Вывод максимальной информации в аннотации файла:
ann = annotate --long
Всегда удалять файлы из-под контроля bzr без удаления их с диска:
forget = remove --keep
Матерые пользователи darcs могут захотеть определить псевдоним:
whatsnew = diff
Примечание: примеры выше даны в нотации, подходящей для помещения в конфигурационный файл bazaar.conf. Для установки их в командной строке через команду bzr alias используйте форму имя="команда опции".

Вредные советы

bzr никак не проверяет смысл и содержание псевдонимов, поэтому вполне реально определить что-нибудь неожиданно деструктивное, например:
ci = revert --no-backup
Я, впрочем, надеюсь наши читатели такими диверсиями заниматься не будут.

Временное отключение пользовательских псевдонимов

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

Глобальная опция --no-aliases, заданная до имени команды, поможет вам в этом:
bzr --no-aliases xxx
Совет: опции --no-plugins и --no-aliases целесообразно использовать при замерах скорости работы bzr.

Заключение

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

пятница, 27 ноября 2009 г.

Встроенная справочная служба bzr: получение списка аргументов и опций для команды

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

К счастью в bzr версии 1.14 появилось очень удобное дополнение: при запуске команды с опцией --usage на экран выводится краткая справка по команде, которая содержит только назначение команды (1 строка) и список аргументов и опций командной строки. Очень удобно, когда запамятовал как называется (правильно пишется) нужная опция.

Сравните вывод bzr add --help и bzr add --usage:
C:\>bzr add --usage
Purpose: Add specified files or directories.
Usage:   bzr add [FILE...]

Options:
  --dry-run            Show what would be done, but don't actually do
                       anything.
  -v, --verbose        Display more information.
  --file-ids-from=ARG  Lookup file ids from this tree.
  --no-recurse         Don't recursively add the contents of directories.
  -q, --quiet          Only display errors and warnings.
  --usage              Show usage message and options.
  -h, --help           Show help message.

See bzr help add for more details and examples.

See also: ignore, remove

Подробнее о встроенной справочной службе можно прочитать в статье "bzr help: встроенная справочная служба класса "люкс" (Часть 1, Часть 2)"

четверг, 26 ноября 2009 г.

Список статей блога bzr-day

Список статей теперь находится на странице http://bzr-day.blogspot.com/p/bzr-day.html





Общие сведения

    Концепции

    Настройки

    Справка по bzr

    Работа с bzr

    Рецепты

    Дополнительно

    Плагины

    bzr-svn

    QBzr

    Блоги


    Список обновлен: 2010/01/15

      среда, 25 ноября 2009 г.

      Как добавить каталог без содержащихся в нём файлов?

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

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

      Используйте опцию --no-recurse. Эта опция отключает обычное рекурсивное поведение и при её использовании будут добавлены только те каталоги (или файлы), которые явно указаны в командной строке.

      Сравните обычное рекурсивное поведение:
      C:\work\bzr-day\add>bzr st
      unknown:
        foo/
      
      C:\work\bzr-day\add>dir /b foo
      eggs
      spam
      
      C:\work\bzr-day\add>bzr add foo
      adding foo
      adding foo/eggs
      adding foo/spam
      
      И поведение при использовании опции --no-recurse
      C:\work\bzr-day\add>bzr st
      unknown:
        foo/
      
      C:\work\bzr-day\add>bzr add foo --no-recurse
      adding foo
      
      C:\work\bzr-day\add>bzr st
      added:
        foo/
      unknown:
        foo/eggs
        foo/spam