вторник, 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 это настоящий швейцарский нож для разработчика с весьма дружественным интерфейсом.