Friday, April 3, 2009

Merging unrelated branches in Bazaar

The skinny : 'cd <working-tree-to-merge-into>', then 'bzr merge <branch-to-merge-with> -r0..-1', and then 'bzr commit "Merged with {bla}"'.

I continue to love Bazaar.

I've wondered for a while : "How can I merge two completely unrelated branches?"

Scenario : I'm working on a large website with an extensive ASP.NET section, and an extensive Flash section. The ASP.NET section is very mature. The Flash section has just begun. I want to be able to version control the Flash stuff in the same repository as the ASP.NET stuff, but in unrelated branches, and eventually merge the branches once the Flash stuff matures somewhat.

Can do! But it took a bit of figuring out.

Along the way, I kept bumping my head against this error message from Bazaar :

bzr: ERROR: Branches have no common ancestor, and no merge base revision was specified.

Suppose my folders were :

C:\BzrRepo\AspDotNetStuff

and

C:\BzrRepo\FlashStuff

I was trying to do :

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff

That wasn't working, so I tried using the --revision= option to specify a base revision (as hinted by the error message) :

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff --revision=1

Still no go.

So I looked at the --change= option.

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff --change=1..27

(27 being the latest revision number in the FlashStuff branch.)

Still no go - it tells me that the --change= option cannot handle revision ranges - it can only handle one specific revision number.

OK, so what if I try to integrate just the very latest change?

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff --change=27

That didn't work either. Instead, it created lots of conflicts.

Ah - finally I think I see the light!

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff --change=1

Yes! Progress! It worked! i.e. I have to start with the very first change in the unrelated branch.

Now will it let me merge the remaining changes?

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff

Nope - it complains that I have uncommitted changes.

Easily fixed :

C:\BzrRepo\AspDotNetStuff> bzr commit -m "Merged with FlashStuff revision 1"

Good.

And now let's try the merge again :

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff

Bonanza! It worked!

And I have now successfully merged two COMPLETELY UNRELATED branches that lived under the same repository.

In summary, the quick way to do it :

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff --change=1
C:\BzrRepo\AspDotNetStuff> bzr commit -m "Merged with FlashStuff revision 1"
C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff
C:\BzrRepo\AspDotNetStuff> bzr commit -m "Merged fully with FlashStuff"

And I'm a happy camper. :o)



UPDATE : Thanks to bialix (in the comments) for pointing out a simpler way to accomplish the same thing :

C:\BzrRepo\AspDotNetStuff> bzr merge ..\FlashStuff -r0..-1
C:\BzrRepo\AspDotNetStuff> bzr commit -m "Merged with FlashStuff"

Slightly different syntax, accomplishes the same thing, but more concise. Did I mention I love Bazaar?

2 comments:

bialix said...

You can merge 2 unrelated branches specifying 0 as first revision in revision range. Next command will merge entire Flash branch:

bzr merge ../Flash -r0..-1

Actually `--change N` option is equal to `--revision N-1..N`.

Verbose Philosopher said...

Thanks bialix! That's a useful one for my bag of tricks. I'm always glad to find new ways to use superb tools! :o)