[merge] tags in repository

Martin Pool mbp at sourcefrog.net
Tue Jan 23 04:12:12 GMT 2007


John Arbash Meinel wrote:

> 
> 1) Tags are not versioned, rather they are just current points in time.
> I know one of the big troubles we had was trying to handle versioning.
> At least it caused a lot of debate.

Yes, that's correct.  There was a bit of a Gordian knot in previous 
discussions, with no clear outcome that would achieve all of these 
characteristics:

  - have tags versioned
  - not require a commit to add/change tags
  - allow relevant tags to be seen within related branches or checkouts 
of old versions
  - not complicate the model by introducing a "meta-version" or otherwise

I think this one addresses the key cases of

  - tags are set and rarely changed
  - tags are (semi-)globally visible - in other words, within the 
community of people working on something, there is one generally 
accepted value for a tag
  - tags are copied when mirroring or merging

and that's enough to satisfy most people most of the time.

That said by putting the policy in the repository there is some scope to 
do something more complex - this doesn't record who set the tags or 
when, but you could.

> > Many systems do not version their tags, though, so it isn't like we are
> doing worse then others. The systems that do version their tags tend to
> have them in the working directory, which means you have to commit them,
> and you can only understand them in context. (There is no way to have a
> floating 'latest stable' tag, because it can only point to something in
> the past).
> 
> 2) Your current implementation of 'copy_tags_to' always overwrites the
> target tag dict with the source. Which also means you lose any local
> tags. For example:
> 
>   bzr branch a b
>   cd a
>   bzr tag foo
>   cd ../b
>   bzr tag bar
>   bzr pull ../a # Now we have 'foo' but we lost 'bar'.

That's true, thanks for pointing it out.  I had wanted to also allow for 
existing values to be either preserved or overwritten but just dropping 
them is not a good default.

> What I would rather see is the dict be a map from key => list of values.
> I don't really care about the ancestry of the values, but you could at
> least see that you have already seen that value so it wouldn't override
> by default.

Where the list is a history of previous values?

If we want to merge them then I think we should treat it as a scalar 
merge, which would require storing a graph, not just a list.

> I can understand that it complicates matters, though. Could we have a
> way to interactively resolve tags?

> So one possibility would be to have the default "copy_tags_to" be:
> 
>   tags = self.target.get_tag_dict()
>   source_tags = self.source.get_tag_dict()
>   for k,v in source_tags.iteritems():
>     tags.setdefault(k,v)
> 
> Which means that it will pull across any tags that don't already exist,
> but it won't touch ones that do.

Yes, that's what I thought by default.  I don't mind holding off on this 
until that is done -- it won't take me long -- but I did want to show 
something.

As an interface I thought we would start by giving a notice to the user 
when there is a difference:

   tag SOMETHING differs:
      source has 134234 at 234234 "some commit message"
      destination has hn231th4n24 "other message"

You could then pull with --overwrite-tags, or use a copy-tag command to 
pull it across.

For uncommit we do actually talk interactively to the user if possible 
(if there's a tty), and that might also be reasonable here.

I am not sure what we can do to help the user make a good decision about 
where the tag *should* be.

-- 
Marti



More information about the bazaar mailing list