Bazaar User Guide

Contents

1   Introduction

1.1   Introducing Bazaar

1.1.1   What is Bazaar?

Bazaar 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, Bazaar can effortlessly merge your work with other people's.

Tools like Bazaar are called version control systems (VCS) and have long been popular with software developers. Bazaar'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 Bazaar 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.

1.1.2   A brief history of version control systems

Version control tools have been evolving for several decades now. In simple terms, there have been 5 generations of tools:

  1. file versioning tools, e.g. SCCS, RCS
  2. tree versioning tools - central style, e.g. CVS
  3. tree versioning tools - central style, done right, e.g. Subversion
  4. tree versioning tools - distributed style, e.g. Arch
  5. tree versioning tools - distributed style, done right, e.g. Bazaar.

The design and implementation of Bazaar builds on the lessons learned from all the previous generations of tools. In particular, Bazaar 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.

1.1.3   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 Bazaar'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 source 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://bazaar-vcs.org/BzrWhy.

1.1.4   Key features of Bazaar

While Bazaar 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. These include:

  • it Just Works - a high focus on usability and performance
  • adaptive - cleanly supports many different ways of working together
  • rich metadata that tracks merge history across distributed locations, understands directories as first-class objects and correctly tracks renames of both files and directories
  • integrated merging that uses this metadata intelligently to ensure that merging is safe without being painful, letting you collaborate without fear
  • truly portable across many operating systems including Windows
  • safe with your data - integrity is checked using cryptographic techniques and all changes can be digitally signed if required
  • low administration, e.g. access to FTP or SFTP is enough to share with others - no special server required
  • efficiently stores data across branches in a flexible and safe way
  • an open architecture and API that makes it easy to integrate with other tools
  • a large number of plugins including bzr-svn and GUI front-ends
  • excellent integration with a range of companion tools and services including PQM, Bundle Buggy and Launchpad
  • completely open source
  • commercial training and support available from Canonical, the company that sponsors Ubuntu.

While all of these are important, perhaps the greatest asset Bazaar has is an active and growing open source community behind it. Bazaar is completely free software written in Python so it is easy to contribute improvements. Our collective goal is to build and support a distributed VCS tool that developers love to use, a tool that helps them get their job done without getting in their way. If you wish to get involved, please see http://bazaar-vcs.org/Community.

1.1.5   Learning more

This manual provides an easy to read introduction to Bazaar 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 Bazaar to collaborate.

Chapters 2-6 provide a closer look at how to use Bazaar to complete various tasks. It is recommended that most users read these in first-to-last order shortly after starting to use Bazaar. Chapters 7 and beyond provide additional information including some recommended best practices. This material can be read when required and in any order.

If you are already familar with other version control tools, you may wish to get started quickly by reading the following documents:

The online help and Bazaar User Reference are also particularly useful as they provide all the gory 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 Bazaar's documentation can be improved, please contact us on the mailing list, bazaar@lists.canonical.com.

1.2   Core concepts

1.2.1   A simple user model

To use Bazaar 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.

1.2.2   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 identified uniquely by a revision-id. An example revision-id is:

pqm@pqm.ubuntu.com-20071129184101-u9506rihe4zbzyyz

While these identifiers are necessary for internal use and external tool integration, branch-specific revision numbers are the preferred interface for humans. Typical revision numbers are 1, 42 and 2977.1.59. See Specifying revisions in the appendices for a closer look at the numerous ways that revisions and ranges of revisions can be specified in Bazaar.

1.2.3   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.

1.2.4   Branch

In the simplest case, a branch is an ordered series of revisions. The last revision is known as the head.

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 sound scary, don't worry. The important things to remembers 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.

If you understand that, you understand branches.

1.2.5   Repository

A repository is simply a store of revisions. In the simpliest 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.

1.2.6   Putting the concepts together

Once the concepts above are understood, the various ways of using Bazaar are easier to understand. The simpliest way of using Bazaar 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 collocated but the repository is in a higher level directory
  • lightweight checkouts - branch is stored is a different location to the working tree.

The best way to use Bazaar depends on what you want to do so let's look at some common workflows next.

1.3   Workflows

1.3.1   Bazaar is just a tool

One of the best things about Bazaar is that it 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 Bazaar.

1.3.2   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.

images/workflows_single.png

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 Bazaar appropriate for this workflow are low administration (no server setup) and ease of use.

1.3.3   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.

images/workflows_peer.png

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, Bazaar's advantages over CVS and Subversion include:

  • no server to setup
  • intelligent merging means merging multiple times isn't painful.

1.3.4   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 bzr update to get their checkout up-to-date, then bzr commit to publish their changes to the central location.

images/workflows_centralized.png

Subversion and CVS are good choices for implementing this workflow because they make it easy. Unlike the vast majority of distributed VCS tools, Bazaar makes it easy as well by directly supporting it. In addition, Bazaar provides some important advantages over CVS and Subversion:

  • better branching and merging
  • better renaming support.

1.3.5   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.

images/workflows_localcommit.png

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 Bazaar does.

1.3.6   Decentralized with shared mainline

In this workflow, each developer has their own branch or branches, plus commit rights to the main branch. They do their work in their personal branch, then merge it into the mainline when it is ready.

images/workflows_shared.png

Advantage over Centralized with local commits:

  • Easier organization of work - separate changes can be developed in their own branches
  • Developers can merge one another's personal branches when working on something together.

Subversion and CVS do not support this model. Other distributed VCS tools support it. Many features of Bazaar are good for this workflow including ease of use, shared repositories, integrated merging and rich metadata (including directory rename tracking).

1.3.7   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.

images/workflows_gatekeeper.png

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 Bazaar's called Bundle Buggy can be very useful for tracking what changes are up for review, their status and reviewer comments.

1.3.8   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 (e.g. PQM) has commit rights to the main branch. When a developer wants their work merged, they request another person to review it. Once passed review, either the original author or the reviewer asks the gatekeeper to merge it, depending on team policies. The gatekeeper 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.)

images/workflows_pqm.png

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 Bazaar's called Patch Queue Manager (PQM) can provide the automated gatekeeper capability.

1.3.9   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.

2   Getting started

2.1   Installing Bazaar

2.1.1   Linux

Bazaar packages are available for most popular Linux distributions including Ubuntu/Debian, Red Hat and Gentoo. See http://bazaar-vcs.org/Download for the latest instructions.

2.1.2   Windows

For Windows users, an installer is available that includes the core Bazaar package together with necessary pre-requisites and some useful plug-ins. See http://bazaar-vcs.org/Download for the latest instructions.

Note: If you are running Cygwin on Windows, a Bazaar for Cygwin package is available and ought to be used instead of the Windows version.

2.1.3   Other operating systems

Beyond Linux and Windows, Bazaar packages are available for a large range of other operating systems include Mac OS X, FreeBSD and Solaris. See http://bazaar-vcs.org/Download for the latest instructions.

2.1.4   Installing from scratch

If you wish to install Bazaar from scratch rather than using a pre-built package, the steps are:

  1. If it is not installed already, install Python 2.4 or later.
  2. Download the bazaar-xxx.tar.gz file (where xxx is the version number) from http://bazaar-vcs.org/Download or from Launchpad (https://launchpad.net/~bzr/).
  3. Unpack the archive using tar, WinZip or equivalent.
  4. Put the created directory on your PATH.

To test the installation, try running the bzr command like this:

bzr version

This will display the version of Bazaar you have installed. If this doesn't work, please contact us via email or IRC so we can help you get things working.

2.1.5   Running the development version

If you wish to always be using the very latest development version of Bazaar, it is easy to do so. 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 help us make Bazaar even better, either through increased testing or sending us changes for bugs and improvements.

Here are the steps to follow:

  1. Install Bazaar using one of the methods given above.

  2. Get a copy of the development version like this:

    bzr branch http://bazaar-vcs.org/bzr/bzr.dev
    
  3. Put the created directory (bzr.dev) 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 pyrex and a C compiler. Please contact us on email or IRC if you need assistance with this.

2.1.6   Running multiple versions

One of the neat things about Bazaar is that it's really easy to have multiple versions installed and to switch between them. To do this, simply provide the full pathname to the bzr 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 bzr 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.

2.2   Entering commands

2.2.1   User interfaces

There are numerous user interfaces available for Bazaar. The core package provides a command line tool called bzr and graphical user interfaces (GUIs) are available as plug-ins.

2.2.2   Using bzr

The syntax is:

bzr [global-options] command [options and arguments]

Global options affect how Bazaar 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.

2.2.3   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.

2.3   Getting help

Bazaar comes with a built-in on-line help system. To see the list of topics, the command is:

bzr help

To see the list of commands, the command is:

bzr help commands

To get help on topic xxx or command xxx, the command is:

bzr help xxx

If you wish to search the help or read it as a larger document, the information is also available in the Bazaar User Reference.

2.4   Configuring Bazaar

2.4.1   Telling Bazaar 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. Bazaar is smart enough to automatically generate an email address by looking up your username and hostname. If you don't like the guess that Bazaar makes, then use the whoami command to set the identifier you want:

% bzr whoami "Your Name <email@example.com>"

If whoami is used without an argument, the current value is displayed.

2.4.2   Configuration files

Configuration files are located in $HOME/.bazaar on Linux/Unix and C:\Documents and Settings\<username>\Application Data\Bazaar\2.0 on Windows. There are three primary configuration files in this location:

  • bazaar.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 .bzr/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 bazaar.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 reference in the appendices.

2.5   Using aliases

2.5.1   What are aliases?

Aliases are an easy way to create shortcuts for commonly-typed commands, or to set defaults for commands.

2.5.2   Defining aliases

Command aliases can be defined in the [ALIASES] section of your bazaar.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 revisions
  • The 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

2.5.3   Using the aliases

The aliases defined above would be used like so:

% bzr recentlog
% bzr ll
% bzr commit
% bzr diff

2.5.4   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 with commit --no-strict.
  • Aliases can override the standard behaviour of existing commands by giving an alias name that is the same as the orignal 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 a ll alias will not work. This includes aliases that override standard commands.
  • Giving the --no-aliases option to the bzr command will tell it to ignore aliases for that run. For example, running bzr --no-aliases commit will perform a standard commit instead, not do a commit --strict.

2.6   Using plugins

2.6.1   What is a plugin?

A plugin is an external component for Bazaar that is typically made by third parties. A plugin is capable of augmenting Bazaar by adding new functionality. A plugin can also change current Bazaar 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 Bazaar 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 Bazaar core and be made available as a plugin instead.

Plugins are good for users, good for external developers and good for Bazaar itself.

2.6.2   Where to find plugins

We keep our list of plugins on the http://bazaar-vcs.org/BzrPlugins page.

2.6.3   How to install a plugin

Installing a plugin is very easy! If not already created, create a plugins directory under your Bazaar configuration directory, ~/.bazaar/ on Linux and C:\Documents and Settings\<username>\Application Data\Bazaar\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 Bazaar branches. For example, to install the bzrtools plugins for your main user account on Linux, one can perform the following:

bzr branch http://panoramicfeedback.com/opensource/bzr/bzrtools
~/.bazaar/plugins/bzrtools

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 bzr-gtk to $BZR_HOME/plugins/bzr-gtk, install it to $BZR_HOME/plugins/gtk.

2.6.4   Alternative plugin locations

If you have the necessary permissions, plugins can also be installed on a system-wide basis. Two locations are currently checked for plugins:

  1. the system location - bzrlib/plugins
  2. the personal location - $BZR_HOME/plugins.

On a Linux installation, these locations are typically /usr/lib/python2.4/site-packages/bzrlib/plugins/ and $HOME/.bazaar/plugins/. On a Windows installation, the system location might be C:\\Program Files\\Bazaar\\plugins while the personal location might be C:\Documents and Settings\<username>\Application Data\Bazaar\2.0\plugins.

One can additionally override the personal plugins location by setting the environment variable BZR_PLUGIN_PATH to a directory that contains plugins.

2.6.5   Listing the installed plugins

To do this, use the plugins command like this:

bzr plugins

The name, location and version of each plugin installed will be displayed.

New commands added by plugins can be seen by running bzr help commands. The commands provided by a plugin are shown followed by the name of the plugin in brackets.

2.6.6   Popular plugins

Here is a sample of some of the more popular plugins.

Category Name Description
GUI QBzr Qt-based GUI tools
GUI bzr-gtk GTK-based GUI tools
GUI bzr-eclipse Eclipse integration
General bzrtools misc. enhancements including shelf
General difftools external diff tool helper
General extmerge external merge tool helper
Integration bzr-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.

3   Personal version control

3.1   Going solo

3.1.1   A personal productivity tool

Some tools are designed to make individuals productive (e.g. editors) while other tools (e.g. back-end services) are focussed on making teams or whole companies more productive. Version control tools have traditionally been in the latter camp.

One of the cool things about Bazaar 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.

3.1.2   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:

images/workflows_single.png

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.

3.2   Starting a project

3.2.1   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
bzr init
bzr add
bzr commit -m "Initial import"

bzr init creates a .bzr directory in the top level directory (my-stuff in the example above). Note that:

  • Bazaar has everything it needs in that directory - you do not need to setup a database, web server or special service to use it
  • Bazaar is polite enough to only create one .bzr in the directory given, not one in every subdirectory thereof.

bzr add then finds all the files and directories it thinks ought to be version controlled and registers them internally. bzr 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.

3.2.2   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:

bzr init-repo my.repo
cd my.repo
bzr init my.main
cd my.main
hack, hack, hack
bzr add
bzr 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.

3.3   Controlling file registration

3.3.1   What does Bazaar track?

As explained earlier, bzr add finds and registers all the things in and under the current directory that Bazaar thinks ought to be version controlled. These things may be:

  • files
  • directories
  • symbolic links.

Bazaar 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.

Unless many other VCS tools, Bazaar 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 Bazaar developers if you are interested in helping develop or test this functionality.

3.3.2   Selective registration

In some cases, you may want or need to explicitly nominate the things to register rather than leave it up to Bazaar to find things. To do this, simply provide paths as arguments to the add command like this:

bzr add fileX dirY/

Adding a directory implicitly adds all interesting things underneath it.

3.3.3   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 Bazaar 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 bzr ignored:

% bzr ignored
config.h                 ./config.h
configure.in~            *~

It is OK to have either an ignore pattern match a versioned file, or to add an ignored file. Ignore patterns have no effect on versioned files; they only determine whether unversioned files are reported as unknown or ignored.

The .bzrignore file should normally be versioned, so that new copies of the branch see the same patterns:

% bzr add .bzrignore
% bzr commit -m "Add ignore patterns"

3.3.4   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, bzr supports a global ignore file in ~/.bazaar/ignore2. It has the same syntax as the per-project ignore file.

[2]On Windows, the users configuration files can be found in the application data directory. So instead of ~/.bazaar/branch.conf the configuration file can be found as: C:\Documents and Settings\<username>\Application Data\Bazaar\2.0\branch.conf. The same is true for locations.conf, ignore, and the plugins directory.

3.4   Reviewing changes

3.4.1   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 bzr commands are particularly useful here: status and diff.

3.4.2   bzr status

The status command tells you what changes have been made to the working directory since the last revision:

% bzr status
modified:
   foo

bzr 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.

3.4.3   bzr 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'':

% bzr 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:

% bzr diff -r 1000..          # everything since r1000
% bzr diff -r 1000..1100      # changes from 1000 to 1100

The --diff-options option causes bzr to run the external diff program, passing options. For example:

% bzr 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, bzr diff -p1 produces a form that works with the command patch -p1.

3.5   Recording changes

3.5.1   bzr 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.

% bzr 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.)

3.5.2   Message from an editor

If you use neither the -m nor the -F option then bzr 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 ~/.bazaar/bazaar.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.

3.5.3   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:

% bzr commit -m "documentation fix" commit.py

By default bzr always commits all changes to the tree, even if run from a subdirectory. To commit from only the current directory down, use:

% bzr commit .

3.6   Browsing history

3.6.1   bzr log

The bzr log command shows a list of previous revisions.

As with bzr diff, bzr log supports the -r argument:

% bzr log -r 1000..          # Revision 1000 and everything after it
% bzr log -r ..1000          # Everything up to and including r1000
% bzr log -r 1000..1100      # changes from 1000 to 1100
% bzr log -r 1000            # The changes in only revision 1000

3.6.2   Viewing the mainline

As distributed VCS tools like Bazaar make merging much easier than it is in central VCS tools, the history of a branch may often show 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 though, you may only be interested in seeing the mainline for a brach, namely the primary line of development within the DAG. To do this, use the following command:

bzr log --short

If you do this commonly, you may even wish to create an alias for it as explained in Using aliases.

3.6.3   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.

3.6.4   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:

bzr log foo.py

3.6.5   Viewing an old version of a file

To get the contents of a file at a given version, use the cat command like this:

bzr 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:

bzr cat -r -2 foo.py | less
bzr car -r 1 foo.py > /tmp/foo-1st-version.py

3.6.6   Graphical history viewers

History browsing is one area where GUI tools really make life easier. Bazaar has numerous plug-ins that provide this capability including QBzr and bzr-gtk. See Using plugins for details on how to install these if they are not already installed.

To use the graphical viewer from QBzr:

bzr qlog

To use the graphical viewer from bzr-gtk:

bzr viz

viz is actually a built-in alias for visualize so use the longer command name if you prefer.

3.7   Releasing a project

3.7.1   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:

bzr 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 different version to 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.

3.7.2   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:

bzr tag version-1-5

That tag can be be used later whenever a revision identifier is required, e.g.:

bzr diff -r tag:version-1-5

To see the list of tags defined in a branch, use the tags command.

3.8   Undoing mistakes

3.8.1   Mistakes happen

Bazaar has been designed to make it easy to recover from mistakes as explained below.

3.8.2   Dropping the revision history for a project

If you accidently put the wrong tree under version control, simply delete the .bzr directory.

3.8.3   Deregistering a file or directory

If you accidently register a file using add that you don't want version controlled, you can use the remove command to tell Bazaar to forget about it.

remove has been designed to Do the Safe Thing in that it will not delete a modified file. For example:

bzr add foo.html
(oops - didn't mean that)
bzr 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 remove the file, use the --force option. For example:

bzr add foo.html
(oops - didn't mean that)
bzr remove --keep foo.html
(foo.html left on disk)

On the other hand, the TODO file is deregistered and removed from disk without complaint in this example:

bzr add TODO
bzr commit -m "added TODO"
(hack, hack, hack - but don't change TODO)
bzr 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.

3.8.4   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:

bzr revert

As a precaution, it is good practice to use bzr status and bzr diff first to check that everything being thrown away really ought to be.

3.8.5   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:

bzr revert foo.py

3.8.6   Undoing the last commit

If you make a commit and really didn't mean to, use the uncommit command to undo it like this:

bzr 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:

bzr commit -m "Fix bug #11"
(damn - wrong bug number)
bzr uncommit
bzr 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.

Note: While the merge command is not introduced until the next chapter, it is worth noting now that uncommit restores any pending merges. (Running bzr 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 Bazaar User Reference.

3.8.7   Undoing multiple commits

You can use the -r option to undo several commits like this:

bzr 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.

3.8.8   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:

% bzr commit "Fix bug #5"
Committed revision 20.
(release the code)
(hmm - bad fix)
bzr revert -r 20
bzr commit -m "Backout fix for bug #5"

3.8.9   Correcting a tag

If you have defined a tag prematurely, use the --force option of the tag command to redefine it. For example:

bzr tag 2.0-beta-1
(oops, we're not yet ready for that)
bzr tag 2.0-beta-1 --force

3.8.10   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:

bzr tag 2.0-beta-4
(oops, we're not releasing a 4th beta)
bzr tag 2.0-beta-4 --delete

4   Sharing with peers

4.1   Working with another

4.1.1   Peer-to-peer rocks

In many cases, two minds can be better than one. You may be the one who started a project and someone wishes to help, or perhaps it's you who wants to help another. Perhaps you are both members of a larger team that have been assigned a task together as pair programmers. Either way, two people need to agree on a process, a set of guidelines and a toolset in order to work together effectively.

Imagine if you were not allowed to call someone on the phone directly and the only way to talk to them was by registering a conference call first? Companies and communities that only share code via a central VCS repository are living with a similar straight-jacket to that every day. There are times when central control makes a lot of sense and times when peer-to-peer rocks. Either way, Bazaar is designed to help.

4.1.2   The partner workflow

While it's certainly not the only way to do it, the partner workflow below is a good starting point for a pair of people who wish to collaborate using Bazaar.

images/workflows_peer.png

Over and above the tasks covered in the previous chapter, this chapter introduces two essential collaboration activities:

  • getting a copy of a branch
  • merging changes between branches.

Even when it's just you working on a code base, it can be very useful to keep multiple branches around (for different releases say) and to merge changes between them as appropriate. Your "partner" may indeed be yourself.

4.2   Branching a project

4.2.1   Branch URLs

Before someone else can get a copy of your work, you need to agree on a transfer technology. You may decide to make the top level directory of your branch a network share, an approach familiar to Windows users. Linux and OS X users might prefer access to be via SFTP, a secure protocol built-in to most SSH servers. Bazaar is very flexible in this regard with support for lots of protocols some of which are given below.

Prefix Description
file:// Access using the standard filesystem (default)
sftp:// Access using SFTP (most SSH servers provide SFTP).
bzr:// Fast access using the Bazaar smart server.
ftp:// Access using passive FTP.
http:// Read-only access to branches exported by a web server.

As indicated above, branches are identified using URLs with the prefix indicating the transfer technology. If no prefix is given, normal filenames are assumed. For a complete list of supported protocols, see the urlspec online help topic or the URL Identifiers section of the Bazaar User Reference.

4.2.2   A reminder re shared repositories

Before getting a copy of a branch, have a quick think about where to put it on your filesystem. For maximum storage efficiency down the track, it is recommended that branches be created somewhere under a directory setup as a shared repository. For example:

bzr init-repo my-repo
cd my-repo

You are now ready to grab a branch from someone else and hack away.

4.2.3   The branch command

To get a copy of an existing branch, use the branch command. The syntax is:

bzr branch URL [directory]

If a directory is not given, one is created based on the last part of the URL. Here are some examples showing a network share URL and an sftp URL respectively:

bzr branch m:/cool-trunk
bzr branch sftp://bill@mary-laptop/cool-repo/cool-trunk

This example shows explicitly giving the directory name to use for the new branch:

bzr branch /home/mary/cool-repo/cool-trunk cool

4.2.4   Time and space considerations

Depending on the size of the branch being transferred and the speed and latency of the network between your computer and the source branch, this initial transfer might take some time. Subsequent updates should be much faster as only the changes are transferred then.

Keep in mind that Bazaar is transferring the complete history of the branch, not just the latest snapshot. As a consequence, you can be off the network (or disconnected from the network share) after branch completes but you'll still be able to log and diff the history of the branch as much as you want. Furthermore, these operations are quick as the history is stored locally.

Note that Bazaar uses smart compression technology to minimize the amount of disk space required to store version history. In many cases, the complete history of a project will take up less disk space than the working copy of the latest version.

As explained in later chapters, Bazaar also has support for lightweight checkouts of a branch, i.e. working trees with no local storage of history. Of course, disconnected usage is not available then but that's a tradeoff you can decide to make if local disk space is really tight for you. Support for limited lookback into history - history horizons - is currently under development as well.

4.2.5   Viewing branch information

If you wish to see information about a branch including where it came from, use the info command. For example:

bzr info cool

If no branch is given, information on the current branch is displayed.

4.3   Merging changes

4.3.1   Parallel development

Once someone has their own branch of a project, they can make and commit changes in parallel to any development proceeding on the original branch. Pretty soon though, these independent lines of development will need to be combined again. This process is known as merging.

4.3.2   The merge command

To incorporate changes from another branch, use the merge command. Its syntax is:

bzr merge [URL]

If no URL is given, a default is used, initially the branch this branch originated from. For example, if Bill made a branch from Mary's work, he can merge her subsequent changes by simply typing this:

bzr merge

On the other hand, Mary might want to merge into her branch the work Bill has done in his. In this case, she needs to explicitly give the URL the first time, e.g.:

bzr merge sftp://mary@bill-laptop/cool-repo/cool-trunk

This sets the default merge branch if one is not already set. To change the default after it is set, use the --remember option.

4.3.3   How does merging work?

A variety of algorithms exist for merging changes. Bazaar's default algorithm is a variation of 3-way merging which works as follows. Given an ancestor A and two branches B and C, the following table provides the rules used.

A B C Result Comment
x x x x unchanged
x x y y line from C
x y x y line from B
x y z ? conflict

Note that some merges can only be completed with the assistance of a human. Details on how to resolve these are given in Resolving conflicts.

4.3.4   Recording a merge

After any conflicts are resolved, the merge needs to be committed. For example:

bzr commit -m "Merged Mary's changes"

Even if there are no conflicts, an explicit commit is still required. Unlike some other tools, this is considered a feature in Bazaar. A clean merge is not necessarily a good merge so making the commit a separate explicit step allows you to run your test suite first to verify all is good. If problems are found, you should correct them before committing the merge or throw the merge away using revert.

4.3.5   Merge tracking

One of the most important features of Bazaar is distributed, high quality merge tracking. In other words, Bazaar remembers what has been merged already and uses that information to intelligently choose the best ancestor for a merge, minimizing the number and size of conflicts.

If you are a refugee from many other VCS tools, it can be really hard to "unlearn" the please-let-me-avoid-merging-at-any-cost habit. Bazaar lets you safely merge as often as you like with other people. By working in a peer-to-peer manner when it makes sense to do so, you also avoid using a central branch as an "integration swamp", keeping its quality higher. When the change you're collaborating on is truly ready for wider sharing, that's the time to merge and commit it to a central branch, not before.

Merging that Just Works truly can change how developers work together.

4.4   Resolving conflicts

4.4.1   Workflow

Unlike some other tools that force you to resolve each conflict during the merge process, Bazaar merges as much as it can and then reports the conflicts. This can make conflict resolution easier because the contents of the whole post-merge tree are available to help you decide how things ought to be resolved. You may also wish to selectively run tests as you go to confirm each resolution or group or resolutions is good.

4.4.2   Listing conflicts

As well as being reported by the merge command, the list of outstanding conflicts may be displayed at any time by using the conflicts command. It is also included as part of the output from the status command.

4.4.3   Resolving a conflict

When a conflict is encountered, the merge command puts embedded markers in each file showing the areas it couldn't resolve. It also creates 3 files for each file with a conflict:

  • foo.BASE
  • foo.THIS
  • foo.OTHER

where foo is the name of the conflicted file. In many cases, you can resolve conflicts by simply manually editing each file in question, fixing the relevant areas and removing the conflict markers as you go.

After fixing all the files in conflict, ask Bazaar to mark them as resolved using the resolve command like this:

bzr resolve

Alternatively, after fixing each file, you can mark it as resolved like this:

bzr resolve foo

Among other things, the resolve command cleans up the BASE, THIS and OTHER files from your working tree.

4.4.4   Using the remerge command

In some cases, you may wish to try a different merge algorithm on a given file. To do this, use the remerge command nominating the file like this:

bzr remerge --weave foo

where foo is the file and weave is one of the available merge algorithms. This algorithm is particularly useful when a so-called criss-cross merge is detected, e.g. when two branches merge the same thing then merge each other. See the online help for criss-cross and remerge for further details.

4.4.5   Using external tools to resolve conflicts

If you have a GUI tool you like using to resolve conflicts, be sure to install the extmerge plugin. Once installed, it can be used like this:

bzr extmerge foo

where foo is the conflicted file. Rather than provide a list of files to resolve, you can give the --all option to implicitly specify all conflicted files.

The extmerge command uses the tool specified by the external_merge setting in your bazaar.conf file. If not set, it will look for some popular merge tools such as kdiff3 or opendiff, the latter being a command line interface to the FileMerge utility in OS X.

4.5   Annotating changes

4.5.1   Seeing the origin of content

When two or more people are working on files, it can be highly useful at times to see who created or last changed certain content. To do this, using the annotate command like this:

bzr annotate readme.txt

If you are a pessimist or an optimist, you might prefer to use one of built-in aliases for annotate: blame or praise. Either way, this displays each line of the file together with information such as:

  • who changed it last
  • when it was last changed
  • the commit message.

4.5.2   GUI tools

The various GUI plugins for Bazaar provide graphical tools for viewing annotation information. For example, the bzr-gtk plugin provides a GUI tool for this that can be launched using the gannotate command:

bzr gannotate readme.txt

The GUI tools typically provide a much richer display of interesting information (e.g. all the changes in each commit) so they are often preferred over the text-based command by users.

5   Team collaboration, central style

5.1   Centralized development

5.1.1   Motivation

Rather than working in parallel and occasionally merging, it can be useful at times to work in lockstep, i.e. for multiple people to be continuously committing changes to a central location, merging their work with the latest content before every commit.

This workflow is very familiar to users of central VCS tools like Subversion and CVS. It is also applicable to a single developer who works on multiple machines, e.g. someone who normally works on a desktop computer but travels with a laptop, or someone who uses their (Internet connected) home computer to complete office work out of hours.

If centralized development works well for your team already, that's great. Many teams begin using Bazaar this way and experiment with alternative workflows later.

5.1.2   Centralized workflow

The diagram below provides an overview of the centralized workflow.

images/workflows_centralized.png

Even if your team is planning to use a more distributed workflow, many of the tasks covered in this chapter may be useful to you, particularly how to publish branches.

5.2   Publishing a branch

5.2.1   Setting up a central repository

While the centralized workflow can be used by socially nominating any branch on any computer as the central one, in practice most teams have a dedicated server for hosting central branches.

Just as it's best practice to use a shared repository locally, it's advisable to put central branches in a shared repository. Note that central shared branches typically only want to store history, not working copies of files, so their enclosing repository is usually creating using the no-trees option, e.g.:

bzr init-repo --no-trees sftp://centralhost/srv/bzr/X-repo/

You can think of this step as similar to setting up a new cvsroot or Subversion repository. However, Bazaar gives you more flexibility in how branches may be organised in your repository. See Choosing a shared repository layout in the appendices for guidelines and examples.

5.2.2   Starting a central branch

There are two ways of populating a central branch with some initial content:

  1. Making a local branch and pushing it to a central location
  2. Making an empty central branch then committing content to it.

Here is an example of the first way:

bzr init-repo X-repo
bzr init X-repo/X-trunk
cd X-repo/X-trunk
cp -ar ~/X .     (copy files in using OS-specific tools)
bzr add
bzr commit -m "Initial import"
(local branch has content - publish it centrally now)
bzr push sftp://centralhost/srv/bzr/X-repo/X-trunk

Here is an example of the second way:

bzr init-repo X-repo
cd X-repo
bzr init sftp://centralhost/srv/bzr/X-repo/X-trunk
bzr checkout sftp://centralhost/srv/bzr/X-repo/X-trunk
cd X-trunk
cp -ar ~/X .     (copy files in using OS-specific tools)
bzr add
bzr commit -m "Initial import"

Note that committing inside a working tree created using the checkout command implicitly commits the content to the central location as well as locally. Had we used the branch command instead of checkout above, the content would have only been committed locally.

Working trees that are tightly bound to a central location like this are called checkouts. The rest of this chapter explains their numerous features in more detail.

5.3   Using checkouts

5.3.1   Turning a branch into a checkout

If you have a local branch and wish to make it a checkout, use the bind command like this:

bzr bind sftp://centralhost/srv/bzr/X-repo/X-trunk

This is necessary, for example, after creating a central branch using push as illustrated in the previous section.

After this, commits will be applied to the bound branch before being applied locally.

5.3.2   Turning a checkout into a branch

If you have a checkout and wish to make it a normal branch, use the unbind command like this:

bzr unbind

After this, commits will only be applied locally.

5.3.3   Getting a checkout

When working in a team using a central branch, one person needs to provide some initial content as shown in the previous section. After that, each person should use the checkout command to create their local checkout, i.e. the sandbox in which they will make their changes.

Unlike Subversion and CVS, in Bazaar the checkout command creates a local full copy of history in addition to creating a working tree holding the latest content. This means that operations such as diff and log are fast and can still be used when disconnected from the central location.

5.3.4   Getting a lightweight checkout

While Bazaar does its best to efficiently store version history, there are occasions when the history is simply not wanted. For example, if your team is managing the content of a web site using Bazaar with a central repository, then your release process might be as simple as updating a checkout of the content on the public web server. In this case, you probably don't want the history downloaded to that location as doing so:

  • wastes disk space holding history that isn't needed there
  • exposes a Bazaar branch that you may want kept private.

To get a history-less checkout in Bazaar, use the --lightweight option like this:

bzr checkout --lightweight sftp://centralhost/srv/bzr/X-repo/X-trunk

Of course, many of the benefits of a normal checkout are lost by doing this but that's a tradeoff you can make if and when it makes sense.

Note: If your code base is really large and disk space on your computer is limited, lightweight checkouts may be the right choice for you. Be sure to consider all your options though including shared repositories and Reusing a checkout as explained later.

5.3.5   Updating to the latest content

One of the important aspects of working in lockstep with others is keeping your checkout up to date with the latest changes made to the central branch. Just as you would in Subversion or CVS, you do this in Bazaar by using the update command like this:

bzr update

This gets any new revisions available in the bound branch and merges your local changes, if any.

5.3.6   Handling commit failures

Note that your checkout must be up to date with the bound branch before running commit. Bazaar is actually stricter about this than Subversion or CVS - you need to be up to date with the full tree, not just for the files you've changed. Bazaar will ask you to run update if it detects that a revision has been added to the central location since you last updated.

If the network connection to the bound branch is lost, the commit will fail. Some alternative ways of working around that are outlined next.

5.4   Working offline on a central branch

5.4.1   The centralized with local commits workflow

If you lose your network connection because you are travelling, the central server goes down, or you simply want to snapshot changes locally without publishing them centrally just yet, this workflow is for you.

images/workflows_localcommit.png

5.4.2   Committing locally

If you're working in a checkout and need/wish to commit locally only, add the --local option to the commit command like this:

bzr commit --local

5.4.3   Being disconnected for long time periods

If you will be or want to be disconnected from the bound branch for a while, then remembering to add --local to every commit command can be annoying. An alternative is to use the unbind command to make the checkout temporarily into a normal branch followed by the bind command at some later point in time when you want to keep in lockstep again.

Note that the bind command remembers where you were bound to last time this branch was a checkout so it isn't necessary to enter the URL of the remote branch when you use bind after an earlier unbind.

5.4.4   Merging a series of local commits

When you make commits locally independent of ongoing development on a central branch, then Bazaar treats these as two lines of development next time you update. In this case, update does the following:

  • it brings the latest revisions from the bound branch down and makes that the mainline of development within your checkout
  • it moves your local changes since you last updated into a logical parallel branch
  • it merges these together so that your local changes are reported as a pending merge by status.

As always, you will need to run commit after this to send your work to the central branch.

5.5   Reusing a checkout

5.5.1   Motivation

At times, it can be useful to have a single checkout as your sandbox for working on multiple branches. Some possible reasons for this include:

  • saving disk space when the working tree is large
  • developing in a fixed location.

In many cases, working tree disk usage swamps the size of the .bzr directory. If you want to work on multiple branches but can't afford the overhead of a full working tree for each, reusing a checkout across multiples branches is the way to go.

On other occasions, the location of your sandbox might be configured into numerous development and testing tools. Once again, reusing a checkout across multiple branches can help.

5.5.2   Changing where a branch is bound to

To change where a checkout is bound to, follow these steps:

  1. Make sure that any local changes have been committed centrally so that no work is lost.
  2. Use the bind command giving the URL of the new remote branch you wish to work on.
  3. Make your checkout a copy of the desired branch by using the update command followed by the revert command.

Note that simply binding to a new branch and running update merges in your local changes, both committed and uncommitted. You need to decide whether to keep them or not by running either revert or commit.

An alternative to the bind+update recipe is using the switch command. This is basically the same as removing the existing branch and running checkout again on the new location, except that any uncommitted changes in your tree are merged in.

Note: As switch can potentially throw away committed changes in order to make a checkout an accurate cache of a different bound branch, it will fail by design if there are changes which have been committed locally but are not yet committed to the most recently bound branch. To truly abandon these changes, use the --force option.

5.5.3   Switching a lightweight checkout

With a lightweight checkout, there are no local commits and switch effectively changes which branch the working tree is associated with. One possible setup is to use a lightweight checkout in combination with a local tree-less repository. This lets you switch what you are working on with ease. For example:

bzr init-repo --no-trees X-repo
cd X-repo
bzr branch sftp://centralhost/srv/bzr/X-repo/X-trunk
bzr checkout --lightweight X-trunk my-sandbox
cd my-sandbox
(hack away)

Note that X-trunk in this example will have a .bzr directory within it but there will be no working tree there as the branch was created in a tree-less repository. You can grab or create as many branches as you need there and switch between them as required. For example:

(assuming in my-sandbox)
bzr branch sftp://centralhost/srv/bzr/X-repo/X-1.0 ../X-1.0
bzr switch ../X-1.0
(fix bug in 1.0)
bzr commit -m "blah, blah blah"
bzr switch ../X-trunk
(go back to working on the trunk)

Note: The branches may be local only or they may be bound to remote ones (by creating them with checkout or by using bind after creating them with branch).

6   Team collaboration, distributed style

6.1   Distributed development

6.1.1   Motivation

Distributed VCS tools offer new ways of working together, ways that better reflect the modern world we live in and ways that enable higher quality outcomes.

6.1.2   The decentralized with shared mainline workflow

In this workflow, each developer has their own branch or branches, plus commit rights to the main branch. They do their work in their personal branch, then merge it into the mainline when it is ready.

images/workflows_shared.png

Other distributed workflows are explored later in this chapter.

6.2   Organizing branches

6.2.1   Mirror branches

A primary difference when using distributed workflows to develop is that your main local branch is not the place to make changes. Instead, it is kept as a pristine copy of the central branch, i.e. it's a mirror branch.

To create a mirror branch, set-up a shared repository (if you haven't already) and then use the branch (or checkout) command to create the mirror. For example:

bzr init-repo X-repo
cd X-repo
bzr branch sftp://centralhost/srv/bzr/X-repo/X-trunk

6.2.2   Task branches

Each new feature or fix is developed in its own branch. These branches or referred to as feature branches * or *task branches - the terms are used interchangably.

To create a task branch, use the branch command against your mirror branch. For example:

bzr branch X-trunk X-fix-123
cd X-fix-123
(hack, hack, hack)

There are numerous advantages to this approach:

  1. You can work on multiple changes in parallel
  2. There is reduced coupling between changes
  3. Multiple people can work in a peer-to-peer mode on a branch until it is ready to go.

In particular, some changes take longer to cook than others so you can ask for reviews, apply feedback, ask for another review, etc. By completing work to sufficient quality in separate branches before merging into a central branch, the quality and stability of the central branch are maintained at higher level than they otherwise would be.

6.2.3   Refreshing a mirror branch

Use the pull command to do this:

cd X-trunk
bzr pull

6.2.4   Merging the latest trunk into a feature branch

Use the merge command to do this:

cd X-fix-123
bzr merge
(resolve any conflicts)
bzr commit -m "merged X-trunk"

6.2.5   Merging a feature into the trunk

The policies for different distributed workflows vary here. The simple case where all developers have commit rights to the main trunk are shown below.

If your mirror is a checkout:

cd X-trunk
bzr update
bzr merge ../X-fix-123
(resolve any conflicts)
bzr commit -m "Fixed bug #123"

If your mirror is a branch:

cd X-trunk
bzr pull
bzr merge ../X-fix-123
(resolve any conflicts)
bzr commit -m "Fixed bug #123"
bzr push

6.2.6   Backing up task branches

One of the side effects of centralized workflows is that changes get frequently committed to a central location which is backed up as part of normal IT operations. When developing on task branches, it is a good idea to publish your work to a central location (but not necessarily a shared location) that will be backed up. You may even wish to bind local task branches to remote ones established on a backup server just for this purpose.

6.3   Using gatekeepers

6.3.1   The decentralized with human gatekeeper workflow

In this workflow, one developer (the gatekeeper) has commit rights to the main branch while other developers have read-only access. All developers make their changes in task branches.

images/workflows_gatekeeper.png

When a developer wants their work merged, they ask the gatekeeper to review their change and merge it if acceptable. If a change fails review, further development proceeds in the relevant task branch until it is good to go.

Note that a key aspect of this approach is the inversion of control that is implied: developers no longer decide when to "commit/push" changes into the central branch: the code base evolves by gatekeepers "merging/pulling" changes in a controlled manner. It's perfectly acceptable, indeed common, to have multiple central branches with different gatekeepers, e.g. one branch for the current production release and another for the next release. In this case, a task branch holding a bug fix will most likely be advertized to both gatekeepers.

One of the great things about this workflow is that it is hugely scalable. Large projects can be broken into teams and each team can have a local master branch managed by a gatekeeper. Someone can be appointed as the primary gatekeeper to merge changes from the team master branches into the primary master branch when team leaders request it.

6.3.2   The decentralized with automatic gatekeeper workflow

To obtain even higher quality, all developers can be required to submit changes to an automated gatekeeper that only merges and commits a change if it passes a regression test suite. One such gatekeeper is a software tool called PQM.

images/workflows_pqm.png

For further information on PQM, see https://launchpad.net/pqm.

6.4   Sending changes

6.4.1   Motivation

In many distributed development scenarios, it isn't always feasible for developers to share task branches by advertising their URLs. For example, a developer working on a laptop might take it home overnight so his/her task branches could well be inaccessible when a gatekeeper in another timezone wants to review or merge it.

Bazaar provides a neat feature to assist here: merge directives.

6.4.2   Understanding merge directives

You can think of a merge directive as a "mini branch" - just the new growth on a branch since it was created. It's a software patch showing what's new but with added intelligence: metadata like interim commits, renames and digital signatures.

Another useful metaphor is a packet cake: a merge directive has a recipe together with the ingredients you need bundled inside it. To stretch the metaphor, the ingredients are all the metadata on the changes made to the branch; the recipe is instructions on how those changes ought to be merged, i.e. information for the merge command to use in selecting common ancestors.

Regardless of how you think of them, merge directives are neat. They are easy to create, suitable for mailing around as attachments and can be processed much like branches can on the receiving end.

6.4.3   Creating a merge directive

To create a merge directive, use the send command. For example, this command creates a merge directive and saves it into the nominated output file:

cd X-fix-123
bzr send -o ../fix-123.patch

That file can then be emailed to a reviewer, together with an explanation of how and why you fixed the problem the way you did, say.

Emailing merge directives is such a common thing that the send command without options will create a merge directive, fire up your email tool and attach it, ready for you to add the explanatory text bit. See the online help for send and the Configuration reference for further details on how to configure this.

6.4.4   Applying a merge directive

Merge directives can be applied in much the same way as branches: by using the merge and pull commands.

They can also be useful when communicating with upstream projects that don't use Bazaar. In particular, the preview of the overall change in a merge directive looks like a vanilla software patch, so they can be applied using patch -p0 for example.

7   Best practices

7.1   Welcome to best practices

We hope that earlier chapters have given you a solid understanding of how Bazaar can assist you in being productive on your own and working effectively with others. If you are learning Bazaar for the first time, it might be good to try the procedures covered already for a while, coming back to this manual once you have mastered them.

This chapter covers miscellaneous topics to guide you in further optimizing how you use Bazaar. Unless stated otherwise, the topics are independent of each other and can therefore be read in whichever order you wish.

7.2   Pseudo merging

7.2.1   Cherrypicking

At times, it can be useful to selectively merge some of the changes in a branch, but not all of them. This is commonly referred to as cherrypicking. Here are some examples of where cherrypicking is useful:

  • selectively taking fixes from the main development branch into a release branch
  • selectively taking improvements out of an experimental branch into a feature branch.

To merge only the changes made by revision X in branch foo, the command is:

bzr merge -c X foo

To merge only the changes up to revision X in branch foo, the command is:

bzr merge -r X foo

To merge only the changes since revision X in branch foo, the command is:

bzr merge -r X.. foo

To merge only the changes from revision X to revision Y in branch foo, the command is:

bzr merge -r X..Y foo

Like a normal merge, you must explicitly commit a cherrypick. You may wish to see the changes made using bzr diff, and run your test suite if any, before doing this.

Unlike a normal merge, Bazaar does not currently track cherrypicks. In particular, the changes look like a normal commit and the (internal) revision history of the changes from the other branch is lost. In many cases where they are useful (see above), this is not a major problem because there are good reasons why a full merge should never be done at a later time. In other cases, additional conflicts will need to be resolved when the changes are merged again.

7.2.2   Reverse cherrypicking

Cherrypicking can be used to reverse a set of changes made by giving an upper bound in the revision range which is below the lower bound. For example, to back-out changes made in revision 10, the command is:

bzr merge -r 10..9

If you want to take most changes, but not all, from somewhere else, you may wish to do a normal merge followed by a few reverse cherrypicks.

7.2.3   Merging uncommitted changes

If you have several branches and you accidently start making changes in the wrong one, here are the steps to take to correct this. Assuming you began working in branch foo when you meant to work in branch bar:

  1. Change into branch bar.
  2. Run bzr merge --uncommitted foo
  3. Check the changes came across (bzr diff)
  4. Change into branch foo
  5. Run bzr revert.

7.2.4   Rebasing

Another option to normal merging is rebasing, i.e. making it look like the current branch originated from a different point than it did. Rebasing is supported in Bazaar by the rebase command provided by the rebase plugin.

The rebase command takes the location of another branch on which the branch in the current working directory will be rebased. If a branch is not specified then the parent branch is used, and this is usually the desired result.

The first step identifies the revisions that are in the current branch that are not in the parent branch. The current branch is then set to be at the same revision as the target branch, and each revision is replayed on top of the branch. At the end of the process it will appear as though your current branch was branched off the current last revision of the target.

Each revision that is replayed may cause conflicts in the tree. If this happens the command will stop and allow you to fix them up. Resolve the commits as you would for a merge, and then run bzr resolve to marked them as resolved. Once you have resolved all the conflicts, you should run bzr rebase-continue to continue the rebase operation. If conflicts are encountered and you decide not to continue, you can run bzr rebase-abort. You can also use rebase-todo to show the list of commits still to be replayed.

Note: Some users coming from central VCS tools with poor merge tracking like rebasing because it's similar to how they are use to working in older tools, or because "perfectly clean" history seems important. Before rebasing in Bazaar, think about whether a normal merge is a better choice. In particular, rebasing a private branch before sharing it is OK but rebasing after sharing a branch with someone else is strongly discouraged.

7.3   Running a smart server

Bazaar does not require a specialised server because it operates over HTTP, FTP or SFTP. There is an optional smart server that can be invoked over SSH, from inetd, or in a dedicated mode.

7.3.1   Dumb servers

We describe HTTP, FTP, SFTP and HTTP-WebDAV as "dumb" servers because they do not offer any assistance to Bazaar. If you make a Bazaar repository available over any of these protocols, Bazaar will allow you to read it remotely. Just enter the URL to the branch in the Bazaar command you are running.:

bzr log http://bazaar-vcs.org/bzr/bzr.dev

Bazaar supports writing over FTP, SFTP and (via a plugin) over HTTP-WebDAV.

7.3.2   High-performance smart server

The high-performance smart server (hpss) performs certain operations much faster than dumb servers are capable of. In future releases, the range of operations that are improved by using the smart server will increase as we continue to tune performance.

To maintain the highest security possible, the current smart server provides read-only access by default. To enable read-write access, run it with --allow-writes. When using the SSH access method, bzr automatically runs with with the --allow-writes option.

The alternative ways of configuring a smart server are explained below.

7.3.2.1   SSH

Using Bazaar over SSH requires no special configuration on the server:

BZR_REMOTE_PATH=~/bin/bzr bzr log bzr+ssh://host/path/to/branch

The BZR_REMOTE_PATH environment variable adjusts how bzr will be invoked on the remote system. By default, just bzr will be invoked, which requires the bzr executable to be on the default search path.

The bzr+ssh:// URL scheme only supports absolute paths from the root of the filesystem. Future versions are expected to support ~ in the same way as sftp:// URLs (https://bugs.launchpad.net/bzr/+bug/109143).

7.3.2.2   inetd

This example shows how to run bzr with a dedicated user bzruser for a shared repository in /srv/bzr/repo which has a branch at /srv/bzr/repo/branchname.

Running a Bazaar server from inetd requires an inetd.conf entry:

4155  stream  tcp  nowait  bzruser  /usr/bin/bzr /usr/bin/bzr serve --inet --directory=/srv/bzr/repo

When running client commands, the URL you supply is a bzr:// URL relative to the --directory option given in inetd.conf:

bzr log bzr://host/branchname

7.3.2.3   Dedicated

This mode has the same path and URL behaviour as the inetd mode. To run as a specific user, you should use su or login as that user.

This example runs bzr on its official port number of 4155 and listens on all interfaces. This allows connections from anywhere in the world that can reach your machine on port 4155.

server:

bzr serve --directory=/srv/bzr/repo

client:

bzr log bzr://host/branchname

This example runs bzr serve on localhost port 1234.

server:

bzr serve --port=localhost:1234 --directory=/srv/bzr/repo

client:

bzr log bzr://localhost:1234/branchname

7.4   Using hooks

7.4.1   What is a hook?

One way to customize Bazaar's behaviour is with hooks. Hooks allow you to perform actions before or after certain Bazaar operations. The operations include commit, push, pull, and uncommit.

7.4.2   Using hooks

To use a hook, you should write a plugin. Instead of creating a new command, this plugin will define and install the hook. Here's an example:

from bzrlib import branch


def post_push_hook(push_result):
    print "The new revno is %d" % push_result.new_revno


branch.Branch.hooks.install_hook('post_push', post_push_hook)
branch.Branch.hooks.name_hook(post_push_hook, 'My post_push hook')

To use this example, create a file named push_hook.py, and stick it in plugins subdirectory of your configuration directory. (If you have never installed any plugins, you may need to create the plugins directory).

First, we define a function that will be run after push completes. We could also use an instance method or a callable object. All push hooks take a single argument, the push_result.

Next, we install the hook. 'post_push' identifies where we want to install the hook, and the second parameter is the hook itself.

Finally, we name the hook. This is optional, but it means the hook name can be used in progress messages and error messages.

That's it! The next time you push, it should show "The new revno is...". Of course, hooks can be much more elaborate than this, because you have the full power of Python at your disposal. Now that you know how to use hooks, what you do with them is up to you.

7.4.3   Standard hooks

For a complete list of hooks and their parameters, see the Hooks Reference.

7.5   Exporting version information

7.5.1   Getting the last revision number

If you only need the last revision number in your build scripts, you can use the revno command to get that value like this:

$ bzr revno
3104

7.5.2   Getting more version information

The version-info command can be used to output more information about the lastest version like this:

$ bzr version-info
revision-id: pqm@pqm.ubuntu.com-20071211175118-s94sizduj201hrs5
date: 2007-12-11 17:51:18 +0000
build-date: 2007-12-13 13:14:51 +1000
revno: 3104
branch-nick: bzr.dev

You can easily filter that output using operating system tools or scripts. For example (on Linux/Unix):

$ bzr version-info | grep ^date
date: 2007-12-11 17:51:18 +0000

The --all option will actually dump version information about every revision if you need that information for more advanced post-processing.

7.5.3   Python projects

If using a Makefile to build your project, you can generate the version information file as simply as:

library/_version.py:
      bzr version-info --format python > library/_version.py

This generates a file which contains 3 dictionaries:

  • version_info: A dictionary containing the basic information about the current state.
  • revisions: A dictionary listing all of the revisions in the history of the tree, along with the commit times and commit message. This defaults to being empty unless --all or --include-history is supplied. This is useful if you want to track what bug fixes, etc, might be included in the released version. But for many projects it is more information than needed.
  • file_revisions: A dictionary listing the last-modified revision for all files in the project. This can be used similarly to how $Id$ keywords are used in CVS-controlled files. The last modified date can be determined by looking in the revisions map. This is also empty by default, and enabled only by --all or --include-file-revisions.

7.5.4   Projects in other languages

Support for dumping version information in other languages in currently in development. Please contact us on the mailing list about your requirements in this area. (As of the Bazaar 1.0 release date, some patches are available for other languages but are not yet merged into the core product.)

7.5.5   Check clean

Most information about the contents of the project can be cheaply determined by just reading the revision entry. However, it can be useful to know if the working tree was completely up-to-date when it was packaged, or if there was a local modification. By supplying either --all or --check-clean, bzr will inspect the working tree, and set the clean flag in version_info, as well as set entries in file_revisions as modified where appropriate.

7.6   Integrating Bazaar with bug trackers

Bazaar has a facility that allows you to associate a commit with a bug in the project's bug tracker. Other tools (or hooks) can then use this information to link between the commit and the bug, or to automatically mark the bug closed in the branches that contain the commit.

7.6.1   Associating commits and bugs

When you make a commit, you can associate it with a bug by using the --fixes option of commit. For example:

$ bzr commit --fixes lp:12345 -m "Properly close the connection"

This records metadata in Bazaar linking the commit with bug 12345 in Launchpad. If you use a different bug tracker, it can be given its own tracker code (instead of lp) and used instead. For details on how to configure this, refer to Bug Tracker Settings in the Bazaar User Reference.

7.6.2   Metadata recording vs bug tracker updating

Recording metadata about bugs fixed at commit time is only one of the features needed for complete bug tracker integration. As Bazaar is a distributed VCS, users may be offline while committing so accessing the bug tracker itself at that time may not be possible. Instead, it is recommended that a hook be installed to update the bug tracker when changes are pushed to a central location appropriate for your project's workflow.

Note: This second processing stage is part of the integration provided by Lauchpad when it scans external or hosted branches.

7.6.3   Making corrections

This method of associating revisions and bugs does have some limitations. The first is that the association can only be made at commit time. This means that if you forget to make the association when you commit, or the bug is reported after you fix it, you generally cannot go back and add the link later.

Related to this is the fact that the association is immutable. If a bug is marked as fixed by one commit but that revision does not fully solve the bug, or there is a later regression, you cannot go back and remove the link.

Of course, bzr uncommit can always be used to undo the last commit in order to make it again with the correct options. This is commonly done to correct a bad commit message and it equally applies to correcting metadata recorded (via --fixes for example) on the last commit.

8   Appendices

8.1   Specifying revisions

8.1.1   Revision identifiers and ranges

Bazaar has a very expressive way to specify a revision or a range of revisions. To specify a range of revisions, the upper and lower bounds are separated by the .. symbol. For example:

$ bzr log -r 1..4

You can omit one bound like:

$ bzr log -r 1..
$ bzr log -r ..4

Some commands take only one revision, not a range. For example:

$ bzr cat -r 42 foo.c

In other cases, a range is required but you want the length of the range to be one. For commands where this is relevant, the -c option is used like this:

$ bzr diff -c 42

8.1.2   Available revision identifiers

The revision, or the bounds of the range, can be given using different format specifications as shown below.

argument type description
number revision number
revno:number positive revision number
last:number negative revision number
revid:guid globally unique revision id
before:rev leftmost parent of ''rev''
date:value first entry after a given date
tag:value revision matching a given tag
ancestor:path last merged revision from a branch
branch:path latest revision on another branch
submit:path common ancestor with submit branch

A brief introduction to some of these formats is given below. For complete details, see Revision Identifiers in the Bazaar User Reference.

8.1.2.1   Numbers

Positive numbers denote revision numbers in the current branch. Revision numbers are labelled as "revno" in the output of bzr log. To display the log for the first ten revisions:

$ bzr log -r ..10

Negative numbers count from the latest revision, -1 is the last committed revision.

To display the log for the last ten revisions:

$ bzr log -r -10..

8.1.2.2   revid

revid allows specifying a an internal revision ID, as shown by bzr log and some other commands.

For example:

$ bzr log -r revid:Matthieu.Moy@imag.fr-20051026185030-93c7cad63ee570df

8.1.2.3   before

before
''rev'' specifies the leftmost parent of ''rev'', that is the revision that appears before ''rev'' in the revision history, or the revision that was current when ''rev'' what comitted.

''rev'' can be any revision specifier and may be chained.

For example:

$ bzr log -r before:before:4
...
revno: 2
...

8.1.2.4   date

date
''value'' matches the first history entry after a given date, either at midnight or at a specified time.

Legal values are:

  • yesterday
  • today
  • tomorrow
  • A YYYY-MM-DD format date.
  • A YYYY-MM-DD,HH:MM:SS format date/time, seconds are optional (note the comma)

The proper way of saying "give me all the log entries for today" is:

$ bzr log -r date:yesterday..date:today

8.1.2.5   Ancestor

ancestor:path
specifies the common ancestor between the current branch and a different branch. This is the same ancestor that would be used for merging purposes.

path may be the URL of a remote branch, or the file path to a local branch.

For example, to see what changes were made on a branch since it was forked off ../parent:

$ bzr diff -r ancestor:../parent

8.1.2.6   Branch

branch
path specifies the latest revision in another branch.

path may be the URL of a remote branch, or the file path to a local branch.

For example, to get the differences between this and another branch:

$ bzr diff -r branch:http://example.com/bzr/foo.dev

8.2   Choosing a shared repository layout

Bazaar is designed to give you flexibility in how you layout branches inside a shared repository. This flexibility allows users to tailor Bazaar to their workflow, but it also leads to questions about what is a "good" layout. We present some alternatives and give some discussion about the benefits of each.

One key point which should be mentioned is that any good layout should somehow highlight what branch a "general" user should grab. In SVN this is deemed the "trunk/" branch, and in most of the layouts this naming convention is preserved. Some would call this "mainline" or "dev", and people from CVS often refer to this as "HEAD".

8.2.1   "SVN-Style" (trunk/, branches/)

Most people coming from SVN will be familiar with their "standard" project layout. Which is to layout the repository as:

repository/       # Overall repository
 +- trunk/        # The mainline of development
 +- branches/     # A container directory
 |   +- foo/      # Branch for developing feature foo
 |     ...
 +- tags/         # Container directory
     +- release-X # A branch specific to mark a given release version
        ...

With Bazaar, that is a perfectly reasonable layout. It has the benefit of being familiar to people coming from SVN, and making it clear where the development focus is.

When you have multiple projects in the same repository, the SVN layout is a little unclear what to do.

8.2.1.1   project/trunk

The preferred method for SVN seems to be to give each project a top level directory for a layout like:

repository/            # Overall repository
 +- project1/          # A container directory
 |   +- trunk/         # The mainline of development of project1
 |   +- branches/      # A container directory
 |       +- foo/       # Branch for developing feature foo of project1
 |         ...
 |
 +- project2/          # Container for project2
     +- trunk/         # Mainline for project2
     +- branches/      # Container for project2 branches

This also works with Bazaar. However, with Bazaar repositories are cheap to create (a simple bzr init-repo away), and their primary benefit is when the branches share a common ancestry.

So the preferred way for Bazaar would be:

project1/          # A repository for project1
 +- trunk/         # The mainline of development of project1
 +- branches/      # A container directory
     +- foo/       # Branch for developing feature foo of project1
       ...

project2/          # A repository for project2
 +- trunk/         # Mainline for project2
 +- branches/      # Container for project2 branches

8.2.1.2   trunk/project

There are also a few projects who use this layout in SVN:

repository/             # Overall repository
  +- trunk/             # A container directory
  |   +- project1       # Mainline for project 1
  |   +- project2       # Mainline for project 2
  |         ...
  |
  +- branches/          # Container
      +- project1/      # Container (?)
      |   +- foo        # Branch 'foo' of project1
      +- project2/
          +- bar        # Branch 'bar' of project2

A slight variant is:

repository/             # Overall repository
  +- trunk/             # A container directory
  |   +- project1       # Mainline for project 1
  |   +- project2       # Mainline for project 2
  |         ...
  |
  +- branches/          # Container
      +- project1-foo/  # Branch 'foo' of project1
      +- project2-bar/  # Branch 'bar' of project2

I believe the reason for this in SVN, is so that someone can checkout all of "trunk/" and get the all the mainlines for all projects.

This layout can be used for Bazaar, but it is not generally recommended.

  1. bzr branch/checkout/get is a single branch at a time. So you don't get the benefit of getting all mainlines with a single command.1
  2. It is less obvious of whether repository/trunk/foo is the trunk of project foo or it is just the foo directory in the trunk branch. Some of this confusion is due to SVN, because it uses the same "namespace" for files in a project that it uses for branches of a project. In Bazaar, there is a clear distinction of what files make up a project, versus the location of the Branch. (After all, there is only one .bzr/ directory per branch, versus many .svn/ directories in the checkout).
[1]Note: NestedTreeSupport can provide a way to create "meta-projects" which aggregate multiple projects regardless of the repository layout. Letting you bzr checkout one project, and have it grab all the necessary sub-projects.

8.2.2   Nested Style (project/branch/sub-branch/)

Another style with Bazaar, which is not generally possible in SVN is to have branches nested within each-other. This is possible because Bazaar supports (and recommends) creating repositories with no working trees (--no-trees). With a --no-trees repository, because the working files are not intermixed with your branch locations, you are free to put a branch in whatever namespace you want.

One possibility is:

project/             # The overall repository, *and* the project's mainline branch
 + joe/              # Developer Joe's primary branch of development
 |  +- feature1/     # Developer Joe's feature1 development branch
 |  |   +- broken/   # A staging branch for Joe to develop feature1
 |  +- feature2/     # Joe's feature2 development branch
 |    ...
 + barry/            # Barry's development branch
 |  ...
 + releases/
    +- 1.0/
        +- 1.1.1/

The idea with this layout is that you are creating a hierarchical layout for branches. Where changes generally flow upwards in the namespace. It also gives people a little corner of the namespace to work on their stuff. One nice feature of this layout, is it makes branching "cheaper" because it gives you a place to put all the mini branches without cluttering up the global branches/ namespace.

The other power of this is that you don't have to repeat yourself when specifying more detail in the branch name.

For example compare:

bzr branch http://host/repository/project/branches/joe-feature-foo-bugfix-10/

Versus:

bzr branch http://host/project/joe/foo/bugfix-10

Also, if you list the repository/project/branches/ directory you might see something like:

barry-feature-bar/
barry-bugfix-10/
barry-bugfix-12/
joe-bugfix-10/
joe-bugfix-13/
joe-frizban/

Versus having these broken out by developer. If the number of branches are small, branches/ has the nice advantage of being able to see all branches in a single view. If the number of branches is large, branches/ has the distinct disadvantage of seeing all the branches in a single view (it becomes difficult to find the branch you are interested in, when there are 100 branches to look through).

Nested branching seems to scale better to larger number of branches. However, each individual branch is less discoverable. (eg. "Is Joe working on bugfix 10 in his feature foo branch, or his feature bar branch?")

One other small advantage is that you can do something like:

 bzr branch http://host/project/release/1/1/1
or
 bzr branch http://host/project/release/1/1/2

To indicate release 1.1.1 and 1.1.2. This again depends on how many releases you have and whether the gain of splitting things up outweighs the ability to see more at a glance.

8.2.3   Sorted by Status (dev/, merged/, experimental/)

One other way to break up branches is to sort them by their current status. So you would end up with a layout something like:

project/               # Overall layout
 +- trunk/             # The development focus branch
 +- dev/               # Container directory for in-progress work
 |   +- joe-feature1   # Joe's current feature-1 branch
 |   +- barry-bugfix10 # Barry's work for bugfix 10
 |    ...
 +- merged/            # Container indicating these branches have been merged
 |   +- bugfix-12      # Bugfix which has already been merged.
 +- abandonded/        # Branches which are considered 'dead-end'

This has a couple benefits and drawbacks. It lets you see what branches are actively being developed on, which is usually only a small number, versus the total number of branches ever created. Old branches are not lost (versus deleting them), but they are "filed away", such that the more likely you are to want a branch the easier it is to find. (Conversely, older branches are likely to be harder to find).

The biggest disadvantage with this layout, is that branches move around. Which means that if someone is following the project/dev/new-feature branch, when it gets merged into trunk/ suddenly bzr pull doesn't mirror the branch for them anymore because the branch is now at project/merged/new-feature. There are a couple ways around this. One is to use HTTP redirects to point people requesting the old branch to the new branch. bzr >= 0.15 will let users know that http://old/path redirects to http://new/path. However, this doesn't help if people are accessing a branch through methods other than HTTP (SFTP, local filesystem, etc).

It would also be possible to use a symlink for temporary redirecting (as long as the symlink is within the repository it should cause little trouble). However eventually you want to remove the symlink, or you don't get the clutter reduction benefit. Another possibility instead of a symlink is to use a BranchReference. It is currently difficult to create these through the bzr command line, but if people find them useful that could be changed. This is actually how Launchpad allows you to bzr checkout https://launchpad.net/bzr. Effectively a BranchReference is a symlink, but it allows you to reference any other URL. If it is extended to support relative references, it would even work over http, sftp, and local paths.

8.2.4   Sorted by date/release/etc (2006-06/, 2006-07/, 0.8/, 0.9)

Another method of allowing some scalability while also allowing the browsing of "current" branches. Basically, this works on the assumption that actively developed branches will be "new" branches, and older branches are either merged or abandoned.

Basically the date layout looks something like:

project/                # Overall project repository
 +- trunk/              # General mainline
 +- 2006-06/            # containing directory for branches created in this month
 |   +- feature1/       # Branch of "project" for "feature1"
 |   +- feature2/       # Branch of "project" for "feature2"
 +- 2005-05/            # Containing directory for branches create in a different month
     +- feature3/
     ...

This answers the question "Where should I put my new branch?" very quickly. If a feature is developed for a long time, it is even reasonable to copy a branch into the newest date, and continue working on it there. Finding an active branch generally means going to the newest date, and going backwards from there. (A small disadvantage is that most directory listings sort oldest to the top, which may mean more scrolling). If you don't copy old branches to newer locations, it also has the disadvantage that searching for a branch may take a while.

Another variant is by release target:

project/          # Overall repository
 +- trunk/        # Mainline development branch
 +- releases/     # Container for release branches
 |   +- 0.8/      # The branch for release 0.8
 |   +- 0.9/      # The branch for release 0.9
 +- 0.8/          # Container for branches targeting release 0.8
 |   +- feature1/ # Branch for "feature1" which is intended to be merged into 0.8
 |   +- feature2/ # Branch for "feature2" which is targeted for 0.8
 +- 0.9/
     +- feature3/ # Branch for "feature3", targeted for release 0.9

Some possible variants include having the 0.9 directory imply that it is branched from 0.9 rather than for 0.9, or having the 0.8/release as the official release 0.8 branch.

The general idea is that by targeting a release, you can look at what branches are waiting to be merged. It doesn't necessarily give you a good idea of what the state of the branch (is it in development or finished awaiting review). It also has a history-hiding effect, and otherwise has the same benefits and deficits as a date-based sorting.

8.2.5   Simple developer naming (project/joe/foo, project/barry/bar)

Another possibly layout is to give each developer a directory, and then have a single sub-directory for branches. Something like:

project/      # Overall repository
 +- trunk/    # Mainline branch
 +- joe/      # A container for Joe's branches
 |   +- foo/  # Joe's "foo" branch of "project"
 +- barry/
     +- bar/  # Barry's "bar" branch of "project"

The idea is that no branch is "nested" underneath another one, just that each developer has his/her branches grouped together.

A variant which is used by Launchpad is:

repository/
 +- joe/             # Joe's branches
 |   +- project1/    # Container for Joe's branches of "project1"
 |   |   +- foo/     # Joe's "foo" branch of "project1"
 |   +- project2/    # Container for Joe's "project2" branches
 |       +- bar/     # Joe's "bar" branch of "project2"
 |        ...
 |
 +- barry/
 |   +- project1/    # Container for Barry's branches of "project1"
 |       +- bug-10/  # Barry's "bug-10" branch of "project1"
 |   ...
 +- group/
     +- project1/
         +- trunk/   # The main development focus for "project1"

This lets you easily browse what each developer is working on. Focus branches are kept in a "group" directory, which lets you see what branches the "group" is working on.

This keeps different people's work separated from each-other, but also makes it hard to find "all branches for project X". Launchpad compensates for this by providing a nice web interface with a database back end, which allows a "view" to be put on top of this layout. This is closer to the model of people's home pages, where each person has a "~/public_html" directory where they can publish their own web-pages. In general, though, when you are creating a shared repository for centralization of a project, you don't want to split it up by person and then project. Usually you would want to split it up by project and then by person.

8.2.6   Summary

In the end, no single naming scheme will work for everyone. It depends a lot on the number of developers, how often you create a new branch, what sort of lifecycles your branches go through. Some questions to ask yourself:

  1. Do you create a few long-lived branches, or do you create lots of "mini" feature branches (Along with this is: Would you like to create lots of mini feature branches, but can't because they are a pain in your current VCS?)
  2. Are you a single developer, or a large team?
  3. If a team, do you plan on generally having everyone working on the same branch at the same time? Or will you have a "stable" branch that people are expected to track.

8.3   Conflicts types

Some operations, like merge, revert and pull, modify the contents of your working tree. These modifications are programmatically generated, and so they may conflict with the current state of your working tree. Many kinds of changes can be combined programmatically, but sometimes only a human can determine the right thing to do. When this happens Bazaar will inform you that there is a conflict and then ask you to resolve it. The command to tell Bazaar a conflict is resolved is resolve, but you must perform some action before you can do this.

Each type of conflict is explained below, and the action which must be done to resolve the conflict is outlined.

8.3.1   Text conflicts

Typical message:

Text conflict in FILE

These are produced when a text merge cannot completely reconcile two sets of text changes. Bazaar will emit files for each version with the extensions THIS, OTHER, and BASE. THIS is the version of the file from the target tree, i.e. the tree that you are merging changes into. OTHER is the version that you are merging into the target. BASE is an older version that is used as a basis for comparison.

In the main copy of the file, Bazaar will include all the changes that it could reconcile, and any un-reconciled conflicts are surrounded by "herringbone" markers like <<<<<<<.

Say the initial text is "The project leader released it.", and THIS modifies it to "Martin Pool released it.", while OTHER modifies it to "The project leader released Bazaar." A conflict would look like this:

<<<<<<< TREE
Martin Pool released it.
=======
The project leader released Bazaar.
>>>>>>> MERGE-SOURCE

The correct resolution would be "Martin Pool released Bazaar."

You can handle text conflicts either by editing the main copy of the file, or by invoking external tools on the THIS, OTHER and BASE versions. It's worth mentioning that resolving text conflicts rarely involves picking one set of changes over the other. More often, the two sets of changes must be intelligently combined.

If you edit the main copy, be sure to remove the herringbone markers. When you are done editing, the file should look like it never had a conflict, and be ready to commit.

When you have resolved text conflicts, just run "bzr resolve", and Bazaar will auto-detect which conflicts you have resolved.

8.3.2   Content conflicts

Typical message:

Contents conflict in FILE

This conflict happens when there are conflicting changes in the target tree and the merge source, but the conflicted items are not text files. They may be binary files, or symlinks, or directories. It can even happen with files that are deleted on one side, and modified on the other.

Like text conflicts, Bazaar will emit THIS, OTHER and BASE files. (They may be regular files, symlinks or directories). But it will not include a "main copy" of the file with herringbone conflict markers. It will appear that the "main copy" has been renamed to THIS or OTHER.

To resolve this, use "bzr mv" to rename the file back to its normal name, and combine the changes manually. When you are satisfied, run "bzr resolve FILE". Bazaar cannot auto-detect when conflicts of this kind have been resolved.

8.3.3   Duplicate paths

Typical message:

Conflict adding file FILE.  Moved existing file to FILE.moved.

Sometimes Bazaar will attempt to create a file using a pathname that has already been used. The existing file will be renamed to "FILE.moved". If you wish, you can rename either one of these files, or combine their contents. When you are satisfied, you can run "bzr resolve FILE" to mark the conflict as resolved.

8.3.4   Unversioned parent

Typical message:

Conflict because FILE is not versioned, but has versioned children.

Sometimes Bazaar will attempt to create a file whose parent directory is not versioned. This happens when the directory has been deleted in the target, but has a new child in the source, or vice versa. In this situation, Bazaar will version the parent directory as well. Resolving this issue depends very much on the particular scenario. You may wish to rename or delete either the file or the directory. When you are satisfied, you can run "bzr resolve FILE" to mark the conflict as resolved.

8.3.5   Missing parent

Typical message:

Conflict adding files to FILE.  Created directory.

This happens when a file has been deleted in the target, but has new children in the source. This is similar to the "unversioned parent" conflict, except that the parent directory does not exist, instead of just being unversioned. In this situation, Bazaar will create the missing parent. Resolving this issue depends very much on the particular scenario. You may wish to rename or delete either the file or the directory. When you are satisfied, you can run "bzr resolve FILE" to mark the conflict as resolved.

8.3.6   Deleting parent

Typical message:

Conflict: can't delete FILE because it is not empty.  Not deleting.

This is the opposite of "missing parent". A directory is deleted in the source, but has new children in the target. Bazaar will retain the directory. Resolving this issue depends very much on the particular scenario. You may wish to rename or delete either the file or the directory. When you are satisfied, you can run "bzr resolve FILE" to mark the conflict as resolved.

8.3.7   Path conflict

Typical message:

Path conflict: PATH1 / PATH2

This happens when the source and target have each modified the name or parent directory of a file. Bazaar will use the path elements from the source. You can rename the file, and once you have, run "bzr resolve FILE" to mark the conflict as resolved.

8.3.8   Parent loop

Typical message:

Conflict moving FILE into DIRECTORY.  Cancelled move.

This happens when the source and the target have each moved directories, so that, if the change could be applied, a directory would be contained by itself. For example:

$ bzr init
$ bzr mkdir a
$ bzr mkdir b
$ bzr commit -m "BASE"
$ bzr branch . ../other
$ bzr mv a b
$ bzr commit -m "THIS"
$ bzr mv ../other/b ../other/a
$ bzr commit ../other -m "OTHER"
$ bzr merge ../other

In this situation, Bazaar will cancel the move, and leave "a" in "b". You can rename the directories if you like, and once you have, run "bzr resolve FILE" to mark the conflict as resolved.

8.3.9   MalformedTransform

It is possible (though very rare) for Bazaar to raise a MalformedTransform exception. This means that Bazaar encountered a filesystem conflict that it was unable to resolve. This usually indicates a bug. Please let us know if you encounter this. Our bug tracker is at https://launchpad.net/bzr/+bugs

8.4   Configuration reference

8.4.1   Environment variables

While most configuration is handled by configuration files, some options which may be semi-permanent can also be controlled through the environment.

8.4.1.1   BZR_EMAIL

Override the email id used by Bazaar. Typical format:

"John Doe <jdoe@example.com>"

See also the email configuration value.

8.4.1.2   BZR_PROGRESS_BAR

Override the progress display. Possible values are "none", "dots", "tty"

8.4.1.3   BZR_SIGQUIT_PDB

Control whether SIGQUIT behaves normally or invokes a breakin debugger.

  • 0 = Standard SIGQUIT behavior (normally, exit with a core dump)
  • 1 = Invoke breakin debugger (default)

8.4.1.4   BZR_HOME

Override the home directory used by Bazaar.

8.4.1.5   BZR_SSH

Select a different SSH implementation.

8.4.1.6   BZR_PDB

Control whether to launch a debugger on error.

  • 0 = Standard behavior
  • 1 = Launch debugger

8.4.1.7   BZR_REMOTE_PATH

Path to the Bazaar executable to use when using the bzr+ssh protocol.

See also the bzr_remote_path configuration value.

8.4.1.8   BZR_EDITOR

Path to the editor Bazaar should use for commit messages, etc.

8.4.1.9   BZR_PLUGIN_PATH

The path to the plugins directory that Bazaar should use.

8.4.1.10   BZRPATH

The path where Bazaar should look for shell plugin external commands.

8.4.2   Configuration files

8.4.2.1   Location

Configuration files are located in $HOME/.bazaar on Linux/Unix and C:\Documents and Settings\<username>\Application Data\Bazaar\2.0 on Windows. (You can check the location for your system by using bzr version.)

There are three primary configuration files in this location:

  • bazaar.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 .bzr/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.

8.4.2.2   General format

An ini file has three types of contructs: section headers, section variables and comments.

8.4.2.2.1   Comments

A comment is any line that starts with a "#" (sometimes called a "hash mark", "pound sign" or "number sign"). Comment lines are ignored by Bazaar when parsing ini files.

8.4.2.2.2   Section headers

A section header is a word enclosed in brackets that starts at the begining of a line. A typical section header looks like this:

[DEFAULT]

The only valid section header for bazaar.conf is [DEFAULT], which is case sensitive. The default section provides for setting variables which can be overridden with the branch config file.

For locations.conf, the variables from the section with the longest matching section header are used to the exclusion of other potentially valid section headers. A section header uses the path for the branch as the section header. Some examples include:

[http://mybranches.isp.com/~jdoe/branchdir]
[/home/jdoe/branches/]
8.4.2.2.3   Section variables

A section variable resides within a section. A section variable contains a variable name, an equals sign and a value. For example:

email            = John Doe <jdoe@isp.com>
check_signatures = require
8.4.2.2.4   Variable policies

Variables defined in a section affect the named directory or URL plus any locations they contain. Policies can be used to change how a variable value is interpreted for contained locations. Currently there are three policies available:

none:
the value is interpreted the same for contained locations. This is the default behaviour.
norecurse:
the value is only used for the exact location specified by the section name.
appendpath:
for contained locations, any additional path components are appended to the value.

Policies are specified by keys with names of the form "$var:policy". For example, to define the push location for a tree of branches, the following could be used:

[/top/location]
push_location = sftp://example.com/location
push_location:policy = appendpath

With this configuration, the push location for /top/location/branch1 would be sftp://example.com/location/branch1.

8.4.2.3   The main configuration file, bazaar.conf

bazaar.conf only allows one section called [DEFAULT]. This default section contains the default configuration options for all branches. The default section can be overriden by providing a branch-specific section in locations.conf.

A typical bazaar.conf section often looks like the following:

[DEFAULT]
email             = John Doe <jdoe@isp.com>
editor            = /usr/bin/vim
check_signatures  = check-available
create_signatures = when-required

8.4.2.4   The branch location configuration file, locations.conf

locations.conf allows one to specify overriding settings for a specific branch. The format is almost identical to the default section in bazaar.conf with one significant change: The section header, instead of saying default, will be the path to a branch that you wish to override a value for. The '?' and '*' wildcards are supported:

[/home/jdoe/branches/nethack]
email = Nethack Admin <nethack@nethack.com>

[http://hypothetical.site.com/branches/devel-branch]
create_signatures = always
check_signatures  = always

[http://bazaar-vcs.org/bzr/*]
check_signatures  = require

8.4.2.5   The authentication configuration file, authentication.conf

authentication.conf allows one to specify credentials for remote servers. This can be used for all the supported transports and any part of bzr that requires authentication (smtp for example).

The syntax of the file obeys the same rules as the others except for the variable policies which don't apply.

For more information on the possible uses of the authentication configuration file see Configuring authentication.

8.4.3   Common variable options

8.4.3.1   email

The email address to use when committing a branch. Typically takes the form of:

email = Full Name <account@hostname.tld>

8.4.3.2   editor

The path of the editor that you wish to use if bzr commit is run without a commit message. This setting is trumped by the environment variable BZR_EDITOR, and overrides the VISUAL and EDITOR environment variables.

8.4.3.3   check_signatures

Defines the behavior for signatures.

require
The gnupg signature for revisions must be present and must be valid.
ignore
Do not check gnupg signatures of revisions.
check-available
(default) If gnupg signatures for revisions are present, check them. Bazaar will fail if it finds a bad signature, but will not fail if no signature is present.

8.4.3.4   create_signatures

Defines the behaviour of signing revisions.

always
Sign every new revision that is committed.
when-required
(default) Sign newly committed revisions only when the branch requires signed revisions.
never
Refuse to sign newly committed revisions, even if the branch requires signatures.

8.4.3.5   recurse

Only useful in locations.conf. Defines whether or not the configuration for this section applies to subdirectories:

true
(default) This section applies to subdirectories as well.
false
This section only applies to the branch at this directory and not branches below it.

8.4.3.6   gpg_signing_command

(Default: "gpg"). Which program should be used to sign and check revisions. For example:

gpg_signing_command = /usr/bin/gnpg

8.4.3.7   bzr_remote_path

(Default: "bzr"). The path to the command that should be used to run the smart server for bzr. This value may only be specified in locations.conf, because:

  • it's needed before branch.conf is accessible
  • allowing remote branch.conf files to specify commands would be a security risk

It is overridden by the BZR_REMOTE_PATH environment variable.

8.4.3.8   smtp_server

(Default: "localhost"). SMTP server to use when Bazaar needs to send email, eg. with merge-directive --mail-to, or the bzr-email plugin.

8.4.3.9   smtp_username, smtp_password

User and password to authenticate to the SMTP server. If smtp_username is set, and smtp_password is not, Bazaar will prompt for a password. These settings are only needed if the SMTP server requires authentication to send mail.

8.4.3.10   mail_client

A mail client to use for sending merge requests. By default, bzr will try to use mapi on Windows. On other platforms, it will try xdg-email. If either of these fails, it will fall back to editor.

Supported values for specific clients:

evolution:Use Evolution.
kmail:Use KMail.
mutt:Use Mutt.
thunderbird:Use Mozilla Thunderbird or Icedove. For Thunderbird/Icedove 1.5, this works around some bugs that xdg-email doesn't handle.

Supported generic values are:

default:See above.
editor:Use your editor to compose the merge request. This also uses your commit id, (see bzr whoami), smtp_server and (optionally) smtp_username and smtp_password.
mapi:Use your preferred e-mail client on Windows.
xdg-email:Use xdg-email to run your preferred mail program

8.4.3.11   submit_branch

The branch you intend to submit your current work to. This is automatically set by bzr send, and is also used by the submit: revision spec. This should usually be set on a per-branch or per-location basis.

8.4.3.12   public_branch

A publically-accessible version of this branch (implying that this version is not publically-accessible). Used (and set) by bzr send.

8.4.4   Branch type specific options

These options apply only to branches that use the dirstate-tags or later format. They are usually set in .bzr/branch/branch.conf automatically, but may be manually set in locations.conf or bazaar.conf.

8.4.4.1   append_revisions_only

If set to "True" then revisions can only be appended to the log, not removed. A branch with this setting enabled can only pull from another branch if the other branch's log is a longer version of its own. This is normally set by bzr init --append-revisions-only.

8.4.4.2   parent_location

If present, the location of the default branch for pull or merge. This option is normally set by pull --remember or merge --remember.

8.4.4.3   push_location

If present, the location of the default branch for push. This option is normally set by push --remember.

8.4.4.4   bound_location

The location that commits should go to when acting as a checkout. This option is normally set by bind.

8.4.4.5   bound

If set to "True", the branch should act as a checkout, and push each commit to the bound_location. This option is normally set by bind/unbind.

8.5   Configuring email

8.5.1   Why set up an email address with Bazaar?

Bazaar stores the specified email address in revisions when they're created so that people can tell who commited which revisions. The email addresses are not verified, therefore they could be bogus, so you have to trust the people involved in your project. Additionally, the email address in a revision gives others a way to contact the author of a revision for credit and/or blame. :)

8.5.2   How to set up your email address

Bazaar will try to guess an email address based on your username and the hostname if none is set. This will probably not be what you want, so three ways exist to tell Bazaar what email to use:

You can set your email in one of several configuration files. Like other configuration values, you can set it in bazaar.conf as a general setting. If you want to override the value for a particular branch, or set of branches, you can use locations.conf. .bzr/branch/branch.conf will also work, but will cause all commits to that branch to use the same email address, even if someone else does them.

The order of precedence is

  1. If the BZR_EMAIL environment variable is set.
  2. If an email is set for your current branch in the locations.conf file.
  3. If an email is set four your current branch in the .bzr/branch/branch.conf file.
  4. If an email is set in the bazaar.conf default configuration file.
  5. If the EMAIL environment variable is set.
  6. Bazaar will try to guess based on your username and the hostname.

To check on what Bazaar thinks your current email is, use the whoami ("who am i?") command:

% bzr whoami
Joe Cool <joe@example.com>

8.5.3   Setting email via the 'whoami' command

You can use the whoami command to set your email globally:

% bzr whoami "Joe Cool <joe@example.com>"

or only for the current branch:

% bzr whoami --branch "Joe Cool <joe@example.com>"

These modify your global bazaar.conf or branch branch.conf file, respectively.

8.5.4   Setting email via default configuration file

To use the default ini file, create or edit the bazaar.conf file (in ~/.bazaar/ on Linix and in %APPDATA%\bazaar\2.0\ in Windows) and set an email address as shown below. Please note that the word DEFAULT is case sensitive, and must be in upper-case.

[DEFAULT]
email=Your Name <name@isp.com>

For more information on the ini file format, see Configuration reference.

8.5.5   Setting email on a per-branch basis

The second approach is to set email on a branch by branch basis by using the locations.conf configuration file like this:

[/some/branch/location]
email=Your Name <name@other-isp.com>

This will set your email address in the branch at /some/branch/location, overriding the default specified in the bazaar.conf above.

8.5.6   Setting email via environment variable

The final method Bazaar will use is checking for the BZR_EMAIL and EMAIL environment variables. Generally, you would use this method to override the email in a script context. If you would like to set a general default, then please see the ini methods above.

8.5.7   Concerns about spam

Some people want to avoid sharing their email address so as not to get spam. Bazaar will never disclose your email address, unless you publish a branch or changeset in a public location. It's recommended that you do use a real address, so that people can contact you about your work, but it's not required. You can use an address which is obfuscated, which bounces, or which goes through an anti-spam service such as spamgourmet.com.

8.6   Configuring authentication

8.6.1   Intent

Many different authentication policies can be described in the authentication.conf file but a particular user should need only a few definitions to cover his needs without having to specify a user and a password for every branch he uses.

The definitions found in this file are used to find the credentials to use for a given url. The same credentials can generally be used for as many branches as possible by grouping their declaration around the remote servers that need them. It's even possible to declare credentials that will be used by different servers.

The intent is to make this file as small as possible to minimize maintenance.

Once the relevant credentials are declared in this file you may use branch urls without embedding passwords (security hazard) or even users (enabling sharing of your urls with others).

Instead of using:

bzr branch ftp://joe:secret@host.com/path/to/my/branch

you simply use:

bzr branch ftp://host.com/path/to/my/branch

provided you have created the following authentication.conf file:

[myprojects]
scheme=ftp
host=host.com
user=joe
password=secret

8.6.2   Authentication definitions

There are two kinds of authentication used by the various schemes supported by bzr:

  1. user and password

FTP and SFTP needs a (user, password) to authenticate against a host (SFTP can use ssh keys too, but we don't talk about that here as ssh agents provide a better solution).

  1. user, realm and password

HTTP and HTTPS needs a (user, realm, password) to authenticate against a host. But, by using .htaccess files, for example, it is possible to define several (user, realm, password) for a given host. So what is really needed is (user, password, host, path). The realm is not taken into account in the defitions, but will displayed if bzr prompts you for a password.

HTTP proxy can be handled as HTTP (or HTTPS) by explicitely specifying the appropriate port.

To take all schemes into account, the password will be deduced from a set of authentication definitions (scheme, host, port, path, user, password).

  • scheme: can be empty (meaning the rest of the definition can be used for any scheme), SFTP and bzr+ssh should not be used here, ssh should be used instead since this is the real scheme regarding authentication,
  • host: can be empty (to act as a default for any host),
  • port can be empty (useful when an host provides several servers for the same scheme), only numerical values are allowed, this should be used only when the server uses a port different than the scheme standard port,
  • path: can be empty (FTP or SFTP will never user it),
  • user: can be empty (bzr will defaults to python's getpass.get_user()),
  • password: can be empty if you prefer to always be prompted for your password.

Multiple definitions can be provided and, for a given URL, bzr will select a (user [, password]) based on the following rules :

  1. the first match wins,
  2. empty fields match everything,
  3. scheme matches even if decorators are used in the requested URL,
  4. host matches exactly or act as a domain if it starts with '.' (project.bzr.sf.net will match .bzr.sf.net but projectbzr.sf.net will not match bzr.sf.net).
  5. port matches if included in the requested URL (exact matches only)
  6. path matches if included in the requested URL (and by rule #2 above, empty paths will match any provided path).

8.6.3   File format

The general rules for configuration files apply except for the variable policies.

Each section describes an authentication definition.

The section name is an arbitrary string, only the DEFAULT value is reserved and should appear as the last section.

Each section should define:

  • user: the login to be used,

Each section could define:

  • host: the remote server,
  • port: the port the server is listening,
  • path: the branch location,
  • password: the password.

8.6.4   Examples

8.6.4.1   Personal projects hosted outside

All connections are done with the same user (the remote one for which the default bzr one is not appropriate) and the password is always prompted with some exceptions:

# Pet projects on hobby.net
[hobby]
host=r.hobby.net
user=jim
password=obvious1234

# Home server
[home]
scheme=https
host=home.net
user=joe
password=1essobV10us

[DEFAULT]
# Our local user is barbaz, on all remote sites we're known as foobar
user=foobar

8.6.4.2   Source hosting provider

In the shp.net (fictious) domain, each project has its own site:

[shpnet domain]
# we use sftp, but ssh is the scheme used for authentication
scheme=ssh
# The leading '.' ensures that 'shp.net' alone doesn't match
host=.shp.net
user=joe
password=precious

8.6.4.3   HTTPS, SFTP servers and their proxy

At company.com, the server hosting released and integration code is behind a proxy, the two servers use different authentication policies:

[reference code]
scheme=https
host=dev.company.com
path=/dev
user=user1
password=pass1

# development branches on dev server
[dev]
scheme=ssh # bzr+ssh and sftp are available here
host=dev.company.com
path=/dev/integration
user=user2
password=pass2

# proxy
[proxy]
scheme=http
host=proxy.company.com
port=3128
user=proxyuser1
password=proxypass1

8.6.5   Planned enhancements

The following are not yet implemented but planned as parts of a work in progress:

  • add a password_encoding field allowing:
    • storing the passwords in various obfuscating encodings (base64 for one),
    • delegate password storage to plugins (.netrc for example).
  • update the credentials when the user is prompted for user or password,
  • add a verify_certificates field for HTTPS.

The password_encoding and verify_certificates fields are recognized but ignored in the actual implementation.

8.7   Serving Bazaar with FastCGI

This feature is EXPERIMENTAL and is NOT SECURE. It will allow access to arbitrary files on your server.

This document describes one way to set up a Bazaar HTTP smart server, using Apache 2.0 and FastCGI or mod_python.

For more information on the smart server, and other ways to configure it see the main smart server documentation.

8.7.1   Example

You have a webserver already publishing /srv/example.com/www/code as http://example.com/code/... with plain HTTP. It contains bzr branches and directories like /srv/example.com/www/code/branch-one and /srv/example.com/www/code/my-repo/branch-two. You want to provide read-only smart server access to these directories in addition to the existing HTTP access.

8.7.2   Configuring Apache 2.0

8.7.2.1   FastCGI

First, configure mod_fastcgi, e.g. by adding lines like these to your httpd.conf:

LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so
FastCgiIpcDir /var/lib/apache2/fastcgi

In our example, we're already serving /srv/example.com/www/code at http://example.com/code, so our existing Apache configuration would look like:

Alias /code /srv/example.com/www/code
<Directory /srv/example.com/www/code>
    Options Indexes
    # ...
</Directory>

We need to change it to handle all requests for URLs ending in .bzr/smart. It will look like:

Alias /code /srv/example.com/www/code
<Directory /srv/example.com/www/code>
    Options Indexes FollowSymLinks
    RewriteEngine On
    RewriteBase /code
    RewriteRule ^(.*/|)\.bzr/smart$ /srv/example.com/scripts/bzr-smart.fcgi
</Directory>

# bzr-smart.fcgi isn't under the DocumentRoot, so Alias it into the URL
# namespace so it can be executed.
Alias /srv/example.com/scripts/bzr-smart.fcgi /srv/example.com/scripts/bzr-smart.fcgi
<Directory /srv/example.com/scripts>
    Options ExecCGI
    <Files bzr-smart.fcgi>
        SetHandler fastcgi-script
    </Files>
</Directory>

This instructs Apache to hand requests for any URL ending with /.bzr/smart inside /code to a Bazaar smart server via FastCGI.

Refer to the mod_rewrite and mod_fastcgi documentation for further information.

8.7.2.2   mod_python

First, configure mod_python, e.g. by adding lines like these to your httpd.conf:

LoadModule python_module /usr/lib/apache2/modules/mod_python.so

Define the rewrite rules with mod_rewrite the same way as for FastCGI, except change:

RewriteRule ^(.*/|)\.bzr/smart$ /srv/example.com/scripts/bzr-smart.fcgi

to:

RewriteRule ^(.*/|)\.bzr/smart$ /srv/example.com/scripts/bzr-smart.py

Like with mod_fastcgi, we also define how our script is to be handled:

Alias /srv/example.com/scripts/bzr-smart.py /srv/example.com/scripts/bzr-smart.py
<Directory /srv/example.com/scripts>
    <Files bzr-smart.py>
        PythonPath "sys.path+['/srv/example.com/scripts']"
        AddHandler python-program .py
        PythonHandler bzr-smart::handler
    </Files>
</Directory>

This instructs Apache to hand requests for any URL ending with /.bzr/smart inside /code to a Bazaar smart server via mod_python.

NOTE: If you don't have bzrlib in your PATH, you will be need to change the following line:

PythonPath "sys.path+['/srv/example.com/scripts']"

To:

PythonPath "['/path/to/bzr']+sys.path+['/srv/example.com/scripts']"

Refer to the mod_python documentation for further information.

8.7.3   Configuring Bazaar

8.7.3.1   FastCGI

We've configured Apache to run the smart server at /srv/example.com/scripts/bzr-smart.fcgi. This is just a simple script we need to write to configure a smart server, and glue it to the FastCGI gateway. Here's what it looks like:

import fcgi
from bzrlib.transport.http import wsgi

smart_server_app = wsgi.make_app(
    root='/srv/example.com/code',
    prefix='/code/',
    path_var='REQUEST_URI',
    readonly=True)

fcgi.WSGIServer(smart_server_app).run()

The fcgi module can be found at http://svn.saddi.com/py-lib/trunk/fcgi.py. It is part of flup.

8.7.3.2   mod_python

We've configured Apache to run the smart server at /srv/example.com/scripts/bzr-smart.py. This is just a simple script we need to write to configure a smart server, and glue it to the mod_python gateway. Here's what it looks like:

import modpywsgi
from bzrlib.transport.http import wsgi

smart_server_app = wsgi.make_app(
    root='/srv/example.com/code',
    prefix='/code/',
    path_var='REQUEST_URI',
    readonly=True)

def handler(request):
    """Handle a single request."""
    wsgi_server = modpywsgi.WSGIServer(smart_server_app)
    return wsgi_server.run(request)

The modpywsgi module can be found at http://trac.pocoo.org/wiki/ModPyWsgi. It is part of pocoo. You sould make sure you place modpywsgi.py in the same directory as bzr-smart.py (ie. /srv/example.com/scripts/).

8.7.4   Clients

Now you can use bzr+http:// URLs, e.g.:

bzr log bzr+http://example.com/code/my-branch

Plain HTTP access should continue to work:

bzr log http://example.com/code/my-branch

8.7.5   Advanced configuration

Because the Bazaar HTTP smart server is a WSGI application, it can be used with any 3rd-party WSGI middleware or server that conforms the WSGI standard. The only requirements are:

  • to construct a SmartWSGIApp, you need to specify a root transport that it will serve.
  • each request's environ dict must have a 'bzrlib.relpath' variable set.

The make_app helper used in the example constructs a SmartWSGIApp with a transport based on the root path given to it, and calculates the 'bzrlib.relpath` for each request based on the prefix and path_var arguments. In the example above, it will take the 'REQUEST_URI' (which is set by Apache), strip the '/code/' prefix and the '/.bzr/smart' suffix, and set that as the 'bzrlib.relpath', so that a request for '/code/foo/bar/.bzr/smart' will result in a 'bzrlib.relpath' of 'foo/bzr'.

It's possible to configure a smart server for a non-local transport, or that does arbitrary path translations, etc, by constructing a SmartWSGIApp directly. Refer to the docstrings of bzrlib.transport.http.wsgi and the WSGI standard for further information.

8.7.5.1   Pushing over bzr+http://

It is possible to allow pushing data over the http smart server. The easiest way to do this, is to just supply readonly=False to the wsgi.make_app() call. But be careful, because the smart protocol does not contain any Authentication. So if you enable write support, you will want to restrict access to .bzr/smart URLs to restrict who can actually write data on your system. At this time, it is not possible to allow some people to have read-only access and others to have read-write access to the same urls. Because at the HTTP layer (which is doing the Authenticating), everything is just a POST request. However, it would certainly be possible to have HTTPS require authentication and use a writable server, and plain HTTP allow read-only access.

8.8   Writing a plugin

8.8.1   Introduction

Plugins are very similar to bzr core functionality. They can import anything in bzrlib. A plugin may simply override standard functionality, but most plugins supply new commands.

8.8.2   Creating a new command

To create a command, make a new object that derives from bzrlib.commands.Command, and name it cmd_foo, where foo is the name of your command. If you create a command whose name contains an underscore, it will appear in the UI with the underscore turned into a hyphen. For example, cmd_baz_import will appear as baz-import. For examples of how to write commands, please see builtins.py.

Once you've created a command you must register the command with bzrlib.commands.register_command(cmd_foo). You must register the command when your file is imported, otherwise bzr will not see it.

8.8.3   Plugin searching rules

Bzr will scan bzrlib/plugins and ~/.bazaar/plugins for plugins by default. You can override this with BZR_PLUGIN_PATH. Plugins may be either modules or packages. If your plugin is a single file, you can structure it as a module. If it has multiple files, or if you want to distribute it as a bzr branch, you should structure it as a package, i.e. a directory with an __init__.py file.

8.8.4   More information

Please feel free to contribute your plugin to BzrTools, if you think it would be useful to other people.

See the Bazaar Developer Guide for details on Bazaar's development guidelines and policies.