Difference between revisions of "Bazaar"

From Armagetron
Line 31: Line 31:
 
== THE ONE BIG DON'T ==
 
== THE ONE BIG DON'T ==
  
Do not, under any circumstances, do a downstram merge. If A is a main development branch, B is your branch of that (not necessarily direct, and maybe A == B) and C is a branch of that (your branch), avoid calling "bzr merge B" while working on branch C. This will keep the order of changes in your branch C, which will make it very difficult to push your changes back to B, from there to A and from there to SVN, because it would force the change order of C upstream, and you can't reorder changes in SVN, so someone has to reorder your work, and that someone is not going to be happy about it.
+
Do not, under any circumstances, do a downstram merge. If A is a main development branch, B is your branch of that (not necessarily direct, and maybe A == B) and C is a branch of that (your branch), avoid calling "bzr merge B" while working on branch C. This will keep the order of changes in your branch C, which will make it problematic to push your changes back to B, from there to A and from there to SVN, because it would force the change order of C upstream, and you can't reorder changes in SVN. What then has to happen is this that the SVN tree gets a total makeover: from the last common point of the previous tree, all changes are discarded, and then replaced by the changes as they appear in your tree. Example from a test:
 +
 
 +
One bzr user edits .bzrignore, changes get pushed to svn: [http://armagetronad.svn.sourceforge.net/viewvc/armagetronad?view=rev&revision=7803]. Second bzr (ok, it was me in another branch) user edits something else, merges the first change, and commits. The result are two new revisions.
 +
 
 +
First revision reverts the previous change and adds the new changes: [http://armagetronad.svn.sourceforge.net/viewvc/armagetronad?view=rev&revision=7802]
 +
 
 +
Second revision repeats to original changes: [http://armagetronad.svn.sourceforge.net/viewvc/armagetronad?view=rev&revision=7803]
 +
 
  
 
Instead of "bzr merge B" if B is closer to SVN than your branch is, use "bzr reorder B; bzr pull B". This has the same net effect, it gets the changes from B you don't have yet into your branch, but it reshuffles your branch so that the changes from B appear before your own changes.
 
Instead of "bzr merge B" if B is closer to SVN than your branch is, use "bzr reorder B; bzr pull B". This has the same net effect, it gets the changes from B you don't have yet into your branch, but it reshuffles your branch so that the changes from B appear before your own changes.

Revision as of 10:10, 8 February 2008


Sections: Installing the Game | Playing the Game | Competition Hub | Server Administration | Extending Armagetron Advanced | Development Docs


Bazaar (bzr) and how we use it

This is work in progress and has not yet been approved by management. Hold your horses.

What we're doing with it

Our main source repository for long term history and releases still is managed with SVN at SourceForge, but our current development trunk and feature development branches that originate from it (and will be eventually merged back) are managed with Bazaar.

Tools you need

To fetch development branches or the trunk using Bazaar, you need Bazaar. You should make yourself familiar with the basic documentation.

To contribute back, we require you "rebase" your work before we integrate it; this makes all integration conflicts happen to you, and not the poor merging operator. You'll need the bzr-rebase plugin for that.

To take over the merging operator duty and manage the two way syncing of the Bazaar branches and SVN, you'll need the bzr-svn plugin and its somewhat difficult dependencies. Difficult unless you run Ubuntu, then you get everything you need apart from the plugin itself. Lucky bastard.

Branch storage

Currently, we're using Launchpad as the primary high performance host for the bzr branches. We have a project and a team registered, and you can browse our main branches. Each branch detail page has instructions what you need to point your bzr at to fetch it and to commit to it.

Mirrors (well, the originals, actually) of the branches that are synced with SVN are available here; the -work branches are the ones mirrored to launchpad, the -sync branches are the hopefully identical copyes that get synced with SVN.

You are encouraged to create your own mirrors of these branches and publish them for others to fetch and to note the location here.

Workflow

In the following, we assume your username at launchpad is john.doe, and you want to work at our trunk branch; the URL to the writable branch then is bzr+ssh://john.doe@bazaar.launchpad.net/~armagetronad-dev/armagetronad/trunk-armagetronad-work. If you're just interested in read only access, you can use the read only URL http://bazaar.launchpad.net/~armagetronad-dev/armagetronad/trunk-armagetronad-work instead. If you want to access a branch maintained by a single developer named jane.doe, replace ~armagetronad-dev with ~jane.doe; just check the branch details on launchpad. We'll abbreviate the URL you're going to use as <URL>, because we're lazy typers.

THE ONE BIG DON'T

Do not, under any circumstances, do a downstram merge. If A is a main development branch, B is your branch of that (not necessarily direct, and maybe A == B) and C is a branch of that (your branch), avoid calling "bzr merge B" while working on branch C. This will keep the order of changes in your branch C, which will make it problematic to push your changes back to B, from there to A and from there to SVN, because it would force the change order of C upstream, and you can't reorder changes in SVN. What then has to happen is this that the SVN tree gets a total makeover: from the last common point of the previous tree, all changes are discarded, and then replaced by the changes as they appear in your tree. Example from a test:

One bzr user edits .bzrignore, changes get pushed to svn: [1]. Second bzr (ok, it was me in another branch) user edits something else, merges the first change, and commits. The result are two new revisions.

First revision reverts the previous change and adds the new changes: [2]

Second revision repeats to original changes: [3]


Instead of "bzr merge B" if B is closer to SVN than your branch is, use "bzr reorder B; bzr pull B". This has the same net effect, it gets the changes from B you don't have yet into your branch, but it reshuffles your branch so that the changes from B appear before your own changes.

Default Operation

The default way to work with bzr is to use its distributed nature. You fetch a complete copy of a branch for local work:

bzr branch <URL>
cd <branch>

There, you do your work; bzr's commands are virtually identical to those of svn, you can add, remove and move files and directories. Use "bzr ignore" to tell bzr to ignore certain files. Use "bzr commit" to record changes.

The big difference to SVN is that all these operations only modify your local copy of the branch. To publish your work, you'll need to get it back to the remote branch. Use

 bzr push <URL>

for that the first time; the next time, you'll only need to use

 bzr push

If bzr tells you that the branches have diverged, use this sequence to reconcile them:

 bzr rebase
 bzr pull
 bzr push

See the previous paragraph on why you should not usually use the usual "bzr merge; bzr commit; bzr push".

Distributed, shmistributed. I just want to work on the mainline or someone else's development branch. Is there no simple way?

There is. You can use bzr in a mode where it behaves like SVN; in this mode, you store no local history, and all operations like commits and log queries go to the remote server. Fetching a local copy of a branch in this way is called a "checkout". Just do

bzr checkout <URL> --lightweight

and then use the checkout like an SVN checkout, just replacing 'svn' with 'bzr'. The only noteworthy difference is that in bzr, moves are primitive operations, usable with "bzr mv a b", while in svn, copies are primitive.

Without the --lightweight, you will fetch the complete history, and read operations on it will no longer go to the remote server. Commits will still go directly to the remote branch. There is a quirk with the launchpad bzr branches, however: directly checking out a branch via its writable URL fails, you have to do the following. Fetch the read-only URL and the writeable URL and do

bzr checkout <read only URL>
cd <checkout>
bzr switch <writable URL>

Development or hack branches

Whenever you want to do some work you won't be able to finish in one go, you should consider branching a development branch off the current mainline or the current stabilization branch. The same holds if you are not a team member, but want to work on your own code modification of arma and want to keep it up to date with current development, make it easy for others to fetch your changes without getting tons of conflicts, and maybe submit it for integration later.

Creation

To create a development branch of <URL>, pick a local name <name> for it and do

bzr branch <URL> <name>
cd <name>

then, you can still work as if you had an SVN checkout, but this time, changes will stay local on your hard disk and will not get committed immediately.

Publishing

To publish your branch on launchpad, select a nice name for it. A good naming convention would be to remove the -work suffix all of the mainline branches have, and replace it with the name of your feature. So, for example, if you want to add flying cylces to the trunk (name trunk-armagetronad-work, URL bzr+ssh://john.doe@bazaar.launchpad.net/~armagetronad-dev/armagetronad/trunk-armagetronad-work), you would name your branch trunk-armagetronad-flyingcycles, and your URL would be bzr+ssh://john.doe@bazaar.launchpad.net/~armagetronad-dev/armagetronad/trunk-armagetronad-flyingcycles. Let's call this URL <URL2>.

To publish your branch, you simply do

bzr push <URL2>

from within your branch.

To publish updates to your branch, you'll only have to do

bzr push

from then on.

Keeping up to date

It is a good idea to make a backup (a simple copy, or publishing it) of your branch before you do this.

To keep your branch up to date with changes on the mainline, you should do

bzr rebase
bzr pull

in regular intervals. This pulls all changes done to the original branch into your branch in a way that makes later merging of your changes easy. During this process, you may encounter conflicts; resolve them one by one and continue the rebasing with "bzr rebase-continue".

Note that unless you plan squashing your changes later, you will have to do this at least once, right before your changes should get integrated back; and the total amount of work created by the rebasing and the conflicts it unearths is independent on how often you do this. So keeping up to date often is a good idea.

Merging back to the mainline

If it has been decided that a development branch is ready to be integrated into the mainline, get it up to date one last time:

bzr rebase
bzr pull

and then push the changes back:

bzr push <mainline URL>

All the changes made to the branch over its lifetime will appear in the mainline as if they had been done just now.

Squashing changes

Whenever you pull changes from upstream and rebase, each of your changes can conflict with each of the upstream changes. If the same position was edited frequently on on your branch, this can get quite annoying and error prone to resolve. You can reduce the number of conflicts you get by collapsing all the changes you have made so far into a single big change. If <URL> is the parent branch, and <URL_SQUISH> is your branch, do

# get a good copy of the original branch
bzr branch <URL>
# merge in your changes, they will get squashed on the way
bzr merge <URL_SQUISH>
<resolve conflicts>
# push the changes back
bzr commit
bzr push <URL_SQUISH>

If others have branches of your branch, this will cause trouble for them; from the point of the squashing on, they'll have to start merging from you instead of rebasing and pulling changes, and you will have to merge their changes into your branch instead of pulling them. So only do this if conflicts drive you mad or if there are no branches originating from yours yet.

Integrating changes

To integrate changes done by someone into a branch maintained by you, you should make one local copy of each of these branches, let's call them A and B. A is your branch, B is the branch containing changes to be integrated. Of course, A and B should not be your only copies of the branches.

You then do

cd A
bzr pull ../B

and hopefully, if the maintainer of B did his rebasings as he should, that's it, and you can republish your branch A. If not, you'll have to handle the rebasing:

cd ../B
bzr rebase ../A
cd ../A
bzr pull ../B

If there are conflicts during the rebasing, you can reject the integration and tell the maintainer of branch B to handle it before you try again. Alternatively, you can merge:

cd A
bzr merge ../B
<resolve conflicts>
bzr commit

This is preferable in complicated situations with lots of conflicts; the downside is that the details of the merged changes will get lost into one big change.

Switching the base branch

NOTE: This does not yet work for 0.2.8 to the trunk. The 0.2.8 branch was started in CVS and merged back incrementally using SVN, this procedure here can't work.

If a development branch was based on a stabilization branch, say 0.3.1, but has been rejected for integration there (say, it was too late), you can just move it to the trunk with

bzr rebase <URL_OF_TRUNK>
bzr pull --remember <URL_OF_TRUNK>

From then on, you'll receive all the changes from the trunk.

Merging bugfixes

NOTE: This does not yet work for 0.2.8 to the trunk. The 0.2.8 branch was started in CVS and merged back incrementally using SVN, this procedure here can't work.

Say TRUNK is a local copy of a trunk branch, and BRANCH is a stabilization branch (say 0.3.1) branching from it, changes from BRANCH can be merged into TRUNK with bzr using

cd TRUNK
bzr merge ../BRANCH
(resolve conflicts)
bzr commit
bzr push <URL of TRUNK>

When editing the commit message, please copy the merge metainformation that you see there into the commit message. SVN does not store the metainfo, so the only way to keep it for us to read is to put it into the commit message.


Sections: Installing the Game | Playing the Game | Competition Hub | Server Administration | Extending Armagetron Advanced | Development Docs