Subject: Re: Git/Mercurial interoperability (and what about bzr?)

From: Jakub Narebski <[email-masked]>
Date: Sat, 01 Nov 2008 03:33:43 -0700 (PDT)

Florian Weimer <[email-masked]> writes:
> * Theodore Tso:
> 
> > In the past I've looked at the possibility of creating a
> > bi-directional, incremental gateway between hg and git repositories.
> > The main thing which makes this difficult is that hg stores tags
> > in-band inside the change-controlled .hgtags file.  This means that if
> > you cut a release, tag it, and then create a commit to further modify
> > the repository, the new commit is descended from the tag commit,
> > whereas in git, the tag is a "bookmark" --- perhaps signed via GPG,
> > but not part of the revision history.
> 
> Couldn't you just keep the .hgtags file and have everyone interested
> in the tags use special scripts?
> 
> (Admittedly, I'm horribly totally by Git's behavior in this area.  I
> haven't figured out yet under what circumstances tags are pushed and
> pulled, so I'm not totally opposed to the Mercurial model. 8-/)

I think you don't understand the issue here.

First, I think that we all agree here that by definition tags should
named reference (for example 'v1.0' or '1.0') to some immutable
snapshot of a state of repository, so for example when somebody says
'v1.0' everybody knows what it is.  In Git tags are immutable (you
can't checkout a tag, you can only checkout state pointed by tag)
external pointers to commits in the DAG (graph) of revisions.

Global tags (tags used to mark releases like 'v1.0') have to _not
versioned_ and _transferable_.  Transferable (global) because we want
to know for example what 'v1.0' version was in each clone / each
repository.  Non-versioned because we want to have the same set of
tags independent on what branch we are (when we are on 'master', we
want to be able to know about 'v1.0.1' which is on 'maint'), and what
revision we have checked out (for example during bisection, we want to
be able to compare to 'v1.0' even if we have checked out revision
which is earlier than 'v1.0').

Do you agree that global tags should be both non-versioned and
trasferable?

Now Mercurial has chosen to use in-tree '.hgtags' file to have global
tags transferable.  Never mind the fact that it had to treat this file
in special way to have it non-versioned (as opposed to for example
.*ignore file, which should be both transferable and versioned); the
fact that in-tree file is used means that tag is visible to outside
(transferable) only after you commit changes in .hgtags file.

In Git tags are external to object database; they reside in
refs/tags/* namespace.  They are of course non-versioned, as not being
in-tree.  In default configuration however (from what I understand) if
you transfer (get) some tagged commit, you also get a tag that points
to transferred commit.  You don't need to create "PROJECT 1.0" (or
"Tagged v1.0") commit to make tag visible to outside.

In short, if you want to have bi-directional gateway between Mercurial
and Git, Git has to be limited:
 * no octopus merges (with more than two parents)
 * always create 'tagging commits' (bump version number for example)
   for tagging purposes on Mercurial side.

-- 
Jakub Narebski
Poland
ShadeHawk on #git