Bazaar
Also available in presentation mode…
Why would I want a Version Control System (VCS)?
- Code backup
- VCS can generally handle small lapses in judgment where you simply want to revert to an older version, or see what you had before. For a full backup affect you really want to have an up-to-date repository on a remote system AND the remote system should be on a reasonable backup schedule.
- Ability to call for a "do-over" ( with benefits )
- You can try something, and if it doesn't work out you can revert to any checked in copy from the past. That's fairly powerful in itself, but wait there's more. You have the ability to revert the entire working tree or just a file or two. Most VCSs can also show you, or even apply, all the code patches done between a sequence of revisions. Now you can revert AND cherry pick all good stuff.
- Documents code evolution
- If version control is a new concept to you, you might not fully appreciate the importance of committing transactions at an appropriate granularity. Commits should be done at a granularity that keeps track of enhancements and new functionality. This can help document progress and allows good isolation of functionality into clear chunks of code/effort.
- Synchronization between multiple locations
- Normally it's extremely frowned upon to commit broken code to a VCS. For shared Centralized servers this is truly a sin. A really nice feature of Distributed VCS is that you can bend a the rules a little and update your own repo as needed. If you share YOUR repo between a desktop and laptop (or work and home) you might want to commit changes at "convenient" points, even if not generally deemed appropriate.
- Not just for Source Code anymore!
- Also consider non-source code implementations. Examples might be complex systems with configuration files and/or varying content. Web-server instances are non-code trees that are commonly put under Version Control. The base of the SLUG Plone site is now under Bazaar Version Control. A side benefit of this is that it's easy to create a "preview" server, or another instance to test an upgrade on.
- Allows deeper cleaning of your source.
- One shock to me, was that I could get rid of commented code I left around "just in case I ever need that again". If you commit with a reasonable granularity and change messages, it should be easy to locate older code when needed. When you have an easy option of getting something back you clean more. This tends to snowball resulting in much nicer looking code as well as a reduced tendency put off Refactoring rough sections.
- Collaborative benefits
- It would be nearly impossible to collaborate more than just superficially without a VCS. You can release archived source and accept patches via email, but it doesn't scale. In fact most of us first see VCS when we want to use somebody's source, or we are forced by employers to work together on a project.
The main reasons I like Bazaar better than Mercurial and GIT
- Well done documentation and internal "bzr help"
- Consistently clean interface
- Automatically edits config files. (eg. "bzr whoami" & "bzr ignore")
- Usage model that allows Centralized VCS ("bzr checkout --lightweight")
- All platform support (Unix, Windows, Mac)
- Nearly all pure Python.
- Slowest of them all, but still fast enough.
- Seems to have a clear Plugin support and feature deprecation.
GIT is blazingly fast. It's also extremely complex to use. It's non-Unix support is arguably not as good as the other two. Part of the support problem is that GIT is written in A LOT of languages. If speed is the only concern then GIT wins.
I find Mercurial to be nearly identical to Bazaar. The two match almost almost perfectly feature for feature. Mercurial has a speed advantage. The Merge functionality of Bazaar is much simpler. Bazaar doesn't make you edit config files. Bazaar is unique in that it has a usage model ("bzr checkout --lightweight") that allows for a Centralized VCS.
Bazaar seems to have taken the time to find the simplest way to handle things, made it as user friendly as possible, and documented it well. In my opinion that is a great methodology to build a project on. I'm willing to trade off a little speed to achieve those goals. A clean design also makes it easier to port, resulting in good support on all platforms. Obviously Python helps make Mercurial and Bazaar more portable.
Bazaar Version Control System (VCS)
The Bazaar homepage (http://bazaar-vcs.org)
- large icons across the top, allow quick access for
- Documentation
- Downloads
The homepage is a good example of the clean design of Bazaar in general. It's simple and yet effectively supplies ones needs. Downloads are easily located, as well as good documentation and tutorials.
Other reviews I used to build my own opinions
Install
Full support exists for most platforms.
- Fedora Linux (as root):
yum -y install bzr - Windows & Macintosh -- Download the appropriate installable package from http://bazaar-vcs.org
Getting help
- Short list of commands:
bzr help
This help list is purposefully short. In comparison to Mercurial this not very long or intimidating when you first look at it. It's also NOT complete. See the next two commands for the full listings. Note that the following two commands are actually in the short list from "bzr help", it's just you might not notice them if I didn't call attention to them.
- Full list of commands:
bzr help commands - Full list of topics:
bzr help topics
Further help might require the Website Documentation and Tutorials.
Do not rule out experimentation with /tmp/ based Bazaar VCS Repos, often this yields quick answers to your exact question. It also builds confidence without the risk involved in working with your real data. If testing something that's only possible to do with real data just "Branch" your real code into a /tmp/ test VCS.
Setup
- Who are you?:
bzr whoami "Jon E. Dough <jon@example.org>"
At this point in a Mercurial setup you would be asked to edit configuration files in your home directory. This approach seems a lot friendlier, and I'm a Unix user, I can only imagine how scary that must be for Win & Mac users.
Creating a new project
Now navigate to some directory tree you want to have managed by Bazaar. The Initialization step must done done at the base of the source area. The other commands can occur in any sub-directories.
- Navigate to the root of your source tree and initialize it:
cd /tmp/project bzr init
All the "bzr init" command does is create a "./.bzr" directory.
For safely lets not include any ".svn" info that might exist. It would be a bad thing to muck with the Subversion (.svn) info for an active project.
- To ignore all ".svn" files:
bzr ignore .svn
Here is another place where Mercurial would have you editing config files. In Bazaar those files do exist, but you're also given these handy little hooks you can use instead. It might not seem like much, but it all adds up.
Removing all traces of Bazaar
EVERYTHING is stored in one top-level .bzr directory:
cd /tmp/project
rm -rf .bzr
There is no other pollution a file tree being managed by Bazaar. This is a huge contrast to how Subversion works, where it puts .svn directories EVERYPLACE.
Managing files under Bazaar Version Control
Adding managed content
Until you tell Bazaar what files you want it to manage and Commit them you will only have an empty repository. First we "Add" files/directories we want managed then we'll need to "Commit" their current state to the VCS Repo.
- Three examples to add content:
bzr add file.c bzr add src/ bzr add .
Checking managed content
- Find out what has been modified and/or not being managed:
bzr status - Find what is being ignored:
bzr ignored
Removing managed content
- You have two options
- Delete files and/or directories directly on the file-system.
- No safety net can be provided by Bazaar
- Use the "bzr remove" command (like you would with Subversion).
- Bazaar will remove unchanged managed content, or ask for confirmation of content it would not be able to get back with a "revert".
- Delete files and/or directories directly on the file-system.
In both cases the files and/or directories will be immediately deleted in the working tree and deleted from the latest repo revision on the next "commit". If it was ever under Version Control it will still exist someplace in an earlier revision inside the VCS.
- Odd case of "add and remove before commit":
bzr add delme/ bzr remove delme --keep
The "--keep" is confusing. But think how scary it is to issue a command called "remove" on your source tree? If you already had the files under revision control Bazaar will delete them, since Bazaar could easily get them back for you. But in this particular case Bazaar does not yet have a copy, so they would be lost if anything was actually deleted. This "annoyance" really is a "feature" for our own safety.
Committing changes
So far we have only shown how to create a local Bazaar instance. Later we will see that Bazaar instances not only remember where they where "pulled" from (and "push" to) but can also be used like a Central Non-Distributed Repository (like Subversion). Fore now just note that the "commit" command updates the repository, which can be either a local or remote Bazaar instance, depending on how it was created.
- Commit your changes (locally, unless this was a checkout):
bzr commit -m "initial import of this project"
Now that the "cat is out of the bag", you know that there will be a repository type I'll call "Checkout". You can still "bzr commit" in a Checkout, but it will automatically update both the local repo and the upstream version you originally Checked-out. If for some reason the upstream is unreachable, you can "bzr commit --local" to update only the local instance. This might be a very common thing if your Checkout was done to a laptop which is frequently used without a network connection.
- To push the local repo contents upstream:
bzr push {BazaarRepoURL} # Future "push" commands will default to the last URL used. bzr push
After pushing to a URL once, the local instance will remember who it pushes to, and will default to it on future "push" commands when a URL is not supplied. The same thing is true for the "pull" command, which is stored separately. This allows for an instance to remember separate upstream and downstream branches.
Commands just like CVS & SVN
- bzr diff file.c
- Show the difference between the last checked in version of "file.c" and the one it the working tree.
- bzr cat file.c
- Display the contents of the last checked in version of "file.c"
- bzr revert file.c
- replace the existing "file.c" with the last checked in version of "file.c"
- bzr mv file.c file2.c
- Moves "file.c" to "file2.c" in the working directory AND informs the repo to do the same on the next "commit" command.
Commands just like CVS & SVN (continued)
- bzr remove file.c
- Deletes the "file.c" from the working directory AND informs the repo to do the same on the next "commit" command.
- bzr commit -m "a really good comment"
- Commits the working directory changes to the repository.
- bzr checkout {BazaarRepoURL}
- Checks out the given Repository. A checkout like this will behave similarly to non-distributed VCS, in that future "commit" commands will attempt to update the checked out URL directly.
- bzr diff
- Shows the differences for ALL changed files in the working tree.
init vs. checkout vs. branch
Keep in mind that a repositories Working Tree can be Outdated or Modified from the most recent version in that repo. And that this is completely independent of each repositories synchronization with other branches, both upstream and downstream. This is a complex system and it's easy to loose track. Remember that the beauty of Bazaar is that it keeps this all as simple as possible, and that if offers a number of usage patterns that manages some of the complexity for you.
bzr init
When covering "commit" above we talked about only knowing about a locally managed Bazaar instances (created with a "bzr init"). This is the simplest Bazaar instance possible. This is both the origin and base of most of these other types.
At this stage it does not know about any other other Bazaar repositories. It stands alone, on the local file-system. Everything is contained within the single ".bzr" directory at the instance root.
bzr branch {BazaarRepoURL} {localpath}
The "branch" command creates a new repository and automatically pulls the contents of an upstream neighbor. Any "commit" commands are NOT automatically shared with the upstream neighbor. The two Branches are said to have "diverged" as soon as one of them has been changed. The new Branched version may update itself from the upstream neighbor using the command "bzr pull". If permission allows, the Branched version may also push it's changes back upstream with a "bzr push" command.
bzr checkout {BazaarRepoURL}
This is the special instance that by default behaves like a non-distributed centralized repository. It's similarly to a "Branch", except that "commit" commands are automatically pushed upstream.
A very interesting option to this command is "--lightweight". In a Lightweight Checkout the "repository VCS data" is not even copied to the locally created repository. Any meta-data checks will require contact with the upstream repository, but substantial savings on local disk space makes this option extremely useful in some circumstances. Most useful in situations where very large files are under VCS mainly for synchronization purposes.
Note that a Checkout (not --lightweight) does actually contain a complete distributed copy of all the repository data. Several convenience feature exists to take advantage of the completeness of this local repo. Bazaar has provided a "--local" option to "bzr commit" that will commit the changes locally. So while a "bzr commit" will fail on a network disconnected laptop, a "bzr commit --local" will cache the transaction for a future network connected commit.
Transitions
Just to complete the confusion a Branch can be made into a Checkout by using the "bzr bind {BazaarRepoURL}" command. Likewise a Checkout can be made into a Branch using the "bzr unbind" command. A stand alone instance can also mirror an existing repository by using the "bzr bind {BazaarRepoURL}" command.
Aditionally a Bazaar VCS can be "Reconfigured" into another type using the "bzr reconfigure" command. Let's say you decide that you no longer need to have local storage taking up disk space for a Branched instance.
Reconfigure existing "/tmp/proj" into a Lightweight Checkout:
bzr reconfigure --lightweight-checkout /tmp/proj
In the world of Distributed VCS (DVCS) it's easy to get overwhelmed by having too many branches. Some thought should be put into the structure you want to support. The Checkout usage model for Bazaar is a nice tool that helps indicate precedence, while still providing full functionality.
Checking out a new working tree
Alright why bother with DVCS if we're not going to Distribute the VCS. Lets assume we have a repository that we want to use/mirror/branch. We'll see one way it can be created in the next section "Off system storage", but any local path or URL accessible repo specification will work. Lets get used to using the most likely URL format of "sftp://server/tmp/common-project", which will use the SFTP/SSH protocol to access host "server" Bazaar repo path "/tmp/common-project".
In our first case we are not really Distributing the VCS, we are distributing the working tree and placing a reference to the originating VCS.
Checking out the "sftp://server/tmp/common-project"
- Checkout as "/tmp/proj1" (no local VCS repo created):
bzr co sftp://server/tmp/common-project --lightweight /tmp/proj1 - Checkout as "/tmp/proj2":
bzr checkout sftp://server/tmp/common-project /tmp/proj2
Note that "co" is a common abbreviation for "checkout". They really are the same thing I'm just using both so that it's less scary when you see it in the future. ;)
Commits done on both "/tmp/proj1" and "/tmp/proj2" will attempt to update "sftp://server/tmp/common-project". Commands accessing meta data, like "bzr log" will however behave differently. Because "/tmp/proj1" does not contain any VCS information it must retrieve log data from "sftp://server/tmp/common-project", while "/tmp/proj2" can answer using only local data.
Branch of "sftp://server/tmp/common-project"
- Branch as "/tmp/proj3":
bzr branch sftp://server/tmp/common-project /tmp/proj3
A "Branch" is just a more detached version of a "Checkout". In fact later you will see how easy it is to Transition a Bazaar Repo from either one to the other.
The Branch "/tmp/proj3" differs from the Checkout "/tmp/proj2" only in that "bzr commit" commands to not automatically get "Pushed" to "sftp://server/tmp/common-project". A "bzr commit" in "/tmp/proj3" only updates the local VCS, the Upstream VCS is not affected until the execution of a "bzr push" command.
Off system storage
If you want to store a Bazaar VCS instance back on a central server there are a lot of different options. There is a container to shared branches with a common roots. There are treeless Repos which have no Working Tree, just the .bzr directory storing the raw repo data. There is the "bzr server" command which will run a network server. And you may serve your Bazaar files over HTTP(S) or (S)FTP.
Lets focus on the easiest choice for Linux "sftp://system/path". Your SSH passkeys are used for all of the "sftp:" based paths. So anyplace you can SSH into without a password you can checkout and commit code to (file-system base permissions allowing). If no passkeys exist you will be prompted for the password, the current user is assumed. Note that the remote server DOES NOT NEED any Bazaar code installed on it.
- Create storage on a central server for a local repo:
cd /tmp/project bzr push sftp://server/tmp/common-project # NOTE: any file path works /tmp is ONLY an example # A complete independent VCS Repo is created there. - Update the central server with a locally committed change:
cd /tmp/project # make changes bzr commit -m "Changed ..." bzr push
Essentially you have created a Branch. It might help to think of your local copy as the "Development VCS" or "Experimental VCS" and the central server version as the "Release VCS".
Branching & Merging
Branching is creating another independently managed copy of the original one. Since both can be updated independently they may Diverge.
- To branch as "/tmp/branch" the Bazaar Repo "/tmp/main":
bzr branch /tmp/main /tmp/branch
At this point both projects are active. You can edit and commit to both independently.
- If changes are made on the "main" code base and you want to make
them on a "p2" branch:
cd /tmp/branch bzr merge # It defaults to it's upstream branch. # Conflicts may occur, see next section "Handling Conflicts" # So far, only the working directory has been modified. bzr commit -m "merged in latest from main project" - You can also merge the "branch" back into "main":
cd /tmp/main bzr merge /tmp/branch # Conflicts may occur, see next section "Handling Conflicts" # So far, only the working directory has been modified. bzr commit -m "merged in latest branch" - Alternately you could Mirror the Merged "branch" back to "main":
cd /tmp/branch bzr push /tmp/main # We must supply a downstream branch the first time.
Regardless of how you perform the Merge both branches will end up up with complete transaction logs.
Handling Conflicts
Sometimes during a "bzr merge" or "bzr update" Bazaar finds conflicting instructions from two Repos. How it handles these situations is to generally holler "Conflict" and ask you to resolve them.
When it first occurs it's a little scary. First there is all that hollering, then you find a number of odd files in your working tree that you didn't put there. At least that was my reaction, which then prompted a look through the documentation to see if it had blown up and how I was supposed to act.
Turns out it's pretty easy. First you can generally ignore the extra files. If it is complaining about "somefile" there could be multiple versions with additional suffixes like: "somefile.BASE", "somefile.OTHER" and "somefile.THIS". You really only need to edit the one file that you normally have in your archive, our "somefile". In that file you'll find a section that will be marked with a lines starting with "<<<<<<<" and ">>>>>>>", and there will be a "=======" line separating your two choices. You should review the choices and pick the one you want to continue forward with, or you may decide to manually merge them both together. Either way you make those edits and save out the file in the normal manner.
You may can explicitly tell Bazaar which file is resolved or simple leave of the file to recheck all the ones it marked with conflicts.
- near duplicate changes:
# edit the Conflicting file # Pick the changes you want or merge both bzr resolve - questionable files:
# Place the version of "somefile" wanted in place (OR delete it) bzr resolve somefile
It's possible that one choice is there should be NO file. In that case it's a little hard to EDIT it to the state you want. So you may have to use the filename option to state that the lack of file does indicates your resolve to leave it out. If however the file should be a part of this you may want to copy one of the "suffixed" files into place.
Other Questions
- Patch Queues
- I believe the LOOM Plugin can handle one or more separate Bazaar repositories of patches that can selectively be applied to a single code base. The "LOOM" determines which threads are woven into the resulting product. These threads (Bazaar repositories) can be enabled, disabled and set as the active thread to apply changes too. I have NOT used this functionality yet.
- Line termination
- The problem here is that textual content like (PERL or Python) that run on Windows and Unix may not like changes in line termination between \r\j and \j. I can say that my Python code has worked perfectly when created and edited on Unix and Windows and checked into a Linux BZR repo. They do explicitly state line termination support on the latest versions of Bazaar.

