threads / discuss / 16520

more merge strategies : feature request

Subject: more merge strategies : feature request

## tl;dr

13 messages between Nov 29, 2008 and Dec 4, 2008.

replies: 12people: 6as markdown or json

Caleb Cushing· Nov 29, 2008, 16:48 UTC · lore

conflict: this strategy would always resolve in a merge conflict allowing you to use git mergetool to piece the files back together.

no-overwrite: if a change from the branch being merged in would overwrite something in the current branch don't merge it. (I think it needs a better name)

-- 
Caleb Cushing
Andreas Ericsson· Dec 1, 2008, 09:18 UTC · re: Caleb Cushing · lore

Re: more merge strategies : feature request

Caleb Cushing wrote:
Show 7 quoted lines
> conflict: this strategy would always resolve in a merge conflict
> allowing you to use git mergetool to piece the files back together.
> 
> no-overwrite: if a change from the branch being merged in would
> overwrite something in the current branch don't merge it. (I think it
> needs a better name)
> 

If you could come up with use-cases where each would be useful, I think you'd have a much easier time to gain acceptance for your suggestions. Right now, you're saying "I want a red button" but you're not explaining what it's for.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231
Caleb Cushing· Dec 2, 2008, 02:38 UTC · re: Andreas Ericsson · lore

Re: more merge strategies : feature request

>  If you could come up with use-cases where each would be useful, I
>  think you'd have a much easier time to gain acceptance for your
>  suggestions. Right now, you're saying "I want a red button" but
>  you're not explaining what it's for.

conflict: when auto-merging isn't merging the way you want it too, but you still want to see the diffs and handle them by hand. no commit won't do this, it just doesn't commit. I've had 2 situations now where git's fast-forward has overwritten changes in a branch I didn't want it to, it would have been better if I could handle them by hand without having to have 1 terminal open to the diff and the other open to the editor to fix it. and yes git was right by it's perspective, but the code it created was wrong by what I wanted and needed. I'm not really sure what more of a use case is needed for this.

no-overwrite: it's basically my way of saying that even though git thinks it's changes are newer and better than the ones in my branch I know they aren't. I only want the new stuff from the other branch. In the second situation mentioned above I have 2 branches that I like to merge back and forth, each needing a specific set of changes to certain files however most changes are shared. when I merge them I often have to change those specific changes back, if it didn't ovewrite them I wouldn't have a problem.

for example I'm tracking my dot files with git, in my main user account I set umask 077 however in my web development account I need umask 027 so apache can read the files I create. when I create a change in webdev and need to merge it back into master it overwrites the 077 umask which I then change back. when I create a change in master that I want in webdev it then changes webdev's umask. very annoying.

the other problem I had was where I'd overwritten a file in another branch just for the point of merging it into the master branch so I could see the differences, and handle them properly (as I see it) unfortunately git felt that this file was newer and simply overwrote the changes in master. this was incorrect they were simply different versions of the same type of file, like comparing an httpd.conf from a gentoo and another from a fedora system. I was merely trying to figure the best of both files to get the results I wanted.

technically the conflict strategy I propose would be adequate for both but the no-overwrite seems like a good idea as well.

-- 
Caleb Cushing
Jeff King· Dec 2, 2008, 03:30 UTC · re: Caleb Cushing · lore

Re: more merge strategies : feature request

On Mon, Dec 01, 2008 at 09:38:07PM -0500, Caleb Cushing wrote:
Show 9 quoted lines
> conflict: when auto-merging isn't merging the way you want it too, but
> you still want to see the diffs and handle them by hand. no commit
> won't do this, it just doesn't commit. I've had 2 situations now where
> git's fast-forward has overwritten changes in a branch I didn't want
> it to, it would have been better if I could handle them by hand
> without having to have 1 terminal open to the diff and the other open
> to the editor to fix it. and yes git was right by it's perspective,
> but the code it created was wrong by what I wanted and needed. I'm not
> really sure what more of a use case is needed for this.

It's not clear to me exactly what you want. Let's say I have a file 'foo' with changes from my merged branches in two different spots. For example:

 merge base     branch A      branch B
    1              2             1
    2              3             2
    3              4             3
    4              5             4
    5

Did you want conflict markers in the resulting file? If so, what should the conflict markers look like, since there isn't actually a conflict?

Alternatively, you could have git leave the file in an unmerged state, and then access the base, ours, and theirs version from the index (or even use git mergetool). Then you would get your desired versions into the merging tool of your choice.

Of course, you could also just use a custom merge driver to accomplish the same thing:

  git config merge.xxdiff.driver 'xxdiff %A %O %B'
  echo '* merge=xxdiff' >.gitattributes
  git merge your-branch

and of course you can specify whatever subset of files you want to actually do this for instead of '*'.

-Peff
Caleb Cushing· Dec 2, 2008, 14:28 UTC · re: Jeff King · lore

Re: more merge strategies : feature request

>
> It's not clear to me exactly what you want. Let's say I have a file
>  ....
I'm afraid I don't fully understand your example

lets say git merge foo bar foo bar 1 1 2 8 3 3 4 4 5 5 6 7

lines 6 and 7 are new in foo line 2 has a conflict because the other head has an 8, history wise because of an early merge the other direction and fix, there was the 8 in foo and it was changed to a 2, when I merge back it will overwrite the 8 with a 2. however I need the 8 to be the 8 and the 2 to be the 2. but I want the 6 and 7 in both.

conflict would create a conflict
such as

foo 1 <<<<<< bar 8 ====== 2

>>>>>>  foo

3 4 5 6 7

no overwrite would result in file1 looking like this

1 8 3 4 5 6 7

>  Did you want conflict markers in the resulting file? If so, what should
>  the conflict markers look like, since there isn't actually a conflict?

if the the remote and local branches are not identical there's a difference which should be able to result in a conflict. for all purposes I'm not sure git couldn't just ignore the history of the files and do a straight head to head merge. the steps you suggest make it more complicated than it needs to be an if done post merge or without merge will probably be need to be done again in a future merge if merging back and forth

-- 
Caleb Cushing
Jeff King· Dec 2, 2008, 15:30 UTC · re: Caleb Cushing · lore

Re: more merge strategies : feature request

On Tue, Dec 02, 2008 at 09:28:41AM -0500, Caleb Cushing wrote:
Show 12 quoted lines
> I'm afraid I don't fully understand your example
> 
> 
> lets say git merge foo bar
> foo          bar
> 1             1
> 2              8
> 3              3
> 4              4
> 5              5
> 6
> 7

I notice that you don't have a "merge base" here, which is an important part of determining conflicts. So if you are proposing to not look at the history at all, and just show all differences, then that is different from what I thought you meant.

Show 23 quoted lines
> lines 6 and 7 are new in foo line 2 has a conflict because the other
> head has an 8, history wise because of an early merge the other
> direction and fix, there was the 8 in foo and it was changed to a 2,
> when I merge back it will overwrite the 8 with  a 2. however I need
> the 8 to be the 8 and the 2 to be the 2. but I want the 6 and 7 in
> both.
>
> conflict would create a conflict
> 
> such as
> 
> foo
> 1
> <<<<<< bar
> 8
> ======
> 2
> >>>>>>  foo
> 3
> 4
> 5
> 6
> 7

OK, so assume we throw away history and just look at the diff between the two branches. How do we know that a conflict should be created for the 2 vs 8, but not for the added "6 7" at the end? I think you have to create a conflict marker for both and fix them up manually. Like:

    1
    <<<<<<< foo
    2
    =======
    8
    >>>>>>> bar
    3
    4
    5
    <<<<<<< foo
    6
    7
    =======
    >>>>>>> bar

The script below munges a diff into conflict markers (and created the output you see above). Note that it is very hacky and not very tested. And note that at this point this really has nothing to do with _git_ specifically, since we aren't even using history. This just generates conflict markers from two files. There may be a more mature tool that can accomplish the same thing (personally, I would use something like xxdiff to do an interactive merge in your case).

You can try it with:
  git config merge.conflict.driver 'perl /path/to/conflict.pl %A %B'
  echo '* merge=conflict' >.gitattributes

-->8 conflict.pl 8<-- #!/usr/bin/perl

use strict; use warnings qw(all FATAL);

my $fn1 = shift; my $fn2 = shift;

open(my $diff, '-|', qw(diff -U 999999), $fn1, $fn2)
  or die "unable to run diff: $!";
open(my $tmp, '>', "$fn1.tmp")
  or die "unable to open temporary file: $!";
select $tmp;
while(<$diff>) {
  last if /^@/;
}
sub start   { print "<<<<<<< $fn1\n" }
sub divider { print "=======\n" }
sub end     { print ">>>>>>> $fn2\n" }
my $conflict = 0;
while(<$diff>) {
  if (/^ (.*)/) {
    if    ($conflict == 0) { }
    elsif ($conflict == 1) { divider; end }
    elsif ($conflict == 2) { end }
    print $1, "\n";
    $conflict = 0;
  }
  elsif(/^-(.*)/) {
    if    ($conflict == 0) { start }
    elsif ($conflict == 1) { }
    elsif ($conflict == 2) { end; start }
    print $1, "\n";
    $conflict = 1;
  }
  elsif(/^\+(.*)/) {
    if    ($conflict == 0) { start; divider }
    elsif ($conflict == 1) { divider }
    elsif ($conflict == 2) { }
    print $1, "\n";
    $conflict = 2;
  }
}

if ($conflict == 0) { } elsif ($conflict == 1) { divider; end } elsif ($conflict == 2) { end }

close($tmp); rename "$fn1.tmp", $fn1; exit 1;

Leo Razoumov· Dec 2, 2008, 02:49 UTC · re: Andreas Ericsson · lore

Re: more merge strategies : feature request

On 12/1/08, Andreas Ericsson <ae@op5.se> wrote:
Show 9 quoted lines
> Caleb Cushing wrote:
>
> > conflict: this strategy would always resolve in a merge conflict
> > allowing you to use git mergetool to piece the files back together.
> >
> > no-overwrite: if a change from the branch being merged in would
> > overwrite something in the current branch don't merge it. (I think it
> > needs a better name)
> >
I guess that "no-overwrite" can be achieved by
git merge -s ours --no-commit
--Leo--
Caleb Cushing· Dec 2, 2008, 13:46 UTC · re: Leo Razoumov · lore

Re: more merge strategies : feature request

> I guess that "no-overwrite" can be achieved by
>
>  git merge -s ours --no-commit

no it doesn't. which is why I called it a bad name. no-overwrite would still add new lines to the file not in ours (and no-commit isn't needed in that case) it just wouldn't overwrite conflicting lines, my understanding of ours is that it will keep the files as is. Caleb Cushing

Leo Razoumov· Dec 3, 2008, 01:07 UTC · re: Caleb Cushing · lore

Re: more merge strategies : feature request

On 12/2/08, Caleb Cushing <xenoterracide@gmail.com> wrote:
Show 12 quoted lines
> > I guess that "no-overwrite" can be achieved by
>  >
>  >  git merge -s ours --no-commit
>
>
> no it doesn't. which is why I called it a bad name. no-overwrite would
>  still add new lines to the file not in ours (and no-commit isn't
>  needed in that case) it just wouldn't overwrite conflicting lines, my
>  understanding of ours is that it will keep the files as is.
>
> Caleb Cushing
>
>From your original email in this thread

"no-overwrite: if a change from the branch being merged in would overwrite something in the current branch don't merge it. (I think it needs a better name)"

I got the impression that you would like to preserve "ours" branch whenever other branch tries to overwrite something? Is it "no-override-conflicting-lines" that you are really after?

--Leo--
Nanako Shiraishi· Dec 3, 2008, 21:27 UTC · re: Leo Razoumov · lore

Re: more merge strategies : feature request

Quoting "Leo Razoumov" <slonik.az@gmail.com>:
Show 9 quoted lines
> On 12/2/08, Caleb Cushing <xenoterracide@gmail.com> wrote:
>> > I guess that "no-overwrite" can be achieved by
>>  >
>>  >  git merge -s ours --no-commit
>>
>> no it doesn't. which is why I called it a bad name. no-overwrite would
>>  still add new lines to the file not in ours (and no-commit isn't
>>  needed in that case) it just wouldn't overwrite conflicting lines, my
>>  understanding of ours is that it will keep the files as is.
Isn't what Caleb wants "-X ours/theirs" per-hunk option for merge strategy backends?
It was discussed several months ago on the list and was rejected.  For details you can start here:
    http://thread.gmane.org/gmane.comp.version-control.git/89010/focus=89021
I still think the patch in the above link was reasonable, but the thread was distracted into discussing minor syntactical details of how the option gets passed to the backend, and the rest of the discussion to decide if it makes sense to add such a feature was unfortunately lost in the noise and never concluded.
-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
Caleb Cushing· Dec 3, 2008, 22:59 UTC · re: Nanako Shiraishi · lore

Re: more merge strategies : feature request

> Isn't what Caleb wants "-X ours/theirs" per-hunk option for merge strategy backends?

just from this description it sounds like it. I can't say anything about that patch, but to me having such a strategy only makes sense.

-- 
Caleb Cushing
Junio C Hamano· Dec 4, 2008, 02:15 UTC · re: Nanako Shiraishi · lore

Re: more merge strategies : feature request

Nanako Shiraishi <nanako3@lavabit.com> writes:
Show 11 quoted lines
> Isn't what Caleb wants "-X ours/theirs" per-hunk option for merge strategy backends?
>
> It was discussed several months ago on the list and was rejected.  For details you can start here:
>
>     http://thread.gmane.org/gmane.comp.version-control.git/89010/focus=89021
>
> I still think the patch in the above link was reasonable, but the thread
> was distracted into discussing minor syntactical details of how the
> option gets passed to the backend, and the rest of the discussion to
> decide if it makes sense to add such a feature was unfortunately lost in
> the noise and never concluded.

I thought http://article.gmane.org/gmane.comp.version-control.git/89033 in the thread (and your response to it which is 89175) pretty much concluded the discussion. Is Caleb adding anything new to the discussion (iow, is there a convincing new argument why having such a merge is a good idea and what the workflow looks like that benefits from it)?

Nanako Shiraishi· Dec 4, 2008, 10:11 UTC · re: Junio C Hamano · lore

Re: more merge strategies : feature request

Quoting Junio C Hamano <gitster@pobox.com>:
Show 5 quoted lines
> I thought http://article.gmane.org/gmane.comp.version-control.git/89033 in
> the thread (and your response to it which is 89175) pretty much concluded
> the discussion.  Is Caleb adding anything new to the discussion (iow, is
> there a convincing new argument why having such a merge is a good idea and
> what the workflow looks like that benefits from it)?
I first thought so, but after reading this feature request thread again I do not think so anymore.
Sorry for the noise.
-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/

← back to recent threads