[PATCH] Make fast forward merges more like normal merges.

Alexis S. L. Carvalho alexis at cecm.usp.br
Wed Jun 6 20:38:52 CDT 2007


Thus spake Eric M. Hopper:
> On Wed, 2007-06-06 at 17:46 -0700, Brendan Cully wrote:
> > On Wednesday, 06 June 2007 at 19:44, Nathan Jones wrote:
> > > I have been using named branches and fast forward merges lately, but I
> > > have found that fast forward merges work differently than normal merges:
> > > 
> > > 1. Parents are not listed.
> > > 2. hg log -M displays fast forward merges.
> > > 3. hg log -p does not display a diff like regular merges.
> > 
> > I don't have a super-strong opinion about it, but I'm not sure these
> > are bad things. It seems like you're turning fast-forward merges back
> > into plain old merges.
> 
> What are fast forward merges, and why were they created?

"Fast-forward merge" is a term that comes from git.  I think the "merge"
here means the act of merging, not a merge revision (i.e. a revision
with more than one parent).

Forget about named branches for a moment.  Say the revision graph looks
originally like:

        a
o---o---o


Now suppose I clone that and start committing and now I have

        a
o---o---o
         \          b
          --o---o---o

If you pull my changes and try to merge, you'll get a "there is nothing to
merge, just use 'hg update'".  And indeed, there's no need to merge
them, since one revision is an ancestor of the other.

(In git, if you do the equivalent operations, the system would just move
the current branch name[1] (which is pointing at "a") to "b",
effectively "fast-forwarding" it.  Note that in this case, there's no
commit involved in this "merge", so it gets this special name.)

Enter named branches.  Suppose you were using the branch "default", and
I used a branch "issue1024":

        a
D---D---D
         \          b
          --I---I---I

You reviewed my changes and want to include them in the "default"
branch (i.e. you want a "hg pull -r default" to include my changes).

Because we store the branch name in the changeset itself, you /have/ to
add another commit on top of "b".  Right now the only parent of this new
commit is "b" (since there's no actual need to merge):

        a               c
D---D---D               D
         \          b  /
          --I---I---I--

But even though we say that "this is a merge; don't forget to commit",
it's not /really/ a merge, because the new revision has only 1 parent.
The patch is essentially suggesting we do a real merge:

        a               c
D---D---D---------------D
         \          b  /
          --I---I---I--

Personal opinion: since we have to add a new revision anyway, I think we
might as well make it a real merge.

I haven't tried the patch, but I think just setting adding the second
parent in the dirstate should be enough; no need to change the status of
other files... but maybe I missed something there.

Alexis

[1] - in git, a branch name is essentially a pointer to a revision,
which is moved every time you commit (or do a fast-forward merge...)


More information about the Mercurial-devel mailing list