Gentoo Archives: gentoo-dev

From: Kent Fredric <kentfredric@×××××.com>
To: gentoo-dev@l.g.o
Subject: Re: [gentoo-dev] Re: Portage Git migration - clean cut or git-cvsserver
Date: Fri, 01 Jun 2012 08:41:29
In Reply to: Re: [gentoo-dev] Re: Portage Git migration - clean cut or git-cvsserver by Dirkjan Ochtman
On 1 June 2012 20:16, Dirkjan Ochtman <djc@g.o> wrote:
> Can you elaborate on why the cleaner history a no-merge policy > enforces is a good thing? I actually think that seeing merge commits > might clarify the history; it can be valuable to see that some mistake > was made in a merge instead, but you can only see that if there's an > explicit merge commit. > > I should note that I come at this from the Mercurial side, where the > immutability of (public) history has historically carried more value > than on the git side (and related to that, rebase-like tools were less > integrated until relatively recently). > > Cheers, > > Dirkjan >
One of the perk of fast-forward only histories is merge problems don't happen. If a commit sequence isn't fast-fowardable, then the submitter has to rebase it, and a rebased history is a guaranteed clean merge. It also puts the onus on making the patch sequence mergable on the contributor of that patch sequence, by forcing them to resolve conflicts before they can submit their branch for inclusion, and this is good, because they understand their own changes best, and are the best person to decide how to deal with conflicts. The best example of this is 2 people contribute behaviourally identical code, with different syntax . In the case of a merge, the person performing the merge has to decide which one to take, and they might not be the best person to do so. ( And historically, it can be confusing if you look at the parents of the merge, and find the 2 competing implementations, of which only 1 is relevant ) If you request that a branch is rebased before it is integrated, then this problem solves itself in a way. Whoevers implementation gets in the tree first gets in, and then the second person rebases their branch on top of that. In the process of performing the rebase, the second person will discover the precise commit on their side that introduces a conflict, and be able to decide if they need to replace the existing code anyway, or if they need to destroy their own code. And when they're done, their entire commit series should be sane and logical as if the first persons code was there in the first place before the second person even started coding. a--->b--->c---->d--->e--->f    | \|/ \--->x--->y---->z Essentially, in this diagram, if d and y are different, but equivalent, they will cause a collision when merge Z is performed. By performing a rebase of the second branch, the logical order becomes a--->b--->c---->d--->e--->f--->x--->y--->z And when the rebaser is applying "y", they will notice it is likely redundant, and the history will become a--->b--->c---->d--->e--->f--->x--->z And in both the merge and rebase examples, z will be the same, just the cognitive overhead of understanding "what the hell happened" in the latter case is simpler, as the biggest delta between any 2 commits will be 1 commit worth, whereas in the merge case, there will be a huge delta between the commit before the merge, and the commit after the merge, and looking at the merge itself diff-wise, you'll be comparing the aggregate result of 2 entire branches worth of commits, as opposed to only comparing one small and simple commit with another. -- Kent perl -e  "print substr( \"edrgmaM  SPA NOcomil.ic\\@tfrken\", \$_ * 3, 3 ) for ( 9,8,0,7,1,6,5,4,3,2 );"