В первой части мы рассмотрели работу с одной веткой. Рассмотрим теперь работу с несколькими ветками.
Сценарий работы
Создадим копию ветки для параллельной работы. Изменим некоторые файлы в старой и новой ветках и зафиксируем новое состояние. Объединим изменения в двух ветках.
Для чего нужны дополнительные ветки?
Использование веток — это неотъемлемая часть при распределенной работе. Фактически каждый участник проекта работает в своей ветке на своем компьютере, периодически рабочие ветки объединяются в главную или интеграционную ветку, которая считается основной веткой проекта.
Часто ветки используются, чтобы разделить разработку нового функционала программного продукта и поддержку выпущенных версий. В этом случае выпущенные версии (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: Начальное состояние файлов
Объединенные ревизии отображаются под ревизией, в которой объединение было зафиксировано, с небольшим отступом. Соответствующий граф ревизий теперь выглядит следующим образом:
C:\Temp>bzr branch Test Experimental -r 2.1.1
Branched 3 revision(s).
Итак, мы рассмотрели работу с несколькими ветками и научились объединять ветки. В следующих статьях мы рассмотрим другие команды для работы с ветками, а также научимся справляться с конфликтами объединения.
Очень интересно! Может я тороплю события но не расскажите ли вы (хотя бы в кратце) про аналоги gitweb/hgweb для bzr?
ОтветитьУдалитьЕсли совсем вкратце, то: официально поддерживаемым web-интерфейсом для просмотра истории и изменений в файлах является Loggerhead (https://launchpad.net/loggerhead).
ОтветитьУдалитьСписок остальных вариантов можно найти здесь: http://bazaar-vcs.org/WebInterfaces
Кроме того, существует неплохая интеграция bzr c Trac и Redmine.
Не хочу устраивать холивар.. но утверждение, насчет стремления базаровцев сохранять обратную совместимость, не походит на правду.
ОтветитьУдалить$ bzr branch lp:loggerhead
You have not informed bzr of your launchpad login. If you are attempting a
write operation and it fails, run "bzr launchpad-login YOUR_ID" and try again.
bzr: ERROR: Unknown branch format: 'Bazaar Branch Format 7 (needs bzr 1.6)\n'
я конечно понимаю, что тащить всякое старье за собой это тоже плохо, но у того же git и hg с этим нет проблем. (точнее я не встречался с ними)
> но у того же git и hg с этим нет проблем.
ОтветитьУдалитьнет проблем с чем? git и hg старых версий умеют автоматически читать данные из репозиториев новых неизвестных форматов?
В сообщении об ошибке написано, что нужна версия bzr не ниже 1.6. У вас установлена более старая. 1.6 была выпущена в августе 2008, т.е. практически полгода назад. На прошлой неделе была выпущена версия 1.13. Обновиться не пробовали? Вам нужно обновиться хотя бы до 1.6.1, лучше 1.9 или более новая.
> Не хочу устраивать холивар
И это правильно. Я не собираюсь в этом блоге терпеть никаких даже намеков на холивары. Делайте это в своих блогах.
Обратная совместимость значит, что используя более позднюю версию Bazaar можно читать данные в форматах предыдущих версий. И это действительно так и кроме этого можно даже преобразовывать данные в более старые форматы.
ОтветитьУдалитьВ данном случае разработчики LoggerHead (не Bazaar) решили использовать более новый формат, который не совместим со старыми версиями Bazaar и это их право. Соотв. если использовать версию начиная с 1.6 (а она вышла где-то пол года назад), то все должно быть нормально.
> git и hg старых версий умеют автоматически читать данные из репозиториев новых неизвестных форматов?
ОтветитьУдалитьу git точно нет проблем чтением из репозиториев инициализированных новыми версиями, во всяком случае с 1.4 такой проблемы я не наблюдал.
> В сообщении об ошибке написано, что нужна версия bzr не ниже 1.6.
это я понял ;)
> Обновиться не пробовали?
да я бэкпортировал 1.10 (у меня debian, кстати в debian stable сейчас `старая' версия bzr, которая уже с lp не работает -> плохо)
Скажите, пожалуйста, а что будет, если сделать несколько подряд merge основной веток и функциаональных без commit'та.
ОтветитьУдалить1) Буду ли в реальности внесены изменения в эти файлы или же нет? Если нет, то получается, что merge объединяет изменения между файлами на уровне репозитория, а не на уровне физических фйлов?
2) Как remerge на несколько шагов назад, например, я сделал три подряд merge, без commit'a, а затем с помощью remerge хочу откатиться на 3 шага назад?
Насколько я понял, Вы являетесь единственным русскоязычным и виндовым разработчиком Bazaar. Поэтому решил написать Вам. Почтового адреса не нашёл, поэтому скриншоты выслать не могу. Делаю bzr diff, получаю вместо букв "козюбрики". Файлы названы по-русски, да. И содержание русское. Но вывод кривой. Как это можно поправить? (на всякий случай - мой адрес os80@rambler.ru)
ОтветитьУдалить2os80: посмотрите комментарии к статье http://bzr-day.blogspot.com/2009/03/bzr-1.html -- там написано как бороться.
ОтветитьУдалитьВопросы лучше всего задавайть здесь: http://groups.google.com/group/ru_bzr
В статье рассмотрен принцип ветвления когда создается отдельная ветка в отдельном рабочем каталоге. А что если сделать экспериментальную ветку в текущем рабочем каталоге проекта? Возможно такое?
ОтветитьУдалитьВ Bazaar с самого начала была принята модель: "один каталог= одна ветка". Поэтому каждая ветка живет отдельно. Это так для bzr v.1.x-2.0.
ОтветитьУдалитьПереход к модели "много веток в одном каталоге" обсуждается, но он не появится раньше версии bzr 3.0 скорее всего.
Если вам нужно экономить место на диске, потому что рабочая копия каждой ветки занимает много места, то можно использовать разделяемый общий репозиторий с ветками без рабочих копий (treless shared repository) и иметь одну рабочую копию, которую переключать между разными ветками. Подробно о таком подходе написано в документации:
http://doc.bazaar-vcs.org/latest/en/user-guide/reusing_a_checkout.html#switching-a-lightweight-checkout
В bzr версии 2.0.1 команда log не показывает ревизии из объединенных веток, если ее не попросить об этом с помощью --include-merges
ОтветитьУдалитьЗдравствуйте. Поплыла разметка в некоторых примерах на этой странице, неудобно читать.)
ОтветитьУдалитьСпасибо, что сказали. Не понимаю почему испортилась разметка, я поправил.
ОтветитьУдалить