Breezy User Guide¶
Introduction¶
Introducing Breezy¶
What is Breezy?¶
Breezy is a tool for helping people collaborate. It tracks the changes that you and other people make to a group of files - such as software source code - to give you snapshots of each stage of their evolution. Using that information, Breezy can effortlessly merge your work with other people’s.
Tools like Breezy are called version control systems (VCS) and have long been popular with software developers. Breezy’s ease of use, flexibility and simple setup make it ideal not only for software developers but also for other groups who work together on files and documents, such as technical writers, web designers and translators.
This guide takes you through installing Breezy and how to use it, whether on your own or with a team of other people. If you’re already familiar with distributed version control and want to dive straight in, you may wish to skim this section and jump straight to Learning more.
A brief history of version control systems¶
Version control tools have been evolving for several decades now. In simple terms, there have been 4 generations of tools:
file versioning tools, e.g. SCCS, RCS
tree versioning tools - central style, e.g. CVS
tree versioning tools - central style, take two, e.g. Subversion
tree versioning tools - distributed style, e.g. Breezy.
The design and implementation of Breezy builds on the lessons learned from all the previous generations of tools. In particular, Breezy cleanly supports both the central and the distributed version control models so you can change models as it makes sense, without needing to change tools.
Central vs distributed VCS¶
Many traditional VCS tools require a central server which provides the change history or repository for a tree of files. To work on the files, users need to connect to the server and checkout the files. This gives them a directory or working tree in which a person can make changes. To record or commit these changes, the user needs access to the central server and they need to ensure they have merged their work with the latest version stored before trying to commit. This approach is known as the centralized model.
The centralized model has proven useful over time but it can have some notable drawbacks. Firstly, a centralized VCS requires that one is able to connect to the server whenever one wants to do version control work. Secondly, the centralized model tightly links the act of snapshotting changes with the act of publishing those changes. This can be good in some circumstances but it has a negative influence on quality in others.
Distributed VCS tools let users and teams have multiple repositories rather than just a single central one. In Breezy’s case, the history is normally kept in the same place as the code that is being version controlled. This allows the user to commit their changes whenever it makes sense, even when offline. Network access is only required when publishing changes or when accessing changes in another location.
In fact, using distributed VCS tools wisely can have advantages well beyond the obvious one of disconnected operations for developers. Other advantages include:
easier for developers to create experimental branches
easier ad-hoc collaboration with peers
less time required on mechanical tasks - more time for creativity
increased release management flexibility through the use of “feature-wide” commits
trunk quality and stability can be kept higher, making everyone’s job less stressful
in open communities:
easier for non-core developers to create and maintain changes
easier for core developers to work with non-core developers and move them into the core
in companies, easier to work with distributed and outsourced teams.
For a detailed look at the advantages of distributed VCS tools over centralized VCS tools, see http://wiki.bazaar.canonical.com/BzrWhy.
Key features of Breezy¶
While Breezy is not the only distributed VCS tool around, it does have some notable features that make it an excellent choice for many teams and communities. A summary of these and comparisons with other VCS tools can be found on the Bazaar Wiki, http://wiki.bazaar.canonical.com.
Of the many features, one in particular is worth highlighting: Breezy is completely free software written in Python. As a result, it is easy to contribute improvements. If you wish to get involved, please see https://www.breezy-vcs.org/pages/support.html.
Learning more¶
This manual provides an easy to read introduction to Breezy and how to use it effectively. It is recommended that all users read at least the rest of this chapter as it:
explains the core concepts users need to know
introduces some popular ways of using Breezy to collaborate.
Chapters 2-6 provide a closer look at how to use Breezy to complete various tasks. It is recommended that most users read these in first-to-last order shortly after starting to use Breezy. Chapter 7 and beyond provide additional information that helps you make the most of Breezy once the core functionality is understood. This material can be read when required and in any order.
If you are already familiar with other version control tools, you may wish to get started quickly by reading the following documents:
Breezy in five minutes - a mini-tutorial
Breezy Quick Start Card - a one page summary of commonly used commands.
In addition, the online help and Breezy User Reference provide all the details on the commands and options available.
We hope you find this manual useful. If you have suggestions on how it or the rest of Breezy’s documentation can be improved, please contact us on the mailing list, bazaar@lists.canonical.com.
Core concepts¶
A simple user model¶
To use Breezy you need to understand four core concepts:
Revision - a snapshot of the files you’re working with.
Working tree - the directory containing your version-controlled files and sub-directories.
Branch - an ordered set of revisions that describe the history of a set of files.
Repository - a store of revisions.
Let’s look at each in more detail.
Revision¶
A revision is a snapshot of the state of a tree of files and directories, including their content and shape. A revision also has some metadata associated with it, including:
Who committed it
When it was committed
A commit message
Parent revisions from which it was derived
Revisions are immutable and can be globally, uniquely identified by a revision-id. An example revision-id is:
pqm@pqm.ubuntu.com-20071129184101-u9506rihe4zbzyyz
Revision-ids are generated at commit time or, for imports from other systems, at the time of import. While revision-ids are necessary for internal use and external tool integration, branch-specific revision numbers are the preferred interface for humans.
Revision numbers are dotted decimal identifiers like 1, 42 and 2977.1.59 that trace a path through the revision number graph for a branch. Revision numbers are generally shorter than revision-ids and, within a single branch, can be compared with each other to get a sense of their relationship. For example, revision 10 is the mainline (see below) revision immediately after revision 9. Revision numbers are generated on the fly when commands are executing, because they depend on which revision is the tip (i.e. most recent revision) in the branch.
See Specifying revisions in the appendices for a closer look at the numerous ways that revisions and ranges of revisions can be specified in Breezy, and Understanding Revision Numbers for a more detailed description of revision numbering.
Working Tree¶
A working tree is a version-controlled directory holding files the user can edit. A working tree is associated with a branch.
Many commands use the working tree as their context, e.g. commit
makes
a new revision using the current content of files in the working tree.
Branch¶
In the simplest case, a branch is an ordered series of revisions. The last revision is known as the tip.
Branches may split apart and be merged back together, forming a graph of revisions. Technically, the graph shows directed relationships (between parent and child revisions) and there are no loops, so you may hear some people refer to it as a directed acyclic graph or DAG.
If this name sounds scary, don’t worry. The important things to remember are:
The primary line of development within the DAG is called the mainline, trunk, or simply the left hand side (LHS).
A branch might have other lines of development and if it does, these other lines of development begin at some point and end at another point.
Repository¶
A repository is simply a store of revisions. In the simplest case, each branch has its own repository. In other cases, it makes sense for branches to share a repository in order to optimize disk usage.
Putting the concepts together¶
Once you have grasped the concepts above, the various ways of using Breezy should become easier to understand. The simplest way of using Breezy is to use a standalone tree, which has a working tree, branch, and repository all in a single location. Other common scenarios include:
Shared repositories - working tree and branch are colocated, but the repository is in a higher level directory.
Stacked branches - branch stores just its unique revisions, using its parent’s repository for common revisions.
Lightweight checkouts - branch is stored in a different location to the working tree.
The best way to use Breezy, however, depends on your needs. Let’s take a look at some common workflows next.
Workflows¶
Breezy is just a tool¶
Breezy supports many different ways of working together. This means that you can start with one workflow and adapt it over time as circumstances change. There is no “one true way” that always makes sense and there never will be. This section provides a brief overview of some popular workflows supported by Breezy.
Keep in mind that these workflow are just some examples of how Breezy can be used. You may want to use a workflow not listed here, perhaps building on the ideas below.
Solo¶
Whether developing software, editing documents or changing configuration files, having an easy-to-use VCS tool can help. A single user can use this workflow effectively for managing projects where they are the only contributor.

Advantages of this workflow over not using version control at all include:
backup of old versions
rollback to an earlier state
tracking of history.
The key features of Breezy appropriate for this workflow are low administration (no server setup) and ease of use.
Partner¶
Sometimes two people need to work together sharing changes as they go. This commonly starts off as a Solo workflow (see above) or a team-oriented workflow (see below). At some point, the second person takes a branch (copy including history) of what the first person has done. They can then work in parallel exchanging changes by merging when appropriate.

Advantages over Solo are:
easier sharing of changes
each line of each text file can be attributed to a particular change including who changed it, when and why.
When implementing this workflow, Breezy’s advantages over CVS and Subversion include:
no server to setup
intelligent merging means merging multiple times isn’t painful.
Centralized¶
Also known as lock-step, this is essentially the same as the workflow
encouraged/enforced by CVS and Subversion. All developers work on the same
branch (or branches). They run brz update
to get their checkout up-to-date,
then brz commit
to publish their changes to the central location.

Subversion and CVS are good choices for implementing this workflow because they make it easy. Breezy directly supports it as well while providing some important advantages over CVS and Subversion:
better branching and merging
better renaming support.
Centralized with local commits¶
This is essentially the same as the Centralized model, except that when
developers are making a series of changes, they do commit --local
or unbind
their checkout. When it is complete, they commit their work to the shared
mainline.

Advantages over Centralized:
Can work offline, e.g. when disconnected during travel
Less chance for a bad commit to interfere with everyone else’s work
Subversion and CVS do not support this model. Other distributed VCS tools can support it but do so less directly than Breezy does.
Decentralized with human gatekeeper¶
In this workflow, each developer has their own branch or branches, plus read-only access to the main branch. One developer (the gatekeeper) has commit rights to the main branch. When a developer wants their work merged, they ask the gatekeeper to merge it. The gatekeeper does code review, and merges the work into the main branch if it meets the necessary standards.

Advantage over Decentralized with shared mainline:
Code is always reviewed before it enters the mainline
Tighter control over when changes get incorporated into the mainline.
A companion tool of Breezy’s called Bundle Buggy can be very useful for tracking what changes are up for review, their status and reviewer comments.
Decentralized with automatic gatekeeper¶
In this workflow, each developer has their own branch or branches, plus read-only access to the mainline. A software gatekeeper has commit rights to the main branch. When a developer wants their work merged, they request another person to review it. Once it has passed review, either the original author or the reviewer asks the gatekeeper software to merge it, depending on team policies. The gatekeeper software does a merge, a compile, and runs the test suite. If and only if the code passes, it is merged into the mainline.
Note: As an alternative, the review step can be skipped and the author can submit the change to the automatic gatekeeper without it. (This is particularly appropriate when using practices such as Pair Programming that effectively promote just-in-time reviews instead of reviewing code as a separate step.)

Advantages over Decentralized with human gatekeeper:
Code is always tested before it enters the mainline (so the integrity of the mainline is higher)
Scales better as teams grow.
A companion tool of Breezy’s called Patch Queue Manager (PQM) can provide the automated gatekeeper capability.
Implementing a workflow¶
For an in-depth look at how to implement each of the workflows above, see chapters 3 to 6 in this manual. First though, chapter 2 explains some important pre-requisites including installation, general usage instructions and configuration tips.
Getting started¶
Installing Breezy¶
GNU/Linux¶
Breezy packages are available for most popular GNU/Linux distributions including Ubuntu, Debian, Red Hat and Gentoo. See https://www.breezy-vcs.org/pages/download.html for the latest instructions.
Windows¶
For Windows users, an installer is available that includes the core Breezy package together with necessary pre-requisites and some useful plug-ins. See https://www.breezy-vcs.org/pages/download.html for the latest instructions.
Note: If you are running Cygwin on Windows, a Breezy for Cygwin package is available and ought to be used instead of the Windows version.
Other operating systems¶
Beyond Linux and Windows, Breezy packages are available for a large range of other operating systems include Mac OS X, FreeBSD and Solaris. See https://www.breezy-vcs.org/pages/download.html for the latest instructions.
Installing from scratch¶
If you wish to install Breezy from scratch rather than using a pre-built package, the steps are:
If it is not installed already, install Python 2.7 or later.
Download the
breezy-xxx.tar.gz
file (where xxx is the version number) from https://www.breezy-vcs.org/pages/download.html or from Launchpad (https://launchpad.net/~brz/).Unpack the archive using tar, WinZip or equivalent.
Put the created directory on your PATH.
To test the installation, try running the brz command like this:
brz version
This will display the version of Breezy you have installed. If this doesn’t work, please contact us via email or IRC so we can help you get things working.
Installing into site-wide locations¶
Instead of adding the directory to your PATH, you can install brz into the system locations using:
python setup.py install
If you do not have a compiler, or do not have the python development tools installed, brz supplies a (slower) pure-python implementation of all extensions. You can install without compiling extensions with:
python setup.py install build_ext --allow-python-fallback
Running the development version¶
You may wish to always be using the very latest development version of Breezy. Note that this is not recommended for the majority of users as there is an increased risk of bugs. On the other hand, the development version is remarkably solid (thanks to the processes we follow) and running it makes it easier for you to send us changes for bugs and improvements. It also helps us by having more people testing the latest software.
Here are the steps to follow:
Install Breezy using one of the methods given above.
Get a copy of the development version like this:
brz branch lp:brzPut the created directory on your PATH.
Advanced users may also wish to build the optional C extensions for greater
speed. This can be done using make
and requires cython
and a C compiler.
Please contact us on email or IRC if you need assistance with this.
Running multiple versions¶
It’s easy to have multiple versions of Breezy installed and to switch between them. To do this, simply provide the full pathname to the brz command you wish to run. The relevant libraries will be automatically detected and used. Of course, if you do not provide a pathname, then the brz used will be the one found on your system path as normal.
Note that this capability is particularly useful if you wish to run (or test) both the latest released version and the development version say.
Entering commands¶
User interfaces¶
There are numerous user interfaces available for Breezy. The core package provides a command line tool called brz and graphical user interfaces (GUIs) are available as plug-ins.
Using brz¶
The syntax is:
brz [global-options] command [options and arguments]
Global options affect how Breezy operates and can appear either
before or after command
. Command specific options must appear
after the command but may be given either before, during or after any
command-specific arguments.
Common options¶
Some options are legal for all commands as shown below.
Short form
Long form
Description
-h
–help
get help
-v
–verbose
be more verbose
-q
–quiet
be more quiet
Quiet mode implies that only errors and warnings are displayed. This can be useful in scripts.
Note: Most commands typically only support one level of verbosity though that may change in the future. To ask for a higher level of verbosity, simply specify the -v option multiple times.
Getting help¶
Breezy comes with a built-in on-line help system, accessed through:
brz help
You can ask for help on a command, or on non-command topics. To see a list of available help of each kind, use either:
brz help commands
brz help topics
For help on a particular command, use either of these forms:
brz help status
brz status --help
If you wish to search the help or read it as a larger document, the information is also available in the Breezy User Reference.
Configuring Breezy¶
Telling Breezy about yourself¶
One function of a version control system is to keep track of who changed
what. In a decentralized system, that requires an identifier for each
author that is globally unique. Most people already have one of these: an
email address. Breezy is smart enough to automatically generate an email
address by looking up your username and hostname. If you don’t like the
guess that Breezy makes, then use the whoami
command to set the
identifier you want:
% brz whoami "Your Name <email@example.com>"
If whoami
is used without an argument, the current value is displayed.
Using a network proxy¶
If your network requires that you use an HTTP proxy for outbound
connections, you must set the http_proxy
variable. If the proxy is
also required for https connections, you need to set https_proxy
too.
If you need these and don’t have them set, you may find that connections
to Launchpad or other external servers fail or time out.
On Unix you typically want to set these in /etc/environment
or
~/.bash_profile
and on Windows in the user profile.
http_proxy=http://proxy.example.com:3128/
https_proxy=http://proxy.example.com:3128/
The no_proxy
variable can be set to a comma-separated list of hosts
which shouldn’t be reached by the proxy. (See
<http://docs.python.org/library/urllib.html> for more details.)
Various ways to configure¶
As shown in the example above, there are various ways to configure Breezy, they all share some common properties though. An option has:
a name which is generally a valid python identifier,
a value which is a string. In some cases, Breezy will be able to recognize special values like ‘True’, ‘False’ to infer a boolean type, but basically, as a user, you will always specify a value as a string.
Options are grouped in various contexts so the option name uniquely identifies it in this context. When needed, options can be made persistent by recording them in a configuration file.
Configuration files¶
Configuration files are located in $HOME/.config/breezy
on Unix and
C:\Documents and Settings\<username>\Application Data\Breezy\2.0
on
Windows. There are three primary configuration files in this location:
breezy.conf
describes default configuration options,locations.conf
describes configuration information for specific branch locations,authentication.conf
describes credential information for remote servers.
Each branch can also contain a configuration file that sets values specific
to that branch. This file is found at .brz/branch/branch.conf
within the
branch. This file is visible to all users of a branch. If you wish to
override one of the values for a branch with a setting that is specific to you,
then you can do so in locations.conf
.
Here is sample content of breezy.conf
after setting an email address using
the whoami
command:
[DEFAULT]
email = Your Name <email@example.com>
For further details on the syntax and configuration settings supported, see Configuration Settings in the Breezy User Reference.
Looking at the active configuration¶
To look at all the currently defined options, you can use the following command:
brz config
brz
implements some rules to decide where to get the value of a
configuration option.
The current policy is to examine the existing configurations files in a given order for matching definitions.
locations.conf
is searched first for a section whose name matches the location considered (working tree, branch or remote branch),the current
branch.conf
is searched next,
breezy.conf
is searched next,finally, some options can have default values generally defined in the code itself and not displayed by
brz config
(see Configuration Settings).
This is better understood by using `brz config
with no arguments, which
will display some output of the form:
locations:
post_commit_to = commits@example.com
news_merge_files = NEWS
branch:
parent_location = bzr+ssh://bazaar.launchpad.net/+branch/brz/
nickname = config-modify
push_location = bzr+ssh://bazaar.launchpad.net/~vila/brz/config-modify/
breezy:
debug_flags = hpss,
Each configuration file is associated with a given scope whose name is displayed before each set of defined options.
If you need to look at a specific option, you can use:
brz config <option>
This will display only the option value and is intended to be used in scripts.
Modifying the active configuration¶
To set an option to a given value use:
brz config opt=value
An option value can reference another option by enclosing it in curly braces:
brz config opt={other_opt}/subdir
If other_opt
is set to 'root
, brz config opt
will display:
root/subdir
Note that when --all
is used, the references are left as-is to better
reflect the content of the config files and make it easier to organize them:
brz config --all .*opt
breezy:
[DEFAULT]
opt = {other_opt}/subdir
other_opt = root
To remove an option use:
brz config --remove opt
Rule-based preferences¶
Some commands and plugins provide custom processing on files matching
certain patterns. Per-user rule-based preferences are defined in
BZR_HOME/rules
.
For further information on how rules are searched and the detailed syntax of the relevant files, see Rules in the Breezy User Reference.
Escaping command lines¶
When you give a program name or command line in configuration, you can quote to include special characters or whitespace. The same rules are used across all platforms.
The rules are: strings surrounded by double-quotes are interpreted as single “words” even if they contain whitespace, and backslash may be used to quote quotation marks. For example:
BZR_EDITOR="C:\Program Files\My Editor\myeditor.exe"
Using aliases¶
What are aliases?¶
Aliases are an easy way to create shortcuts for commonly-typed commands, or to set defaults for commands.
Defining aliases¶
Command aliases can be defined in the [ALIASES]
section of your
breezy.conf
file. Aliases start with the alias name, then an
equal sign, then a command fragment. Here’s an example ALIASES section:
[ALIASES]
recentlog=log -r-3..-1
ll=log --line -r-10..-1
commit=commit --strict
diff=diff --diff-options -p
Here are the explanations of the examples above:
The first alias makes a new
recentlog
command that shows the logs for the last three revisionsThe
ll
alias shows the last 10 log entries in line format.the
commit
alias sets the default for commit to refuse to commit if new files in the tree are not recognized.the
diff
alias adds the coveted -p option to diff
Using the aliases¶
The aliases defined above would be used like so:
% brz recentlog
% brz ll
% brz commit
% brz diff
Rules for aliases¶
You can override a portion of the options given in an alias by specifying the new part on the command-line. For example, if you run
lastlog -r-5..
, you will only get five line-based log entries instead of 10. Note that all boolean options have an implicit inverse, so you can override the commit alias withcommit --no-strict
.Aliases can override the standard behaviour of existing commands by giving an alias name that is the same as the original command. For example, default commit is changed with
commit=commit --strict
.Aliases cannot refer to other aliases. In other words making a
lastlog
alias and referring to it with all
alias will not work. This includes aliases that override standard commands.Giving the
--no-aliases
option to the brz command will tell it to ignore aliases for that run. For example, runningbrz --no-aliases commit
will perform a standard commit instead, not do acommit --strict
.
Using plugins¶
What is a plugin?¶
A plugin is an external component for Breezy that is typically made by third parties. A plugin is capable of augmenting Breezy by adding new functionality. A plugin can also change current Breezy behavior by replacing current functionality. Sample applications of plugins are:
overriding commands
adding new commands
providing additional network transports
customizing log output.
The sky is the limit for the customization that can be done through plugins. In fact, plugins often work as a way for developers to test new features for Breezy prior to inclusion in the official codebase. Plugins are helpful at feature retirement time as well, e.g. deprecated file formats may one day be removed from the Breezy core and be made available as a plugin instead.
Plugins are good for users, good for external developers and good for Breezy itself.
Where to find plugins¶
We keep our list of plugins on the http://wiki.bazaar.canonical.com/BzrPlugins page.
How to install a plugin¶
Installing a plugin is very easy! If not already created, create a
plugins
directory under your Breezy configuration directory,
~/.config/breezy/
on Unix and
C:\Documents and Settings\<username>\Application Data\Breezy\2.0\
on Windows. Within this directory (referred to as $BZR_HOME below),
each plugin is placed in its own subdirectory.
Plugins work particularly well with Breezy branches. For example, to install the brztools plugins for your main user account on GNU/Linux, one can perform the following:
brz branch http://panoramicfeedback.com/opensource/brz/brztools
~/.config/breezy/plugins/brztools
When installing plugins, the directories that you install them in must
be valid python identifiers. This means that they can only contain
certain characters, notably they cannot contain hyphens (-
). Rather
than installing brz-gtk
to $BZR_HOME/plugins/brz-gtk
, install it
to $BZR_HOME/plugins/gtk
.
Alternative plugin locations¶
If you have the necessary permissions, plugins can also be installed on a
system-wide basis. One can additionally override the personal plugins
location by setting the environment variable BZR_PLUGIN_PATH
(see User
Reference
for a detailed explanation).
Listing the installed plugins¶
To do this, use the plugins command like this:
brz plugins
The name, location and version of each plugin installed will be displayed.
New commands added by plugins can be seen by running brz help commands
.
The commands provided by a plugin are shown followed by the name of the
plugin in brackets.
Popular plugins¶
Here is a sample of some of the more popular plugins.
Category
Name
Description
GUI
QBzr
Qt-based GUI tools
GUI
brz-gtk
GTK-based GUI tools
GUI
brz-eclipse
Eclipse integration
General
brztools
misc. enhancements including shelf
General
difftools
external diff tool helper
General
extmerge
external merge tool helper
Integration
brz-svn
use Subversion as a repository
Migration
cvsps
migrate CVS patch-sets
If you wish to write your own plugins, it is not difficult to do. See Writing a plugin in the appendices to get started.
Breezy Zen¶
Grokking Breezy¶
While Breezy is similar to other VCS tools in many ways, there are some important differences that are not necessarily obvious at first glance. This section attempts to explain some of the things users need to know in order to “grok” Breezy, i.e. to deeply understand it.
Note: It isn’t necessary to fully understand this section to use Breezy. You may wish to skim this section now and come back to it at a later time.
Understanding revision numbers¶
All revisions in the mainline of a branch have a simple increasing integer. (First commit gets 1, 10th commit gets 10, etc.) This makes them fairly natural to use when you want to say “grab the 10th revision from my branch”, or “fixed in revision 3050”.
For revisions which have been merged into a branch, a dotted notation is used (e.g., 3112.1.5). Dotted revision numbers have three numbers [2]. The first number indicates what mainline revision change is derived from. The second number is the branch counter. There can be many branches derived from the same revision, so they all get a unique number. The third number is the number of revisions since the branch started. For example, 3112.1.5 is the first branch from revision 3112, the fifth revision on that branch.
Hierarchical history is good¶
Imagine a project with multiple developers contributing changes where many changes consist of a series of commits. To give a concrete example, consider the case where:
The tip of the project’s trunk is revision 100.
Mary makes 3 changes to deliver feature X.
Bill makes 4 changes to deliver feature Y.
If the developers are working in parallel and using a traditional centralized VCS approach, the project history will most likely be linear with Mary’s changes and Bill’s changes interleaved. It might look like this:
107: Add documentation for Y
106: Fix bug found in testing Y
105: Fix bug found in testing X
104: Add code for Y
103: Add documentation for X
102: Add code and tests for X
101: Add tests for Y
100: ...
Many teams use this approach because their tools make branching and merging difficult. As a consequence, developers update from and commit to the trunk frequently, minimizing integration pain by spreading it over every commit. If you wish, you can use Breezy exactly like this. Breezy does offer other ways though that you ought to consider.
An alternative approach encouraged by distributed VCS tools is to create feature branches and to integrate those when they are ready. In this case, Mary’s feature branch would look like this:
103: Fix bug found in testing X
102: Add documentation for X
101: Add code and tests for X
100: ...
And Bill’s would look like this:
104: Add documentation for Y
103: Fix bug found in testing Y
102: Add code for Y
101: Add tests for Y
100: ...
If the features were independent and you wanted to keep linear history, the changes could be pushed back into the trunk in batches. (Technically, there are several ways of doing that but that’s beyond the scope of this discussion.) The resulting history might look like this:
107: Fix bug found in testing X
106: Add documentation for X
105: Add code and tests for X
104: Add documentation for Y
103: Fix bug found in testing Y
102: Add code for Y
101: Add tests for Y
100: ...
While this takes a bit more effort to achieve, it has some advantages over having revisions randomly intermixed. Better still though, branches can be merged together forming a non-linear history. The result might look like this:
102: Merge feature X
100.2.3: Fix bug found in testing X
100.2.2: Add documentation for X
100.2.1: Add code and tests for X
101: Merge feature Y
100.1.4: Add documentation for Y
100.1.3: Fix bug found in testing Y
100.1.2: Add code for Y
100.1.1: Add tests for Y
100: ...
Or more likely this:
102: Merge feature X
100.2.3: Fix bug
100.2.2: Add documentation
100.2.1: Add code and tests
101: Merge feature Y
100.1.4: Add documentation
100.1.3: Fix bug found in testing
100.1.2: Add code
100.1.1: Add tests
100: ...
This is considered good for many reasons:
It makes it easier to understand the history of a project. Related changes are clustered together and clearly partitioned.
You can easily collapse history to see just the commits on the mainline of a branch. When viewing the trunk history like this, you only see high level commits (instead of a large number of commits uninteresting at this level).
If required, it makes backing out a feature much easier.
Continuous integration tools can be used to ensure that all tests still pass before committing a merge to the mainline. (In many cases, it isn’t appropriate to trigger CI tools after every single commit as some tests will fail during development. In fact, adding the tests first - TDD style - will guarantee it!)
In summary, the important points are:
Organize your work using branches.
Integrate changes using merge.
Ordered revision numbers and hierarchy make history easier to follow.
Each branch has its own view of history¶
As explained above, Breezy makes the distinction between:
mainline revisions, i.e. ones you committed in your branch, and
merged revisions, i.e. ones added as ancestors by committing a merge.
Each branch effectively has its own view of history, i.e. different branches can give the same revision a different “local” revision number. Mainline revisions always get allocated single number revision numbers while merged revisions always get allocated dotted revision numbers.
To extend the example above, here’s what the revision history of Mary’s branch would look like had she decided to merge the project trunk into her branch after completing her changes:
104: Merge mainline
100.2.1: Merge feature Y
100.1.4: Add documentation
100.1.3: Fix bug found in testing
100.1.2: Add code
100.1.1: Add tests
103: Fix bug found in testing X
102: Add documentation for X
101: Add code and tests for X
100: ...
Once again, it’s easy for Mary to look at just her top level of history to see the steps she has taken to develop this change. In this context, merging the trunk (and resolving any conflicts caused by doing that) is just one step as far as the history of this branch is concerned.
It’s important to remember that Breezy is not changing history here, nor is it changing the global revision identifiers. You can always use the latter if you really want to. In fact, you can use the branch specific revision numbers when communicating as long as you provide the branch URL as context. (In many Breezy projects, developers imply the central trunk branch if they exchange a revision number without a branch URL.)
Merges do not change revision numbers in a branch, though they do allocate local revision numbers to newly merged revisions. The only time Breezy will change revision numbers in a branch is when you explicitly ask it to mirror another branch.
Note: Revisions are numbered in a stable way: if two branches have the same revision in their mainline, all revisions in the ancestry of that revision will have the same revision numbers. For example, if Alice and Bob’s branches agree on revision 10, they will agree on all revisions before that.
Summary¶
In general, if you follow the advice given earlier - organise your work in branches and use merge to collaborate - you’ll find Breezy generally does what you expect.
In coming chapters, we examine various ways of using Breezy beginning with the simplest: using Breezy for personal projects.
Personal version control¶
Going solo¶
A personal productivity tool¶
Some tools are designed to make individuals productive (e.g. editors) while other tools (e.g. back-end services) are focused on making teams or whole companies more productive. Version control tools have traditionally been in the latter camp.
One of the cool things about Breezy is that it is so easy to setup that version control can now be treated as a personal productivity tool. If you wish to record changes to files for the purposes of checkpointing good known states or tracking history, it is now easy to do so. This chapter explains how.
The solo workflow¶
If you are creating your own masterpiece, whether that be a software project or a set of related documents, the typical workflow looks like this:

Even if you will always be working as part of a team, the tasks covered in this chapter will be the basis of what you’ll be doing so it’s a good place to start.
Starting a project¶
Putting an existing project under version control¶
If you already have a tree of source code (or directory of documents) you wish to put under version control, here are the commands to use:
cd my-stuff
brz init
brz add
brz commit -m "Initial import"
brz init
creates a .brz
directory in the top level directory
(my-stuff
in the example above). Note that:
Breezy has everything it needs in that directory - you do not need to setup a database, web server or special service to use it
Breezy is polite enough to only create one
.brz
in the directory given, not one in every subdirectory thereof.
brz add
then finds all the files and directories it thinks
ought to be version controlled and registers them internally.
brz commit
then records a snapshot of the content of these
and records that information, together with a commit message.
More information on init
, add
and commit
will be provided
later. For now, the important thing to remember is the recipe above.
Starting a new project¶
If you are starting a project from scratch, you can also use the recipe above, after creating an empty directory first of course. For efficiency reasons that will be explored more in later chapters though, it is a good idea to create a repository for the project at the top level and to nest a main branch within it like this:
brz init-repo my.repo
cd my.repo
brz init my.main
cd my.main
hack, hack, hack
brz add
brz commit -m "Initial import"
Some users prefer a name like trunk or dev to main. Choose whichever name makes the most sense to you.
Note that the init-repo
and init
commands both take a path as an
argument and will create that path if it doesn’t already exist.
Controlling file registration¶
What does Breezy track?¶
As explained earlier, brz add
finds and registers all the things in
and under the current directory that Breezy thinks ought to be
version controlled. These things may be:
files
directories
symbolic links.
Breezy has default rules for deciding which files are interesting and which ones are not. You can tune those rules as explained in Ignoring files below.
Unlike many other VCS tools, Breezy tracks directories as first class items. As a consequence, empty directories are correctly supported - you don’t need to create a dummy file inside a directory just to ensure it gets tracked and included in project exports.
For symbolic links, the value of the symbolic link is tracked, not the content of the thing the symbolic link is pointing to.
Note: Support for tracking projects-within-projects (“nested trees”) is currently under development. Please contact the Breezy developers if you are interested in helping develop or test this functionality.
Selective registration¶
In some cases, you may want or need to explicitly nominate the things
to register rather than leave it up to Breezy to find things. To do this,
simply provide paths as arguments to the add
command like this:
brz add fileX dirY/
Adding a directory implicitly adds all interesting things underneath it.
Ignoring files¶
Many source trees contain some files that do not need to be versioned,
such as editor backups, object or bytecode files, and built programs. You
can simply not add them, but then they’ll always crop up as unknown files.
You can also tell Breezy to ignore these files by adding them to a file
called .bzrignore
at the top of the tree.
This file contains a list of file wildcards (or “globs”), one per line. Typical contents are like this:
*.o
*~
*.tmp
*.py[co]
If a glob contains a slash, it is matched against the whole path from the
top of the tree; otherwise it is matched against only the filename. So
the previous example ignores files with extension .o
in all
subdirectories, but this example ignores only config.h
at the top level
and HTML files in doc/
:
./config.h
doc/*.html
To get a list of which files are ignored and what pattern they matched,
use brz ignored
:
% brz ignored
config.h ./config.h
configure.in~ *~
Note that ignore patterns are only matched against non-versioned files, and control whether they are treated as “unknown” or “ignored”. If a file is explicitly added, it remains versioned regardless of whether it matches an ignore pattern.
The .bzrignore
file should normally be versioned, so that new copies
of the branch see the same patterns:
% brz add .bzrignore
% brz commit -m "Add ignore patterns"
The command brz ignore PATTERN
can be used to easily add PATTERN to
the .bzrignore file
(creating it if necessary and registering it to
be tracked by Breezy). Removing and modifying patterns are done by
directly editing the .bzrignore
file.
Global ignores¶
There are some ignored files which are not project specific, but more user
specific. Things like editor temporary files, or personal temporary files.
Rather than add these ignores to every project, brz supports a global
ignore file in ~/.config/breezy/ignore
[3]. It has the same syntax as the
per-project ignore file.
Reviewing changes¶
Looking before you leap¶
Once you have completed some work, it’s a good idea to review your changes prior to permanently recording it. This way, you can make sure you’ll be committing what you intend to.
Two brz commands are particularly useful here: status and diff.
brz status¶
The status command tells you what changes have been made to the working directory since the last revision:
% brz status
modified:
foo
brz status
hides “boring” files that are either unchanged or ignored.
The status command can optionally be given the name of some files or
directories to check.
brz diff¶
The diff command shows the full text of changes to all files as a standard unified diff. This can be piped through many programs such as ‘’patch’’, ‘’diffstat’’, ‘’filterdiff’’ and ‘’colordiff’’:
% brz diff
=== added file 'hello.txt'
--- hello.txt 1970-01-01 00:00:00 +0000
+++ hello.txt 2005-10-18 14:23:29 +0000
@@ -0,0 +1,1 @@
+hello world
With the -r
option, the tree is compared to an earlier revision, or
the differences between two versions are shown:
% brz diff -r 1000.. # everything since r1000
% brz diff -r 1000..1100 # changes from 1000 to 1100
To see the changes introduced by a single revision, you can use the -c
option to diff.
% brz diff -c 1000 # changes from r1000
# identical to -r999..1000
The --diff-options
option causes brz to run the external diff program,
passing options. For example:
% brz diff --diff-options --side-by-side foo
Some projects prefer patches to show a prefix at the start of the path
for old and new files. The --prefix
option can be used to provide
such a prefix.
As a shortcut, brz diff -p1
produces a form that works with the
command patch -p1
.
Recording changes¶
brz commit¶
When the working tree state is satisfactory, it can be committed to the branch, creating a new revision holding a snapshot of that state.
The commit command takes a message describing the changes in the
revision. It also records your userid, the current time and timezone, and
the inventory and contents of the tree. The commit message is specified
by the -m
or --message
option. You can enter a multi-line commit
message; in most shells you can enter this just by leaving the quotes open
at the end of the line.
% brz commit -m "added my first file"
You can also use the -F
option to take the message from a file. Some
people like to make notes for a commit message while they work, then
review the diff to make sure they did what they said they did. (This file
can also be useful when you pick up your work after a break.)
Message from an editor¶
If you use neither the -m
nor the -F
option then brz will open an
editor for you to enter a message. The editor to run is controlled by
your $VISUAL
or $EDITOR
environment variable, which can be overridden
by the editor
setting in ~/.config/breezy/breezy.conf
; $BZR_EDITOR
will override either of the above mentioned editor options. If you quit the
editor without making any changes, the commit will be cancelled.
The file that is opened in the editor contains a horizontal line. The part of the file below this line is included for information only, and will not form part of the commit message. Below the separator is shown the list of files that are changed in the commit. You should write your message above the line, and then save the file and exit.
If you would like to see the diff that will be committed as you edit the
message you can use the --show-diff
option to commit
. This will include
the diff in the editor when it is opened, below the separator and the
information about the files that will be committed. This means that you can
read it as you write the message, but the diff itself wont be seen in the
commit message when you have finished. If you would like parts to be
included in the message you can copy and paste them above the separator.
Selective commit¶
If you give file or directory names on the commit command line then only the changes to those files will be committed. For example:
% brz commit -m "documentation fix" commit.py
By default brz always commits all changes to the tree, even if run from a subdirectory. To commit from only the current directory down, use:
% brz commit .
Giving credit for a change¶
If you didn’t actually write the changes that you are about to commit, for instance
if you are applying a patch from someone else, you can use the --author
commit
option to give them credit for the change:
% brz commit --author "Jane Rey <jrey@example.com>"
The person that you specify there will be recorded as the “author” of the revision, and you will be recorded as the “committer” of the revision.
If more than one person works on the changes for a revision, for instance if you
are pair-programming, then you can record this by specifying --author
multiple
times:
% brz commit --author "Jane Rey <jrey@example.com>" \
--author "John Doe <jdoe@example.com>"
Browsing history¶
brz log¶
The brz log
command shows a list of previous revisions.
As with brz diff
, brz log
supports the -r
argument:
% brz log -r 1000.. # Revision 1000 and everything after it
% brz log -r ..1000 # Everything up to and including r1000
% brz log -r 1000..1100 # changes from 1000 to 1100
% brz log -r 1000 # The changes in only revision 1000
Viewing merged revisions¶
As distributed VCS tools like Breezy make merging much easier than it is in central VCS tools, the history of a branch may often contain lines of development splitting off the mainline and merging back in at a later time. Technically, the relationship between the numerous revision nodes is known as a Directed Acyclic Graph or DAG for short.
In many cases, you typically want to see the mainline first and drill down from there. The default behaviour of log is therefore to show the mainline and indicate which revisions have nested merged revisions. To explore the merged revisions for revision X, use the following command:
brz log -n0 -rX
To see all revisions and all their merged revisions:
brz log -n0
Note that the -n option is used to indicate the number of levels to display
where 0 means all. If that is too noisy, you can easily adjust the number
to only view down so far. For example, if your project is structured with
a top level gatekeeper merging changes from team gatekeepers, brz log
shows what the top level gatekeeper did while brz log -n2
shows what
the team gatekeepers did. In the vast majority of cases though, -n0
is fine.
Tuning the output¶
The log
command has several options that are useful for tuning
the output. These include:
--forward
presents the log in chronological order, i.e. the most recent revisions are displayed last.the
--limit
option controls the maximum number of revisions displayed.
See the online help for the log command or the User Reference for more information on tuning the output.
Viewing the history for a file¶
It is often useful to filter the history so that it only
applies to a given file. To do this, provide the filename
to the log
command like this:
brz log foo.py
Viewing an old version of a file¶
To get the contents of a file at a given version, use the
cat
command like this:
brz cat -r X file
where X
is the revision identifier and file
is
the filename. This will send output to the standard output
stream so you’ll typically want to pipe the output through
a viewing tool (like less
or more
) or redirect it
like this:
brz cat -r -2 foo.py | less
brz cat -r 1 foo.py > /tmp/foo-1st-version.py
Graphical history viewers¶
History browsing is one area where GUI tools really make life easier. Breezy has numerous plug-ins that provide this capability including QBzr and brz-gtk. See Using plugins for details on how to install these if they are not already installed.
To use the graphical viewer from QBzr:
brz qlog
To use the graphical viewer from brz-gtk:
brz viz
viz
is actually a built-in alias for visualize
so use the longer
command name if you prefer.
Releasing a project¶
Packaging a release¶
The export
command is used to package a release, i.e. to
take a copy of the files and directories in a branch and
package them into a fresh directory or archive. For example,
this command will package the last committed version into
a tar.gz
archive file:
brz export ../releases/my-stuff-1.5.tar.gz
The export
command uses the suffix of the archive file
to work out the type of archive to create as shown below.
Supported formats
Autodetected by extension
dir
(none)
tar
.tar
tbz2
.tar.bz2, .tbz2
tgz
.tar.gz, .tgz
zip
.zip
If you wish to package a revision other than the last one, use
the -r
option. If you wish to tune the root directory inside
the archive, use the --root
option. See the online help or
User Reference for further details on the options supported by
export
.
Tagging a release¶
Rather than remembering which version was used to package a release,
it’s useful to define a symbolic name for a version using the tag
command like this:
brz tag version-1-5
That tag can be used later whenever a revision identifier is required, e.g.:
brz diff -r tag:version-1-5
To see the list of tags defined in a branch, use the tags
command.
Undoing mistakes¶
Mistakes happen¶
Breezy has been designed to make it easy to recover from mistakes as explained below.
Dropping the revision history for a project¶
If you accidentally put the wrong tree under version control, simply
delete the .brz
directory.
Deregistering a file or directory¶
If you accidentally register a file using add
that you
don’t want version controlled, you can use the remove
command to tell Breezy to forget about it.
remove
has been designed to Do the Safe Thing in
that it will not delete a modified file. For example:
brz add foo.html
(oops - didn't mean that)
brz remove foo.html
This will complain about the file being modified or unknown.
If you want to keep the file, use the --keep
option.
Alternatively, if you want to delete the file, use the --force
option.
For example:
brz add foo.html
(oops - didn't mean that)
brz remove --keep foo.html
(foo.html left on disk, but deregistered)
On the other hand, the unchanged TODO
file is deregistered and
removed from disk without complaint in this example:
brz add TODO
brz commit -m "added TODO"
(hack, hack, hack - but don't change TODO)
brz remove TODO
(TODO file deleted)
Note: If you delete a file using your file manager, IDE or via an operating
system command, the commit
command will implicitly treat it as removed.
Undoing changes since the last commit¶
One of the reasons for using a version control tool is that it
lets you easily checkpoint good tree states while working. If you
decide that the changes you have made since the last commit
ought
to be thrown away, the command to use is revert
like this:
brz revert
As a precaution, it is good practice to use brz status
and
brz diff
first to check that everything being thrown away
really ought to be.
Undoing changes to a file since the last commit¶
If you want to undo changes to a particular file since the last commit but
keep all the other changes in the tree, pass the filename as an argument
to revert
like this:
brz revert foo.py
Undoing the last commit¶
If you make a commit and really didn’t mean to, use the uncommit
command
to undo it like this:
brz uncommit
Unlike revert
, uncommit
leaves the content of your working tree
exactly as it is. That’s really handy if you make a commit and accidently
provide the wrong error message. For example:
brz commit -m "Fix bug #11"
(damn - wrong bug number)
brz uncommit
brz commit -m "Fix bug #1"
Another common reason for undoing a commit is because you forgot to add
one or more files. Some users like to alias commit
to commit --strict
so that commits fail if unknown files are found in the tree.
Tags for uncommitted revisions are removed from the branch unless
--keep-tags
was specified.
Note: While the merge
command is not introduced until the next
chapter, it is worth noting now that uncommit
restores any pending
merges. (Running brz status
after uncommit
will show these.)
merge
can also be used to effectively undo just a selected commit
earlier in history. For more information on merge
, see
Merging changes in the next chapter and the
Breezy User Reference.
Undoing multiple commits¶
You can use the -r option to undo several commits like this:
brz uncommit -r -3
If your reason for doing this is that you really want to
back out several changes, then be sure to remember that uncommit
does not change your working tree: you’ll probably need to run the
revert
command as well to complete the task. In many cases though,
it’s arguably better to leave your history alone and add a new
revision reflecting the content of the last good state.
Reverting to the state of an earlier version¶
If you make an unwanted change but it doesn’t make sense to uncommit
it (because that code has been released to users say), you can use
revert
to take your working tree back to the desired state.
For example:
% brz commit "Fix bug #5"
Committed revision 20.
(release the code)
(hmm - bad fix)
brz revert -r 19
brz commit -m "Backout fix for bug #5"
This will change your entire tree back to the state as of revision 19,
which is probably only what you want if you haven’t made any new commits
since then. If you have, the revert
would wipe them out as well. In that
case, you probably want to use Reverse cherrypicking instead to
back out the bad fix.
Note: As an alternative to using an absolute revision number (like 19), you can specify one relative to the tip (-1) using a negative number like this:
brz revert -r -2
Correcting a tag¶
If you have defined a tag prematurely, use the --force
option of
the tag
command to redefine it. For example:
brz tag 2.0-beta-1
(oops, we're not yet ready for that)
(make more commits to include more fixes)
brz tag 2.0-beta-1 --force
Clearing a tag¶
If you have defined a tag and no longer want it defined, use the
--delete
option of the tag
command to remove it. For example:
brz tag 2.0-beta-4
(oops, we're not releasing a 4th beta)
brz tag 2.0-beta-4 --delete