Very often, it can be useful to re-use a working tree to work on multiple branches.
Re-using a working tree is a matter of organizing your local branches in a certain way:
bzr bind
followed by bzr update
and bzr revert
, or by using bzr switch
Let's create a shared repository with no working trees by default:
$ bzr init-repo /sandbox/reusing --no-trees Shared repository (format: 2a) Location: shared repository: /sandbox/reusing
Let's create a few sample branches:
$ cd /sandbox/reusing/ $ bzr branch lp:~bzrbook/bzrbook-examples/common-two-features trunk Branched 3 revisions. $ bzr branch -r1.2.3 trunk/ feature1 Branched 4 revisions. $ bzr branch -r1.1.2 trunk/ bug1 Branched 3 revisions.
Since the shared repository is configured to create no trees, we can confirm that all these branches have no working trees:
$ ls * bug1: feature1: trunk:
Finally, we need to create a checkout with a working tree that we will use to switch between branches and perform version control operations:
$ bzr checkout trunk/ work
As we can confirm, a checkout always has a working tree:
$ ls work/ hello.py hello.rb hello.sh screenshots todo.txt
There is one very important precaution to take before switching branches—make sure you don't have uncommitted changes in the working tree. As the whole point of switching branches is overwriting the working tree, you should make sure to commit all the important changes before going ahead with the switch. Although the methods explained here do not destroy the uncommitted changes by default, they can get mingled with other changes in the process, making them extremely difficult to recover. A wise thing to do is to commit all the pending changes before switching branches.
The working tree we created is currently bound to the trunk:
$ cd work $ bzr info Repository checkout (format: 2a) Location: repository checkout root: . checkout of branch: /sandbox/reusing/trunk shared repository: /sandbox/reusing
We can switch to another branch by using bzr bind
followed by bzr update
, followed by bzr revert
:
$ bzr bind ../bug1/ $ bzr info Repository checkout (format: 2a) Location: repository checkout root: . checkout of branch: /sandbox/reusing/bug1 shared repository: /sandbox/reusing
There is no output after bzr bind
, because the command doesn't change the working tree. When binding to a new location, the working tree must be updated by using bzr update
to synchronize it with the repository.
$ bzr update All changes applied successfully. Updated to revision 3 of branch /sandbox/reusing/bug1 Your local commits will now show as pending merges with 'bzr status', and can be committed with 'bzr commit'.
The way update works is, if the original branch contains revisions that are not in the new target branch, then those revisions will be treated as local commits.
If there had been "real" local commits before this step, they would still be local commits, naturally following the regular commits that have been converted to local commits. However, notice the danger here—these real local commits exist only in this branch; by definition, they have not been committed in other branches. The next step in completing the switch is bzr revert
, which will erase these local commits. In a realistic situation, you should not have any local commits when switching between branches, as that would risk losing work.
In our example, we are not working on
local commits; we simply want to switch our working tree to another branch. So, at this point, we want to move these changes out of the way with bzr revert
:
$ bzr revert - hello.rb M todo.txt $ bzr status unknown: hello.rb
Although there is an unknown file left behind, because it existed in the previous branch, this is not a problem. In any case, we should move it out of the way, otherwise it might lead to conflicts when we switch to another branch later. We can remove the file manually, or by using the bzr clean-tree
command:
$ bzr clean-tree hello.rb Are you sure you wish to delete these? ([y]es, [n]o): yes deleting paths: hello.rb
As usual, Bazaar does not make
irreversible changes without asking for confirmation. To skip the confirmation, you can use the --force
flag.
With this last move, we have successfully switched the working tree to another branch.
The switch
command is not a core feature, but is included in the
loom plugin. It makes switching between branches much easier:
$ bzr info Repository checkout (format: 2a) Location: repository checkout root: . checkout of branch: /sandbox/reusing/trunk shared repository: /sandbox/reusing $ bzr switch ../feature1/ Updated to revision 4. Switched to branch: /sandbox/reusing/feature1/ $ bzr info Repository checkout (format: 2a) Location: repository checkout root: . checkout of branch: /sandbox/reusing/feature1 shared repository: /sandbox/reusing
The switch
command hides most of the details involved in the process of switching branches.
An interesting difference from using the bind-update-revert
method is that bzr switch
will refuse to run if there are local commits in the branch. This is a good thing, because it is potentially unsafe to switch branches when there are local commits, as those commits would get lost. To switch anyway throwing away local commits, use the --force
flag.
A very useful feature of the switch
command is to create a new branch from the current one and switch to it immediately by using the -b
or --create-branch
option. For example:
$ bzr switch -b ../feature2 Tree is up to date at revision 3. Switched to branch: /sandbox/reusing/feature2/
When using a shared repository, it may seem pointless at first to use a lightweight checkout locally—branches are already very cheap, as the revisions are not stored directly inside the branches but in the shared repository. Whether a checkout is lightweight or not, it makes no difference in terms of disk space, and since we are performing branch operations locally, there is also no network latency.
However, there is still a benefit of using a lightweight checkout instead of a regular one—by definition there cannot be local commits. Considering that you may inadvertently delete important local commits, there exists some amount of risk when using regular checkouts. By using lightweight checkouts, you can effectively eliminate this risk when switching branches.
You can convert your working tree by using bzr reconfigure
. For example:
$ bzr reconfigure --lightweight-checkout $ bzr info Lightweight checkout (format: 2a) Location: light checkout root: . checkout of branch: /sandbox/reusing/feature2 shared repository: /sandbox/reusing
18.226.104.153