By now the benefits (and negatives) concerning DRCS systems has been
talked about alot. Version control applications like git, bazaar, mercurial,
and darcs, to name a few have all been getting much attention.
For me, the lure is being able to work on applications and maintain sensible
revision history while working offline. Also working in a mode where I can toy
in a local (non-public) branch and toss it away if it’s no good helps. Enter
Bazaar.
Background Info
A little bit of info is required before we get underway.
- bzr checkouts
- Like with standard CRCS systems such as Subversion, a bzr checkout
functions as a real-time mirror of the linked repository location. So
once you’ve done a checkout, making changes and committing them is
automatically performed to the linked repo. Working with checkouts
directly is not something often done, but merging changes from other
branches using a checkout is quite helpful.
- bzr branches
- Unlike with standard CRCS systems, in a DRCS like bzr branching is
encouraged. All bug fixes, feature enhancements, etc, should be done on
a separate branch and ultimately merged back to trunk when complete. bzr
makes merging back by remembering when branches were merged last so
re-merging won’t have any ill effects. Branches also support pushing and
pulling allowing one branch to mirror another.
Getting Started
We’ll be performing our bzr tactics against a the publically available
subversion repository of ClueBin. I’m using bzr-svn 0.4.10, bzr 1.5,
svn 1.5 for all of this.
Begin by creating a local bzr repo for all ClueBin work (this speeds
up bzr work and saves space) and make a checkout of the real svn trunks
of the projects we care about.
$ bzr init-repo --rich-root-pack repo # rich-root-pack required for svn stuff
$ cd repo
repo$ bzr co https://dev.serverzen.com/svn/cluemapper/ClueBin/trunk ClueBin-trunk
repo$ cd ..
$
Before we go any further, lets setup the python environment for actually
running ClueBin. We use virtualenv (1.1) to setup the sandbox. Setting
up virtualenv is beyond the scope of these writings.
$ virtualenv-py2.5 cluebin-app
$ source cluebin-app/bin/activate
(cluebin-app) $ cd repo
(cluebin-app) repo$ cd ClueBin-trunk
(cluebin-app) repo/ClueBin-trunk$ python setup.py develop
(cluebin-app) repo/ClueBin-trunk$ cd ..
(cluebin-app) repo$
Our First Feature Branch
Now that we have an environment setup with the trunks of all the projects
activated, we want to branch for feature work.
(cluebin-app) repo$ bzr branch ClueBin-trunk ClueBin-purple-monster
(cluebin-app) repo$ cd ClueBin-purple-monster
(cluebin-app) repo/ClueBin-purple-monster$ python setup.py develop
At this point you make all of your changes, and do commits as you normally would
(I recommend small isolated committing myself). Once you have completed your
work for today, you should decide what you want to do with your branch. Is
this branch something to be tossed away because you don’t want it? Then just
remove it. Is this branch something you want to keep working on but you’re
not done yet? If so, I suggest you mirror your branch back to the remote svn
repo so that the changes aren’t just left on your own hard drive. Due to
limitations in bzr itself, to make initial push back into svn (that auto-creates
a new folder in svn) you have to use svn-push instead of regular push.
(cluebin-app) repo/ClueBin-purple-monster$ bzr svn-push https://dev.serverzen.com/svn/cluemapper/ClueBin/branches/purple-monster
Now that your branch has been mirrored you can work on your local branch,
make more changes, and finally bzr push again when you’re done (this time
no url needs to be specified because bzr remembers the last one).
(cluebin-app) repo/ClueBin-purple-monster$ bzr push
If you make changes to that svn branch on some other workstation and want
to update your local branch, this is where you would use pull. But be warned
this only works if your local branch has no additional changes that were not
pushed back to the remote svn mirror branch.
(cluebin-app) repo/ClueBin-purple-monster$ bzr pull
If by some chance you (or someone else) had committed changes to both the
local branch and the remove svn mirror branch, you would need to merge. But
don’t fret the merge, this is where DVCS’ shine … they remember what was
merged!
Merging to Trunk
A more common case of merging is when you’re ready to publish your purple
monster changes to trunk for everyone else to see.
First off, you might want to see what changes were done to trunk that you
don’t yet have in your purple monster branch. And for that, you want
to update your checkout of trunk too.
(cluebin-app) repo/ClueBin-purple-monster$ bzr update
(cluebin-app) repo/ClueBin-purple-monster$ bzr missing ../ClueBin-trunk
You’ll get a list of revisions that haven’t yet been merged into your
purple monster branch. If everything looks good, merge them in.
(cluebin-app) repo/ClueBin-purple-monster$ bzr merge ../ClueBin-trunk
Of course you’ll need to commit the changes from the merge (nothing is
ever auto-committed).
(cluebin-app) repo/ClueBin-purple-monster$ bzr commit
Now that you know your branch is current with trunk, it’s time to merge your
branch changes back to trunk. Remember that since the trunk branch is an
actual checkout of trunk, committing directly to that branch will propagate
changes right to svn.
(cluebin-app) repo/ClueBin-purple-monster$ cd ../Cluebin-trunk
(cluebin-app) repo/ClueBin-trunk$ bzr merge ../ClueBin-purple-monster
And assuming there are no conflicts to deal with, you can go ahead and commit.
(conflicts are handled the same way as with svn or cvs)
(cluebin-app) repo/ClueBin-trunk$ bzr commit
And voila, trunk and purple-monster branch are now synced with one another.