threads / discuss / 10923

git merge no longer handles add/add

Subject: git merge no longer handles add/add

## tl;dr

8 messages between Nov 19, 2007 and Nov 20, 2007.

replies: 7people: 5as markdown or json

Martin Langhoff· Nov 19, 2007, 03:18 UTC · lore

git used to be really good at merging 2 branches that had gotten the same code added independently. Right now, both master (1.5.3.5.737.gdee1b) and next (9445b41) are telling me that the exact same file (same sha1), with the same mode added on 2 branches is a merge conflict. On _one_ of the branches there is an extra commit.

Hmmm.

I am pretty sure that early git (pre 1.0) could handle this correctly. I remember sending git-archimport to Junio and immediately doing 3 or 4 commits on top, and having the next pull work correctly without conflict because the merge machinery spotted the "last common sha1" for that file and saw that only one side had changed since then.

Happens with recursive and resolve. Happy to provide a minimal repro case, but I think this is fairly obvious...

cheers,
martin
Martin Langhoff· Nov 19, 2007, 03:29 UTC · re: Martin Langhoff · lore

Re: git merge no longer handles add/add

On Nov 19, 2007 4:18 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:
> Happens with recursive and resolve. Happy to provide a minimal repro
> case, but I think this is fairly obvious...
Steps to repro...
    mkdir repro
    cd repro/
    cp /etc/resolv.conf ./resolv.conf
    git init
    git add resolv.conf
    git commit -m 'a' resolv.conf
    cp resolv.conf resolv-1.conf
    git add resolv-1.conf
    git commit -m 'a1' resolv-1.conf
    echo blabla >> resolv-1.conf
    git commit -m 'a2' resolv-1.conf
    git-branch other HEAD^^
    git checkout other
    cp resolv.conf resolv-1.conf
    git add resolv-1.conf
    git commit -m 'b'
    git checkout master
    git merge other
    ...
   Auto-merged resolv-1.conf
   CONFLICT (add/add): Merge conflict in resolv-1.conf
   Automatic merge failed; fix conflicts and then commit the result.
m
Junio C Hamano· Nov 19, 2007, 06:43 UTC · re: Martin Langhoff · lore

Re: git merge no longer handles add/add

"Martin Langhoff" <martin.langhoff@gmail.com> writes:
Show 16 quoted lines
> On Nov 19, 2007 4:18 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:
>> Happens with recursive and resolve. Happy to provide a minimal repro
>> case, but I think this is fairly obvious...
>
> Steps to repro...
>
>     mkdir repro
>     cd repro/
>     cp /etc/resolv.conf ./resolv.conf
>     git init
>     git add resolv.conf
>     git commit -m 'a' resolv.conf
>     cp resolv.conf resolv-1.conf
>     git add resolv-1.conf
>     git commit -m 'a1' resolv-1.conf
>     echo blabla >> resolv-1.conf
      **************
Show 12 quoted lines
>     git commit -m 'a2' resolv-1.conf
>     git-branch other HEAD^^
>     git checkout other
>     cp resolv.conf resolv-1.conf
>     git add resolv-1.conf
>     git commit -m 'b'
>     git checkout master
>     git merge other
>     ...
>    Auto-merged resolv-1.conf
>    CONFLICT (add/add): Merge conflict in resolv-1.conf
>    Automatic merge failed; fix conflicts and then commit the result.

As far as the point of the merge is concerned, that's an add/add of _different_ contents, and we have always left the conflict to resolve for you since day one. The only case we handle without complaining is the accidental *clean* merge. Both branches adds the path *identically* compared to the common ancestor.

The very initial implementation of merge may have used the total emptyness as the common ancestor for the merge, and later we made it a bit more pleasant to resolve by computing the common part of the file from the two branches to be used as a fake ancestor contents. But the fact we left the result as conflict for you to validate hasn't changed and will not change.

Martin Langhoff· Nov 19, 2007, 18:33 UTC · re: Junio C Hamano · lore

Re: git merge no longer handles add/add

On Nov 19, 2007 7:43 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 5 quoted lines
> As far as the point of the merge is concerned, that's an add/add
> of _different_ contents, and we have always left the conflict to
> resolve for you since day one.  The only case we handle without
> complaining is the accidental *clean* merge.  Both branches adds
> the path *identically* compared to the common ancestor.

Even if the 2 paths did have matching content at one point? In fact, the 2 files here get added with identicaly content and one of them is later modified...

Show 6 quoted lines
> The very initial implementation of merge may have used the total
> emptyness as the common ancestor for the merge, and later we
> made it a bit more pleasant to resolve by computing the common
> part of the file from the two branches to be used as a fake
> ancestor contents.  But the fact we left the result as conflict
> for you to validate hasn't changed and will not change.

In this case, if you use the common part (100%) as the ancestor, then you get a _clean_ merge. The file is added on both sides identically, and then it changes on one side.

I'll see if I can repro with an older git install...
m
J. Bruce Fields· Nov 19, 2007, 18:46 UTC · re: Martin Langhoff · lore

Re: git merge no longer handles add/add

On Tue, Nov 20, 2007 at 07:33:27AM +1300, Martin Langhoff wrote:
Show 21 quoted lines
> On Nov 19, 2007 7:43 PM, Junio C Hamano <gitster@pobox.com> wrote:
> > As far as the point of the merge is concerned, that's an add/add
> > of _different_ contents, and we have always left the conflict to
> > resolve for you since day one.  The only case we handle without
> > complaining is the accidental *clean* merge.  Both branches adds
> > the path *identically* compared to the common ancestor.
> 
> Even if the 2 paths did have matching content at one point? In fact,
> the 2 files here get added with identicaly content and one of them is
> later modified...
> 
> > The very initial implementation of merge may have used the total
> > emptyness as the common ancestor for the merge, and later we
> > made it a bit more pleasant to resolve by computing the common
> > part of the file from the two branches to be used as a fake
> > ancestor contents.  But the fact we left the result as conflict
> > for you to validate hasn't changed and will not change.
> 
> In this case, if you use the common part (100%) as the ancestor, then
> you get a _clean_ merge. The file is added on both sides identically,
> and then it changes on one side.

That sounds like an inevitable consequence of git's design--it only uses a global (not a per-file) common ancestor.

--b.
Junio C Hamano· Nov 19, 2007, 19:25 UTC · re: Martin Langhoff · lore

Re: git merge no longer handles add/add

"Martin Langhoff" <martin.langhoff@gmail.com> writes:
Show 10 quoted lines
> On Nov 19, 2007 7:43 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> As far as the point of the merge is concerned, that's an add/add
>> of _different_ contents, and we have always left the conflict to
>> resolve for you since day one.  The only case we handle without
>> complaining is the accidental *clean* merge.  Both branches adds
>> the path *identically* compared to the common ancestor.
>
> Even if the 2 paths did have matching content at one point? In fact,
> the 2 files here get added with identicaly content and one of them is
> later modified...
A merge does not look at the history.

It _does_ look at the history to figure out what the common ancestors are, but after finding them out, the "file history" is not examined by following each step in the ancestry chain (that would have been the "blame merge").

Show 10 quoted lines
>> The very initial implementation of merge may have used the total
>> emptyness as the common ancestor for the merge, and later we
>> made it a bit more pleasant to resolve by computing the common
>> part of the file from the two branches to be used as a fake
>> ancestor contents.  But the fact we left the result as conflict
>> for you to validate hasn't changed and will not change.
>
> In this case, if you use the common part (100%) as the ancestor, then
> you get a _clean_ merge. The file is added on both sides identically,
> and then it changes on one side.

Exactly. We may keep conflict markers in the file left in the work tree to highlight which lines are unique to the side that added more (iow, one group of lines delimited by <<< === >>> is empty while the other is not) but this is currently treated as "fishy, needs human validation" to catch mismerges.

Jakub Narebski· Nov 19, 2007, 19:56 UTC · re: Junio C Hamano · lore

Re: git merge no longer handles add/add

Junio C Hamano wrote:
Show 5 quoted lines
> Exactly.  We may keep conflict markers in the file left in the
> work tree to highlight which lines are unique to the side that
> added more (iow, one group of lines delimited by <<< === >>> is
> empty while the other is not) but this is currently treated as
> "fishy, needs human validation" to catch mismerges.

BTW can xdifflib merge use original diff3 conflict markers, i.e. <<< [main] |||| [ancestor] === [branch] >>>?

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Johannes Schindelin· Nov 20, 2007, 01:15 UTC · re: Jakub Narebski · lore

Re: git merge no longer handles add/add

Hi,
On Mon, 19 Nov 2007, Jakub Narebski wrote:
Show 10 quoted lines
> Junio C Hamano wrote:
> 
> > Exactly. ?We may keep conflict markers in the file left in the work 
> > tree to highlight which lines are unique to the side that added more 
> > (iow, one group of lines delimited by <<< === >>> is empty while the 
> > other is not) but this is currently treated as "fishy, needs human 
> > validation" to catch mismerges.
> 
> BTW can xdifflib merge use original diff3 conflict markers, i.e. <<< 
> [main] |||| [ancestor] === [branch] >>>?

There was a patch floating around which added git-diff3, just after I went public with my xmerge patch. This seemed to have the code you look for.

Ciao, Dscho

P.S.: I will refuse to reply to you in future whenever you do not Cc: me.

← back to recent threads