Bazaar-NG usage notes

We want to set up a central repository, where several people contribute to a project and backups are easy, but allow complete local development when one is off-line. These are notes that help me remember how/what to do.

Installation

Links to sources and precompiled binaries are available from the Bazaar-NG site. As of today (2006-05-17) I find no binaries of the current version (0.8.2) for Debian. Thus, download the tar.gz, and uncompress, and do as root:

python2.4 setup.py install

If you only want to install for your user do:

python2.4 setup.py install --home /home/myuser

You'll also probably want to install the plugins bzrtools and bzrk (available also as deb packages or obtained via bzr branch or from sources), as well as difftools, show-paths and gannotate.

For the current bzr you can obtain the bzrtools source, the bzrk sources, difftools sources. (For instance, issuing the command "wget -nd http://people.ubuntu.com/~jbailey/snapshot/bzr/bzrtools_0.8" will leave the tar.gz in the current directory).

To get show-paths and gannotate:

bzr branch http://bzr.onembedding.com/bzr.win/plugins/show_paths/
bzr branch http://panoramicfeedback.com/opensource/bzr/gannotate/

To get latest difftools do:

bzr branch http://mysite.verizon.net/sward.dev/projects/bzr_difftools/

After decompressing or branching, move the directories (e.g., bzrtools) to ~/.bazaar/plugins or install system wide (python2.4 setup.py install). For those plugins that do not have a setup.py, just copy (i.e., do "cp -a") the directory under ~/.bazaar/plugins (for you user) or /usr/lib/python2.4/site-packages/bzrlib/plugins/ (system wide).

If using Debian GNU/Linux you will probably need to do "apt-get install python2.4-paramiko python2.4-cairo python2.4-crypto python2.4-gtk2 python2.4-numeric". (Some of these are needed not for bzr itself but for the plugins).

Workflow

(Most of this based on an email from Robert Collins on 2006-05-05 answering my questions to the bazaar email list).

We assume we have some code in a "central repository" in a machine remote.server, in directory /Disk2/bzr-test-repo. Several people are working on that project. All of them will have a local repository on their machines (which, among other things, will allow them to use the revision control system fully even if disconnected from remote.server).

You work on your local machine, commit those changes to your local branch and, at the end of the day, or at certain important milestones, you save those changes back to the central repository (and thus make your newly edited code available to the rest of the people in the project).

You have permissions to access this machine and directory via ssh. ssh and sftp server are running in remote.server and you have the corresponding clients in your local machine.

"If you perform a checkout of this branch to your local machine, bzr will understand that this is a shared branch, and let you know when other people have done edits, and allow you to reconcile them locally."

(...) commit will commit directly to [the central repository] and is multi-user safe. If another user has committed before you did, you can just do a 'bzr update' and then do the commit again."

bazaar.conf for identification

In your local machine:

mkdir ~/.bazaar
cd .bazaar
echo "email = MyName <myaddress@wherever.org>" > bazaar.conf

Create your local repository

We assume a repository with branch(es) already exists. On your machine do (based on R. Collins' email):

# Create a checkout of the shared branch
$ bzr checkout sftp://myself@remote.server/Disk2/bzr-test-repo boundbranch
$
# Create a branch I'm going to work on
$ bzr branch boundbranch localbranch2

Edit and periodically commit changes

Edit the files with your favourite editor

  • Check changes:

    bzr status
    bzr diff
    
  • Commit:

    bzr commit
    

commit can be used also to commit only some specific file(s)

  • How we have changed our repository:

    bzr log
    bzr log --verbose
    bzr annotate onefile
    

    In newer versions, or with some pluggins, other diffs (xxdiff, tkdiff, mgdiff, kompare, etc) might be available.

  • Other info:

    bzr info
    

Deleting, removing, renaming files

  • Files and directories can be moved and renamed and bzr keeps track of it: bzr mv
  • To take a file out of version control (does NOT delete it): bzr remove
  • To delete a file do rm as usual. bzr revert can restore the file.

Undoing changes

  • Before commit: bzr revert, bzr shelve (bzr unshelve)
  • After commit: bzr uncommit
  • Getting a file from a previous revison: bzr cat

Graphical interfaces (navigating revisions, etc)

The plugins gannotate and bzrk (provides viz) are very nice:

bzr gannotate FILENAME
bzr viz

Sending changes back to the remote repository

(Again, from R. Collins' email):

      # now we do a merge and publish it in the shared branch
      $ cd ../boundbranch
      # pickup any new work in the shared repository
      $ bzr update
      # now merge the changes you did in localbranch2
      $ bzr merge ../localbranch2
      # and commit them (after resolving any conflicts)
      $ bzr commit -m 'Merge in feature-X'.


"That last commit will commit directly to
sftp://remote.server/Disk2/bzr-test-repo and is multi-user safe. If another
user has committed before you did, you can just do a 'bzr update' and
then do the commit again."

Resolving conflicts

Conflicts can arise when we merge things back to the server, if bzr can not reconcile changes made by several people. See The Independant for examples of merging. See below, under Stable and development branches: fixing the same bug and dealing with conflicts for a couple of long examples including showing diffs, etc.

Summary of the remote and local repositories logic

What we did above was:

  1. Create a local repository (boundbranch) that is bound to a remote one.

  2. Create a branch from the local repository to a second local repository (localbranch2) that is no longer bound to the remote one.

  3. Do our coding and commiting in the localbranch2

  4. When we want to send changes back to the remote server we:

    4.1. Get latest changes from the remote repository (bzr update)

    4.2. Merge the changes we made and the (possible) chages anybody else made.

    4.3. From boundbranch commit our changes: recall boundbranch is bound to the remove server.

Notice that some of the above operations could be carried out "by hand" and using bzr push. See email from Matthieu Moy on 2006-05-05 in the bazaar-ng list.

A different approach to using repositories

(This follows an answer posted by Erik B�fors on 2006-05-05 to the bazaar-ng list).

Instead of creating localbranch2, which is a branch of a local repository that is bound to the remote, we can just work on boundrepository directly. The main difference is that the commits to boundrepository will need to use bzr commit --local. Once we want to commit to the remote we just do bzr commit. (It is a good idea to do bzr update first, then bzr status and then bzr commit; the update gets the possible changes from others, the status shows what has happened and possible conflicts).

So this option uses one fewer local repository. But we must remember to use --local for each local commit. (We could also set up an alias, which is a feature available in bzr 0.8).

Stable and development branches: fixing the same bug and dealing with conflicts

An extremely useful feature of using version control with bzr (and some other systems) is that, if we fix a bug in one of our "branches", we can immediately incorporate that bug fix into another branch without any need for editing lots of files. This feature is particularly useful if we have a development branch and a stable branch of the same program. A bug can be fixed in one, and the changes merged into the other. (We will use kdiff3 here for dealing with conflicts).

###################################################
##########                            #############
##########    Cherry-picking works    #############
##########                            #############
###################################################

## create a stable branch
mkdir stableA
cd stableA
## create a file, and add enough stuff to it (e.g., .emacs),
## so that a few changes do not screw up diffs and related
echo -e line 1\\n line 2 \\n line 3 \\n line 4 > tmp
cat tmp ../.emacs > file1
bzr init
bzr add file1
bzr commit -m 'initial commit of file1'
cd ..
## branch to devel
bzr branch stableA develA

## do something in stable branch
cd stableA
sed -i 's/line 1/line 1 in file 1/' file1
bzr diff
bzr commit -m 'add stuff to line 1'
echo 'a new first line' | cat - file1 > tmp; mv tmp file1
bzr commit -m 'add new first line'


## do something else in devel
cd ..
cd develA
sed -i 's/line 2/line 2 in devel/' file1
bzr diff
bzr commit -m 'add stuff to line 2 in file devel'
sed -i 's/line 4/line 4 in devel/' file1
bzr diff
bzr commit -m 'add stuff to line 4 in file devel'
echo 'last line' | cat file1 - > ftmp; mv ftmp file1
bzr commit -m 'added last line in devel'


## show diffs using kdiff3
bzr diff -r1..4 file1 --using kdiff3

## Now the development and stable branches are different
## Cherrypick last change in devel?

kdiff3 file1 ../stableA/file1
bzr log
cd ../stableA
bzr merge -r 3..4 ../develA
bzr diff
bzr commit -m 'Added the merge from devel'

## try again
bzr merge -r 1..2 ../develA ## Humm, a conflict
## we could solve things, and do bzr resolve.
## save as file1.solved

kdiff3 file1.BASE file1.OTHER file1.THIS
cp file1.solved file1
bzr resolved file1
bzr commit -m 'the conflicting change'


## how does gannotate display changes?
bzr gannotate file1

##
bzr viz

## of course, viz shows a different story
## depending on where you are; it shows a branch
cd ../develA
bzr viz

We could do similar things if both devel and stable came from a common trunk. But notice we need a minumum similarity so that bzr can correctly identify what should be merged. Otherwise, things will fail. For example:

###################################################
##########                            #############
##########   Cherry-picking doesn't   #############
##########           work             #############
##########                            #############
###################################################

mkdir trunkB
cd trunkB
echo -e line 1\\n line 2 \\n line 3 \\n line 4 > file1
bzr init
bzr add file1
bzr commit -m 'initial commit of file1'
cd ..
bzr branch trunkB stableB
bzr branch trunkB develB

## do something in stable branch
cd stableB
sed -i 's/line 1/line 1 in file 1/' file1
bzr diff
bzr commit -m 'add stuff to line 1'


## do something else in develB
cd ..
cd develB
sed -i 's/line 2/line 2 in file 1/' file1
bzr diff
bzr commit -m 'add stuff to line 2 in file devel'
sed -i 's/line 4/line 4 in file 1/' file1
bzr diff
bzr commit -m 'add stuff to line 4 in file devel'
echo 'fifth line' | cat file1 - > ftmp; mv ftmp file1
bzr commit -m 'added line 5 in devel'

## Now the development and stable branches are different
## Cherrypick last change in devel?
bzr log
cd ../stableB
bzr merge -r 3..4 ../develB ## nope, won't work

Place a local directory under version control

Many projects we work on are just single-person projects that we only keep on our hard drive (e.g., a LaTeX file for a presentation). It is very handy to have revision control here.

cd ~/somedirectory
bzr init
bzr add *

We might want to use .brzignore file to specify files to ignore (e.g., '.so', '.pyc', etc)

Other relevant documentation

If you are new to bzr, you should definitely start by working through the Quick Hacking with Bazaar (the five minute introduction to Bazaar) and then the Introduction to Bzr.

A few very helpful documents that relate to issues covered in this document:

Date:2006-05-19 (4th revision)
Author:Ramon Diaz-Uriarte <rdiaz at ligarto dot org>