Subject: Re: [boost] [GitHelp] (Mis-)Understanding merge
From: Edward Diener (eldiener_at_[hidden])
Date: 2014-02-26 09:23:38
On 2/26/2014 3:42 AM, Daniel James wrote:
> On 26 February 2014 08:12, Edward Diener <eldiener_at_[hidden]> wrote:
>> Yes, how did you figure that out ?
> I went to https://github.com/boostorg/ and looked at what had been
> recently changed.
>>> there are a lot of
>>> differences between master and your merge base, when you merge git
>>> won't take these into account - it only deals with changes made after
>>> the last merge.
>> I thought Git was always smart enough to find the merge base and then do a
>> three way merge between the merge base, the commit being merged to and the
>> commit being merged from.
> The three way merge works by looking at the differences between the
> merge base and the two heads. Just considering this file, in 'develop'
> the file is unchanged. In 'master' the file is in the merge base, but
> not in master, so git assumes the file has been removed - remember it
> only looks at those three revisions, and none others. Since there's no
> change on the develop branch, but there is on the master branch, git
> picks the master branch.
Just for the sake of argument:
'develop' has file
'master' does not have file
'merge base' has file
I tell git to merge from 'develop' to 'master'.
Why would not git see that a file which is in 'develop' and is in the
'merge base' but is not in 'master', needs to be added to 'master' as
part of the three way merge ?
> Git doesn't normally make mistakes like this when the merge history is
> usually more accurate. Although there are some rare edge cases .
It just seems like incorrect 3-way merging logic to me.
>>> This is the tricky thing about transitioning from
>>> subversion to git, they have different models of merging, subversion
>>> is based on tracking individual changesets, git is based on the
>>> history graph. You could try finding the old changesets that haven't
>>> been merged and cherry pick them.
>> This would theoretically mean that I would have to go one by one through
>> every 'develop' change. Ugh ! I thought Git was supposed to save me from
>> having to do all that tedious work.
> It typically does, but in this case it doesn't have a decent merge
> history as that's really difficult to extract from our complicated and
> messy subversion merge history. You don't have to go through every
> change, you can look at the differences between master and develop,
> and then use 'git log' and 'git annotate' to find which revision they
> come from. Although that gets a lot harder when there's a mix of
> merged and unmerged changes.
>>> But even after doing that there are still a lot of old changes that
>>> need to be merged, mainly in the documentation:
>>> You could try to track down all the appropriate changes, but IMO the
>>> best thing to do is to get develop to a release-worthy point and just
>>> overwrite master from develop.
>> I could do that. If I did do I just push 'develop' to 'origin/master' ?
>> I could also, after having done my local merge, just do a 'git diff master
>> develop' and then update master with appropriate changes.
> Don't just push develop to origin/master as that will break history.
You are right. I forgot about the history.
> There actually used to be a command for doing this kind of merge, but
> the git developers decided it was a bad idea and removed it. Here's
> the way I emulate it:
> # Make sure we're up to date and on the right branch
> git fetch
> git checkout master
> # Cheap way to tell git that this is a merge:
> git merge --no-commit -s ours origin/develop
> # Copy changes over from develop:
> git diff --binary origin/develop | git apply -R --index
> # Commit the "merge"
> git commit
> I got that technique from http://stackoverflow.com/a/5211321/2434
> Once that's done you should be able to merge normally in the future.
Thanks ! I need to do more reading about 'merge'.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk