Using Bazaar with Subversion

Bazaar works transparently with Subversion—the checkout, update, commit, branch, pull, push, and merge commands, all work directly with Subversion repositories. There are several advantages in working with Subversion through Bazaar:

  • The benefit of being distributed is that branches carry the complete revision history: Since Subversion is a centralized VCS; a checkout contains only the latest revision, not the full history. Operations that involve the history require access to the central repository, making these operations slower, or even unusable when the server is down. If you check out from Subversion by using Bazaar, you will have the full history locally.
  • You can create local branches: In Subversion, all branches must be created and stored on a central server. If you checkout using Bazaar, you can create local branches and enjoy more freedom to experiment.
  • Merging branches is easier: Bazaar is very good at merging branches, and you also have the option to try different merging strategies.
  • Backup, mirroring, migration: Since a checkout using Bazaar will have the complete history, it is close to a backup of the original Subversion location.

Installing bzr-svn

The plugin to work with Subversion branches is named svn, typically in a package named bzr-svn. Confirm whether or not it is already installed in your system by using bzr plugins. If it is not in the list, see the Installing plugins section, and follow the steps to install it.

In addition to bzr-svn, you also need to install subvertpy, a Python library to interface with Subversion. Install it using your operating system's package manager or pip. A simple way to verify that both bzr-svn and subvertpy are correctly installed is by creating a dummy Subversion repository using Bazaar:

$ bzr init --subversion /tmp/empty-svn-repo
Initialising Subversion metadata cache in /Users/janos/.bazaar/svn-cache/2f4f2ffe-08e1-45a5-847b-c4ce217833be.
Created a repository branch (format: subversion)
Using shared repository: /tmp/empty-svn-repo/

The --subversion flag is provided by the bzr-svn plugin. Normally, the bzr init command does not have such options.

Supported protocols and URL schemes

Bazaar supports all the standard Subversion URL formats, such as the following:

  • http://server/path/to/branch
  • https://server/path/to/branch
  • svn://server/path/to/branch
  • svn+ssh://user@server/path/to/branch
  • file:///path/to/repo/branch

Although the generic URL formats, such as http://, https://, or file:///, can be Bazaar or even other VCS, Bazaar correctly detects Subversion repositories.

Note that when using the svn+ssh:// protocol, the path to the Subversion repository must be the full absolute path, even if the repository is in the home directory of the user. And, unlike with bzr+ssh://, the /~/ notation to indicate the user's home directory does not work; you must use the full path always.

Using the example Subversion repository

The best way to explore how Bazaar works with Subversion branches is by playing with a local Subversion repository. If you are familiar with Subversion, you can create a repository by using svnadmin, or you can download and unpack the following sample repository:

https://launchpad.net/bzrbook-examples/trunk/examples/+download/svn-repo.tar.gz

The svn-repo directory inside the ZIP file contains a small Subversion repository, which will be accessible via file:/// URLs. For example, if you move the svn-repo directory into /tmp, it will be accessible via file:///tmp/svn-repo. You can try some other commands, such as bzr info or bzr log, on it:

$ bzr info file:///tmp/svn-repo
Repository branch (format: subversion)                                         
Location:
  shared repository: /tmp/svn-repo
  repository branch: /tmp/svn-repo
$ bzr log file:///tmp/svn-repo/trunk --line -n0
4: gatekeeper 2012-12-02 [merge] merged from anna                              
  3.1.3: anna 2012-12-02 added r impl
  3.1.2: anna 2012-12-02 added python impl
  3.1.1: janos 2012-12-02 created branch for anna
3: janos 2012-11-26 merged from mike
2: janos 2012-11-26 added readme
1: janos 2012-11-26 created standard svn layout

The examples in this section will use this repository, assuming it at the path /sandbox/svn-repo.

Understanding branches in Subversion

Before we begin to branch or check out from Subversion, it is good to be aware of some important differences between how branches and tags work in Subversion.

A typical Subversion repository contains the following subdirectories at the repository root:

  • trunk: This is the master branch, where the main development happens
  • branches: This is a container directory for branches
  • tags: This is a container directory for tags

In Subversion, a branch is a lightweight copy of another directory at some specific revision. Typically, it is created in the branches directory, and it behaves like a directory. Tags are created in exactly the same way, that is, as lightweight copies of specific directories at specific revisions.

Although internally Subversion stores branches and tags efficiently, when you checkout the repository, the layout is expanded into the filesystem as regular directories, which can take a lot of disk space. In order to avoid expanding a very large directory tree with all the branches, make sure to use the right Subversion URL in the checkout and branch operations.

Keep in mind that the preceding layout is a commonly used standard, not a hard rule. It is up to the managers of the project how they organize branches and tags inside their Subversion repository. Make sure to confirm the right URL before you begin to checkout or branch.

Another important point to note is that although in Bazaar the smallest logical unit that you can checkout is a branch, in Subversion it is a subdirectory.

Branching or checkout from Subversion

You can branch or checkout from Subversion with the bzr branch and bzr checkout commands, or by using Bazaar Explorer as usual. But first let's create a shared repository:

$ bzr init-repo /sandbox/svn-examples
Shared repository with trees (format: 2a)
Location:
  shared repository: svn-examples
$ cd /sandbox/svn-examples/

It is always a good idea to use a shared repository when working with multiple remote branches. This is especially true when working with foreign branches, due to the added overhead of translation between Bazaar and the foreign protocol.

Next, let's checkout a few branches by using bzr checkout:

$ bzr checkout file:///sandbox/svn-repo/trunk
Initialising Subversion metadata cache in /Users/janos/.bazaar/svn-cache/5260eff9-c761-4657-805e-432c3fbc2731.
$ bzr checkout file:///sandbox/svn-repo/branches/mike

Notice the message after the first checkout—Initializing Subversion metadata cache. This is an optimization by Bazaar—the Subversion plugin builds a cache of Subversion metadata in order to speed up operations when working with the same Subversion repository again in the future. A new directory is created to store the cache of each distinct Subversion repository you use, and the name of the directory corresponds to the UUID of the Subversion repository, a universally unique ID generated by Subversion when the repository was created.

Branching from Subversion works exactly in the same way as with Bazaar branches. Regardless of the manner in which you fetch a Subversion branch, the end result will be a native Bazaar branch.

Keep in mind that Bazaar branches store the complete revision history, and therefore the first checkout or branch from a Subversion repository may take a long time depending upon the size of the project and the number of commits.

Preserving Subversion metadata

When fetching a Subversion location, Bazaar preserves various metadata about the revisions, such as the following:

  • Basic revision information—committer, timestamp, and log message
  • Original revision number in Subversion
  • Versioned properties, such as svn:mergeinfo and svn:mime-type
  • Revision IDs and file IDs

Preserving original revision numbers

Revision numbers in Subversion are not per-branch but per-repository. If you recall that branches in Subversion behave much like directories, this makes sense.

Although both Bazaar and Subversion increments the revision number on each commit, when fetching a subdirectory of a Subversion repository, Bazaar downloads only the revisions that affected the specified path, which is only a subset of all the revisions inside the entire Subversion repository. As a result, the revision numbers in the Bazaar branch will not be the same as in the original Subversion repository. We can confirm this by using bzr log:

$ bzr log -r3 trunk/
------------------------------------------------------------
revno: 3
svn revno: 6 (on /trunk)
committer: janos
timestamp: Mon 2012-11-26 20:50:53 +0000
message:
  merged from mike

The Bazaar revision number is 3, but the Subversion revision number is 6, because only three of the commits in Subversion affected /trunk.

You can reference the past revisions by their original Subversion revision number by prefixing with svn:. For example:

$ bzr log -r svn:6 trunk/
------------------------------------------------------------
revno: 3
svn revno: 6 (on /trunk)
committer: janos
timestamp: Mon 2012-11-26 20:50:53 +0000
message:
  merged from mike

Preserving versioned properties

Versioned properties are a feature of Subversion that is not supported by Bazaar. In Subversion, these are used for storing all kinds of metadata associated with files, directories, and merging, such as mime-types, keywords, line-ending character, and various other purposes, and all these metadata are versioned. Bazaar will preserve versioned properties and write them back when pushing to a Subversion repository, but in general, they will be ignored.

Preserving revision and file IDs

Most importantly, Bazaar preserves revision and file IDs, which we can see by using the --show-ids flag of bzr log. For example:

$ bzr log -r3 trunk/ --show-ids
------------------------------------------------------------
revno: 3
revision-id: svn-v4:5260eff9-c761-4657-805e-432c3fbc2731:trunk:6
parent: svn-v4:5260eff9-c761-4657-805e-432c3fbc2731:trunk:2
svn revno: 6 (on /trunk)
committer: janos
timestamp: Mon 2012-11-26 20:50:53 +0000
message:
  merged from mike

The revision ID is derived from the Subversion repository's UUID, the path inside the Subversion repository, and the original Subversion revision number. In this way, Bazaar can uniquely identify revisions that originated from a Subversion repository, and it also keeps track of the parent-child relationships of the revisions.

The great benefit of this is that two independent Bazaar branches created from the same Subversion location will be identical:

$ bzr branch file:///sandbox/svn-repo/trunk tmp
Branched 4 revisions.
$ bzr missing -d trunk/ tmp/
Branches are up to date.

This is especially important when merging branches, as it effectively prevents from merging the same revisions twice.

Pulling or updating from Subversion

Updating a Bazaar branch from a Subversion parent branch works in the same way as it does with native Bazaar branches. Let's test this by branching from an older revision of a Subversion branch, and then pulling from it to bring the local branch up-to-date:

$ bzr branch -rlast:2 file:///sandbox/svn-repo/trunk feature1
Branched 3 revisions.

Our local Bazaar branch is out of date, precisely one revision behind, so let's bring it up-to-date by using bzr pull:

$ cd feature1
$ bzr pull
Using saved parent location: /sandbox/svn-repo/trunk/
+N  hello.r                                                                    
+N  hello.tcl
All changes applied successfully.                                              
Now on revision 4 (svn revno: 10).

Keep in mind that the pull command may rearrange the revisions in the local branch in the same way as it works with native Bazaar branches.

Similarly, if we had used bzr checkout to get a Subversion branch, then we can download new revisions from the Subversion server with bzr update, exactly as if we were working with native Bazaar branches:

$ bzr checkout -rlast:2 file:///sandbox/svn-repo/trunk checkout1
$ cd checkout1/                                                                
$ bzr up
+N  hello.r                                                                    
+N  hello.tcl
All changes applied successfully.                                              
Updated to revision 4 of branch /sandbox/svn-repo/trunk

Committing to Subversion

Committing in a branch bound to a Subversion repository works exactly in the same way as with native Bazaar branches—changes are first committed at the remote location, and only if that is successful, the changes are committed in the local Bazaar branch. If the local branch is out of date, the commit will be rejected, and you will have to update the local branch first by using bzr update.

When committing to a Subversion repository, Bazaar sets some metadata about the revisions to re-use later when working with those revisions again, such as the author information and other details. Bazaar stores these metadata as revision properties named with a prefix bzr: to make it easy to filter them out if necessary. These revision properties have no effect on Subversion operations, and are only visible in the most detailed logs. If for some reason you want to prevent Bazaar from saving such data, then you cannot use bzr commit; the only way is to unbind the branch, commit your changes locally only, and use the bzr dpush command to push them to Subversion. In this way, the extra bzr: properties won't be saved; the revisions will be applied on the server as if they were native Subversion commits.

Tip

To see all the revision properties, including the ones set by Bazaar operations, you can use the Subversion command svn log --with-all-revprops --xml.

Pushing to Subversion

Pushing to a Subversion repository works in the same way as it does with native Bazaar branches:

$ bzr branch file:///sandbox/svn-repo/trunk feature2
Branched 4 revisions.                                                          
$ cd feature2
$ bzr push file:///sandbox/svn-repo/branches/feature2
Created new branch at /branches/feature2.  

Be careful when using bzr push, as it can reorder revisions to match the local history layout at the remote repository location. This is especially important when the Subversion repository is publicly available. To prevent such issues, Bazaar will refuse to perform the push if that would reorder revisions.

As with committing, Bazaar saves additional metadata to Subversion when pushing revisions. If for some reason you prefer to not save such metadata, then use bzr dpush to push revisions instead of bzr push. If the pushed revisions do not contain a merge from other Subversion branches, then the end result will be exactly the same.

Merging Subversion branches

Bazaar is very good at merging Subversion branches, thanks to a few notable key factors:

  • bzr-svn correctly tracks the relationships between Subversion revisions across different branches
  • Since bzr-svn converts Subversion branches to native Bazaar branches, ultimately the merge operation is performed between Bazaar branches
  • Bazaar is great at merging, thanks to proper tracking of rename operations, and the many user-friendly and powerful features, such as bzr remerge

Let's try it out by merging /branches/jack into /trunk. We already fetched the trunk with bzr checkout earlier; now, let's get /branches/jack and perform the merge:

$ bzr branch file:///sandbox/svn-repo/branches/jack --no-tree
Branched 6 revisions.
$ cd trunk/
$ bzr merge ../jack/
+N  hello.py                                                                   
+N  hello.rb
All changes applied successfully.

In this example, we fetched /branches/jack to a local Bazaar branch before merging from it, but we could have used the remote branch URL directly. However, it is always a good idea to fetch the branch first, as in this way you can re-use the branch multiple times without redownloading it again from the source repository.

Also notice that we used the --no-tree flag to create the branch. In this way, we can save disk space, as we don't need the working tree of a branch we just want to merge from it.

Let's commit the merge:

$ bzr commit -m 'merged from jack' --author gatekeeper
Committing to: /sandbox/svn-repo/trunk                                         
added hello.rb
added hello.tcl
Committed revision 5.

Since we fetched trunk with bzr checkout, it is bound to the Subversion repository, and as we can see in the Committed to line in the output, the revision is committed to the Subversion repository itself. If our trunk directory had been an unbound branch, then the merge would be committed only locally, and we could push it to Subversion with bzr push :parent.

When committing the merge or pushing it later to Subversion, Bazaar sets the svn:mergeinfo property used by Subversion to track merges. This is essential to let Subversion understand correctly that the commit was in fact a merge, and appear as if performed by using a native Subversion client. We can confirm this by using the svn program, the command-line interface of Subversion:

$ svn pget svn:mergeinfo file:///sandbox/svn-repo/trunk
/branches/anna:7-9
/branches/mike:3-5
/branches/jack:11-13

Indeed, the property contains the information about the merge from /branches/jack we performed earlier.

As mentioned in the previous sections, bzr push will write the additional revision properties to the Subversion repository. Although this behavior can be prevented by using bzr dpush instead, in that case Bazaar will also not write svn:mergeinfo. In this situation, you would have to add svn:mergeinfo manually later, by using a Subversion client.

Tip

Remember that with Bazaar, you can choose from different merge algorithms, which sometimes yield better results with fewer conflicts. The bzr remerge command is especially useful to try a different algorithm on selected files, and the --reprocess flag may help reducing the size of conflicted areas. See Chapter 3, Using Branches, on branching and merging for a detailed explanation with examples.

Merging local branches into Subversion

Although you can merge local Bazaar branches into Subversion, there is a very important difference between Bazaar and Subversion—in Bazaar, the merged revisions are preserved and propagated to the remote location when committing or pushing the merge, but in Subversion, this is not the case.

When merging a local Bazaar branch that does not exist in the Subversion repository, the merge will be just a single commit in Subversion; the unique revisions of the branch will not be copied. If you want to preserve the revisions of the local branch in Subversion, then first you have to push that branch to a suitable location in the Subversion repository.

Let's illustrate this with an example, through the following steps:

  1. Create a local branch from the trunk.
  2. Commit to the branch a few times.
  3. Push the branch to Subversion.
  4. Merge the branch to the trunk and commit it to Subversion.

Let's create a local branch from the trunk called feature3 and do some commits in it:

$ bzr branch trunk feature3
Branched 4 revisions.                                                          
$ cd feature3/
$ echo >> hello.pl
$ bzr commit -m 'meaningless change'
Committing to: /sandbox/svn-examples/feature3/                                 
modified hello.pl
Committed revision 5.                                                          
$ echo >> hello.sh
$ bzr commit -m 'another meaningless change'
Committing to: /sandbox/svn-examples/feature3/                                 
modified hello.sh
Committed revision 6.

At this point, the branch exists only locally, not in Subversion. Let's push this to Subversion before we merge it into the trunk. We can push it after we merge too, but in this way, the metadata will make more sense, as you will see later:

$ bzr push file:///sandbox/svn-repo/branches/feature3
Created new branch at /branches/feature3.

Next, let's update our trunk and merge the branch into it. In our example, the updating is unnecessary, as we know for a fact that nobody else has committed to the trunk; this is just a reminder so that you don't forget to do in a real-life situation.

$ bzr update                                                                       
Tree is up to date at revision 4 of branch /sandbox/svn-repo/trunk             
$ bzr merge ../feature3/
 M  hello.pl                                                                   
 M  hello.sh
All changes applied successfully.

Finally, let's commit the merge. Since our trunk is bound to the Subversion repository, because we created it using bzr checkout, the commit will be written back to Subversion immediately:

$ bzr commit -m 'merged from feature3 branch'
Committing to: /sandbox/svn-repo/trunk                                         
modified hello.pl
modified hello.sh
Committed revision 5.

This commit, like all commits in Subversion, is a single revision including all the changes we did in our local feature3 branch. If we hadn't pushed the feature3 branch to Subversion earlier, the commits in that branch would not be preserved anywhere in Subversion. Since we did push it, the revisions are preserved, and Bazaar also created the necessary metadata to let Subversion know about the relationship between the trunk and the feature3 branch we pushed, as we can confirm with svn pget:

$ svn pget svn:mergeinfo file:///sandbox/svn-repo/trunk /branches/mike:3-5
/branches/anna:7-9
/branches/feature3:14-15

If you want to preserve the individual commits in your local branches, remember to push the branch to Subversion before merging it into the trunk. That way, Bazaar will record the necessary metadata correctly. If you forget to perform the operations in this order, then you would have to create that metadata yourself.

Binding and unbinding to Subversion locations

You can bind to and unbind from a Subversion repository in the same way as with native Bazaar branches. The result of bzr checkout is a bound branch:

$ bzr info trunk/
Repository checkout (format: 2a)
Location:
  repository checkout root: trunk
        checkout of branch: /sandbox/svn-repo/trunk
         shared repository: .

You can unbind from the Subversion location, which can be useful, for example, if the repository is temporarily inaccessible due to network problems, or if you want to commit locally only:

$ cd trunk/
$ bzr unbind
$ bzr info
Repository tree (format: 2a)
Location:
  shared repository: /sandbox/svn-examples
  repository branch: .

When the connection is restored, or you are ready to merge your local commits into Subversion, you can bind to it again:

$ bzr bind file:///sandbox/svn-repo/trunk
$ bzr update                                                                     
Tree is up to date at revision 4 of branch /sandbox/svn-repo/trunk

Similarly, you can bind to a Subversion location that you branched from using bzr branch:

$ bzr branch file:///sandbox/svn-repo/trunk tmp
Branched 4 revisions.                                                          
$ cd tmp
$ bzr bind :parent

Using lightweight checkouts

An interesting feature of bzr-svn is that a lightweight checkout is actually a native Subversion working copy:

$ bzr checkout --lightweight file:///sandbox/svn-repo/trunk light
$ ls -a light/
.
..
.svn
README.md
hello.pl
hello.py
hello.r
hello.sh

As you can see, instead of a .bzr directory, there is a .svn directory. In fact, Bazaar can work with native Subversion working copies, as if using a Subversion client.

In general, the same limitations apply to lightweight checkouts as when using native Bazaar branches—all the operations that work with the revision history will be slow. In addition, due to the overhead of the conversion between protocols, these operations will be even slower than usual.

Browsing the logs

An interesting benefit of using Bazaar to merge Subversion branches is that the branch history is easier to view in the logs, thanks to the additional metadata added by Bazaar:

Browsing the logs

Notice that we can see the merged revisions from Anna's branch—merged using Bazaar, but we cannot see the merged revisions in Mike's branch—merged using Subversion.

Limitations of bzr-svn

The plugin has the following limitations:

  • Creating the first branch from a Subversion repository can be extremely or even intolerably slow, depending upon the size of the repository.
  • Creating a branch from a Subversion repository is sometimes not possible at all, due to bugs and crashes.
  • Some Subversion properties have no effect in Bazaar—svn:ignore, svn:mime-type, svn:eol-style, svn:keywords, and svn:externals. These properties are ignored in general, but carried over correctly in branch operations.
  • Subversion merges are not shown in Bazaar, unless the svk:merge property (used by SVK) is also set in addition to svn:mergeinfo.

For a more complete and up-to-date list of limitations, refer to the plugin's homepage:

http://wiki.bazaar.canonical.com/ForeignBranches/Subversion

Final remarks on bzr-svn

For the most part, Bazaar works transparently with Subversion repositories. The result of a checkout or branch operation from Subversion is a native Bazaar branch, thus all your local operations will be native Bazaar operations that you are used to. However, all the interactions with the remote Subversion repository will be inevitably slower than usual, due to the translation between the protocols of these systems.

As long as you are aware of the limitations and the differences of the two systems, you can greatly benefit from the added features of Bazaar, such as the ability to create local branches and advanced merging capabilities.

Quick tips and cheat sheet:

  • Be aware of the limitations before you start using Bazaar with Subversion
  • Always use a shared repository locally when working with Subversion
  • Double-check the correct Subversion URL before you checkout or branch, in order to avoid downloading too many branches at once
  • The first checkout or branch operation will take a long time; subsequent operations should be much faster
  • Avoid operations directly on remote Subversion branches, check out or branch from them first, and use the local Bazaar branch instead
  • Feel free to merge Subversion branches in Bazaar to benefit from Bazaar's advanced merging features, such as bzr remerge and the various merging strategies
  • Remember to push local branches to Subversion if you want to preserve their revisions in the Subversion repository
  • Use a lightweight checkout if you just want to view the latest version of the project without working on it

The up-to-date details and limitations of the plugin are documented at the following locations:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.105.159