Pulling into a branch

Giorgos Keramidas keramida at ceid.upatras.gr
Wed Nov 12 06:28:08 CST 2008


On Wed, 12 Nov 2008 12:10:09 +0000, "Ben Hood" <0x6e6562 at gmail.com> wrote:
> Girogos,
>
> On Wed, Nov 12, 2008 at 3:25 AM, Giorgos Keramidas
> <keramida at ceid.upatras.gr> wrote:
>>    $ hg rebase -s 54281f61b769 -d tip
>>
>> The rebase extension is very cool for pulling lots of changesets,
>> because it pops up a merge tool when there are conflicts it cannot
>> resolve automatically, and it even includes a --continue option when a
>> merge cannot be completed right away and is finished a bit later.
>>
>> After rebase is done, the history should be 'linear' again, and it can
>> be pushed back to the 'main' branch.
>
> Cool, I'll give that a go.
>
>> One thing that is worth noting is that rebasing changes means that the
>> contributor changesets will change hashes (as does transplanting them or
>> importing them on top of a different history).  This may require that
>> for new work, or re-synchronizing his local tree the contributor creates
>> a new clone with "hg clone -r CHANGE" and then re-pull from the 'main'
>> tree, or to use the "hg strip" command from MQ.
>
> Doesn't this mean that the contributor is effectively throwing away
> their old tree?

Not really.  They are throwing away only 'parts' of the old history.
The same thing as a developer working in a Subversion branch and
committing his changes as revisions:

    12345                    ; fix #1
    12346                    ; fix #2

and then checking out the /trunk where these have been merged as
revision numbers:

    13925                    ; merge of 12345 from /user/keramida/foo
    13927                    ; merge of 12346 from /user/keramida/foo

The revision numbers are not the same, but the changes are all there :)

> Also, what happens if the contributor makes a change subsequent to you
> having synchronized with their tree - what would they have to do in
> this case?

They would have to transplant _that_ change, or re-rebase.  The rebase
extension is useful with MQ when you rebase multiple times, because the
following may happen:

    1. A contributor creates changes A and B on top of 'main'.  The
       contributor branch now has a history of:

                 [1] -- [2] -- [A] -- [B]

    2. Someone else commits in the 'main' branch another change:

                 [1] -- [2] -- [3]

    3. The contributor pulls [3] and rebases:

                 [1] -- [2] -- [3] -- [A'] -- [B']

    4. Another change is made in 'main':

                 [1] -- [2] -- [3] -- [4]

    5. One of the maintainers of 'main' pulls from the contributor and
       rebases on top of [4].  Immediately after the pull the history
       will look like this:

                 [1] -- [2] -- [3] -- [4]
                                \
                                 `-- [A'] -- [B]

       After the second rebase the 'main' branch will be:

                 [1] -- [2] -- [3] -- [4] -- [A''] -- [B'']

    6. Now if the contributor pulls from the latest `main' branch he
       will end up with:

                 [1] -- [2] -- [3] -- [A'] -- [B']
                                 \
                                  `-- [4] -- [A''] -- [B'']

At this point there are two options for the contributor:

    (a) He can strip away and forget about the [A'] -- [B'] branch.
        They are already parts of the history as [A''] -- [B''].

    (b) He can create a new clone with:

                 hg clone -r "B''" old-repo new-clone

If in the mean time, the contributor has committed *more* stuff on top
of the history at step 3 above, then at step 6 he would have a history
like this:

                 [1] -- [2] -- [3] -- [A'] -- [B'] -- [C]
                                 \
                                  `-- [4] -- [A''] -- [B'']

This means he can selectively rebase changeset [C] before throwing away
the stale changes:

                 hg rebase -s C -d "B''"
                 hg strip "A'"

That would create a history like:

                 [1] -- [2] -- [3] -- [4] -- [A''] -- [B''] -- [C']


>> Another important detail is that if the 'main' branch changes *again*
>> while you are rebasing one set of changesets, you may have to repeat
>> the rebase operation.  With a 'main' repository that does not have a
>> huge amount of traffic, this may be ok.  In a large project where
>> things are being pushed (or pulled into) very fast, this may cause an
>> endless rebase loop.
>
> That's good to know. Would rebasing to a branch in the main repo make
> this any better, i.e. if you have some kind of policy where
> effectively only one developer is working on a particular branch at
> the same time and therefore (by disciplin) eliminate the possibility
> of having the target branch change?

That would help, indeed :)



More information about the Mercurial mailing list