Cherrypicking workflows with bzr

John Arbash Meinel john at arbash-meinel.com
Thu Jan 19 01:13:52 GMT 2006


Matthew Palmer wrote:
> I'm currently using baz to support the following workflow.  Can bzr handle a
> similar workflow, or how can I achieve a similar result in bzr?
> 
> One master trunk holds all of the "common" files for all of the different
> projects -- templates, common config files, and so on.
> 
> There are a number of branches taken from this trunk, one for each separate
> site we're supporting.  The branch contains customisation of the common
> config, deployments of the templates into new files, and often new general
> purpose features needed by a particular branch.
> 
> Periodically, we go through the branches and "remerge" all of the useful
> general features back into the trunk for other branches to use.  Since a lot
> of changesets aren't suitable for the trunk, we replay the relevant branch
> changesets into the trunk and then sync-tree all of the unwanted changesets,
> so that we can use "baz missing" to tell us about what changesets in a
> branch haven't been merged/ignored in the trunk.
> 
> For various practical reasons, we can't always implement new features in the
> trunk and then push them out to the branch, and it would be problematic to
> require each new feature on a branch.
> 
> I'll happily admit that I'm not "up" on the latest of bzr, and I'm not 100%
> confident I've got the whole bzr mental model of data and metadata yet, so
> this may be something that is trivial.  But my current understanding is that
> bzr's underlying concepts are quite different to baz's, so taking single
> changesets out of branches and keeping everything straight isn't done in the
> same way.
> 
> All help and comments appreciated.
> 
> - Matt
> 
> 

Short answer: Probably not with the current bzr. But maybe after we
support cherry picking better.

Long answer:
I don't think the interface right now lets you do this easily. If only
because we have no 'sync' command.
After thinking about it in long form (se

But lets try to think about the internal model...

Lets define some branches
T - Trunk
A - Site A
B - Site B

Originally both A and B are branched from T.
In A, you do some work, generating 3 revisions (10, 11, 12).
Then you do:

$ cd $T
$ bzr merge -r 10..12 $A
This says merge the changes of 12 relative to 10, which should be 11 and 12.

At this point if you set the .bzr/pending-merges to include
revision 12, to $T it will look like you merged everything in
$A
$ bzr sync $A # Theoretical command

You should get equivalent results by doing:
$ bzr merge $A
$ bzr merge --force -r 10..9 $A

Which is basically saying, merge all of A, and then remove the changes
for revision 10. (--force is necessary because merge doesn't like to
merge into a modified tree)

At this point you
$ bzr commit -m "cherry pick A-11,12"

Now, the ancestry should look like:

T1 --- T9 ---------------.-> T10
        |               /
        v              /
        A10 -> A11 -> A12

At this point if you
$ cd $A
$ bzr merge $T

What you want is for it to not do anything. However, I think the merge
code would pick A12 as the common ancestor for both trees, and then
notice that T10 changed some stuff.
Base = A12, This = A12, Other = T10
That would show a content change, which would be applied A (effectively
reverting A10).

However, if you go to A and 'sync' T the ancestry looks like:

T1 --- T9 ---------------.-> T10
        |               /     \
        v              /       \
        A10 -> A11 -> A12-------`-> A13


At this point, if you were in A and you did:
$ cd $A; bzr merge $T
Then it should pick T10 as the common base.
Base = T10, This = A13, Other = T10

Which has no changes to merge.

However, going back to $T
$ cd $T; bzr merge $A
It would pick
Base = T10, This = T10, Other = A13
Which would have changes to merge.

So I think are diff3 merging would not do what you would want. Because
we look at the specific contents of BASE, THIS, and OTHER, and merge
from there. If BASE & OTHER are not identical, it will try and merge
those changes.

Now what about Weave merge? Going back to the first scenario, where T
has cherrypicked A's changes. Revision T10 specifically deletes the
lines from A10, so A10 would try to delete them => failure.

And if we 'sync' A versus T10, it actually looks like the lines are
specifically created by A13 (resurrecting deleted lines looks like a new
addition, they do not keep the old revision identifiers one of the
limitations of our weave format). So again we fail.

So it doesn't really seem possible.
The problem is that we don't do patches, we do snapshots. So when we
mark something as an ancestor, we basically say "This version of the
contents is better than that old version of the contents". Not, "I have
those changes, don't try and pull them in the future".

We have discussed how to do cherry picking, and some of those changes
would probably allow your use case to work. Specifically, if we can
resurrect lines, then when T tries to merge A13, it will notice that
those lines are older than it is, so it won't merge them (theoretically).

Alternatively, we might introduce some sort of 'bzr replay' rather than
'bzr merge'. Where 'replay' can find the common ancestor, and then
replay the changes that aren't present. And since A12->A13 doesn't have
a text change, then T would not replay the A10 fix.
All that is really needed is that BASE would have to be picked
correctly. So that BASE vs OTHER doesn't look like anything has changed.
Even a regular merge command, that would restrict the merge base into
being in one of the revision-histories might do the right thing.

So I think it is something that we *can* support, but I'm not sure how
to do it yet.

John
=:->

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 256 bytes
Desc: OpenPGP digital signature
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20060118/e006de49/attachment.pgp 


More information about the bazaar mailing list