monotone-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Monotone-devel] Re: CVS -> SVN -> Git


From: Markus Schiltknecht
Subject: [Monotone-devel] Re: CVS -> SVN -> Git
Date: Sat, 21 Jul 2007 09:55:36 +0200
User-agent: Icedove 1.5.0.12 (X11/20070607)

Hi,

(I'm cross posting to monotone-devel, as that might be of interest.)

This is an overview about how to represent tags or branches in distributed VCSes. It focuses on 'broken' tags which span multiple revisions, because they are imported from a legacy VCS (like CVS or subversion) where such things were possible.

Karl Fogel wrote:
Right now, cvs2svn goes out of its way to try and do all that in *one*
commit.  It's not immediately obvious to me which way is better...

For monotone, git and mercurial, you always have to add an artificial revision. The question is, how to create those artificial revisions to represent the original history the best. For example, let's have three revisions, A, B, C, following each other:

        A
        |
        B
        |
        C

Let's assume, that CVS (or svn) defines a tag which spans all three revisions (i.e. files from A, B and C get tagged together), most of them from B. There are basically two possibilities, on how you could represent that in the mtn/git/hg world.


Variant 1. - artificial patches

        A
        |
        B
        | \
        C  X

Where X is the artificial revision which gets tagged. X needs to add all the (reverting or forwarding) changes needed, to satisfy what the tag wants.

For a file tagged at A, the log would show something like:

    X:  an artificial revision for your tag (a merge)
        (reverting 'some change to the file')

    B:  some change to the file

    A:  initial import


For a file tagged at C, the log would show:

    X:  an artificial revision for your tag (a merge)
        (forward patch to 'some future change')

    B:  some change to the file

    A:  initial import

(Note that C doesn't even show up)



Variant 2. a) - multiple artificial merges

        A
        | \
        B - Y - X
        |      /
        C ----+

This involves two additional artificial revisions, which merge contents together until we meet the requirements for our tag.

For a file tagged at A, the log would show:

    X:  an artificial revision for your tag (a merge)

    Y: an artificial revision for your tag (a merge)

    A: some change to your file


For a file tagged at C, the log would show:

    X:  an artificial revision for your tag (a merge)

    C: some other change to another file


This variant does not need to add artificial changes (patches), but only needs to add artificial merges. That's why I'm favoring this approach.


Variant 2. b) - a single artificial merge

I've just discovered, that git can handle revisions with multiple parents... Monotone can't. That would allow, what others probably called a "one commit" solution:

        A
        | \
        B - X
        | /
        C

The logs would even be cleaner than in variant 2. a), as we have one less artificial merge. Likewise, that would only add a merge, but no artificial patches.


I'm clearly favoring variant 2. Wherever possible (git?), 2. b), otherwise 2. a) (monotone, mercurial, codeville).


Please note again, that all the above does not only apply to tags, but also to branchpoints, which makes the whole issue more important.


Also, you might have noted, that such an artificial revision creates a new head in the main branch (trunk). This is disturbing and unwanted, but can easily be circumvented by putting the artificial revisions into a separate branch for the tag. For branchpoints that's not an issue, as we already have a branch to put the artificial revisions in.


I hope to have brought some clarity into the discussion and provided examples which can be discussed further.

Regards

Markus





reply via email to

[Prev in Thread] Current Thread [Next in Thread]