git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Guided merge with override
@ 2008-06-16  4:16 Geoff Russell
  2008-06-16  9:25 ` Miklos Vajna
  0 siblings, 1 reply; 23+ messages in thread
From: Geoff Russell @ 2008-06-16  4:16 UTC (permalink / raw)
  To: git

I have a two repositories A and B.  B is a tiny subset of the files in
A and all have been
modified.   If I do a "git pull B" into A, I get conflicts. I always
want to resolve these
by accepting the version from B. Is there a magic "override" switch to
let me do this?

Cheers,
Geoff Russell

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-16  4:16 Guided merge with override Geoff Russell
@ 2008-06-16  9:25 ` Miklos Vajna
  2008-06-16 10:16   ` Johannes Sixt
  0 siblings, 1 reply; 23+ messages in thread
From: Miklos Vajna @ 2008-06-16  9:25 UTC (permalink / raw)
  To: Geoff Russell; +Cc: git

[-- Attachment #1: Type: text/plain, Size: 512 bytes --]

On Mon, Jun 16, 2008 at 01:46:38PM +0930, Geoff Russell <geoffrey.russell@gmail.com> wrote:
> I have a two repositories A and B.  B is a tiny subset of the files in
> A and all have been
> modified.   If I do a "git pull B" into A, I get conflicts. I always
> want to resolve these
> by accepting the version from B. Is there a magic "override" switch to
> let me do this?

There was a thread about this:

http://thread.gmane.org/gmane.comp.version-control.git/84047

and then you can do a git pull -s theirs B.

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-16  9:25 ` Miklos Vajna
@ 2008-06-16 10:16   ` Johannes Sixt
  2008-06-16 21:16     ` Miklos Vajna
  2008-06-16 22:21     ` Sverre Rabbelier
  0 siblings, 2 replies; 23+ messages in thread
From: Johannes Sixt @ 2008-06-16 10:16 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: Geoff Russell, git

Miklos Vajna schrieb:
> On Mon, Jun 16, 2008 at 01:46:38PM +0930, Geoff Russell <geoffrey.russell@gmail.com> wrote:
>> I have a two repositories A and B.  B is a tiny subset of the files in
>> A and all have been
>> modified.   If I do a "git pull B" into A, I get conflicts. I always
>> want to resolve these
>> by accepting the version from B. Is there a magic "override" switch to
>> let me do this?
> 
> There was a thread about this:
> 
> http://thread.gmane.org/gmane.comp.version-control.git/84047
> 
> and then you can do a git pull -s theirs B.

I don't think that's what Geoff needs. The 'theirs' strategy replaces the
entire tree by 'their' - B's - tree. But IIUC, only the subset of files
that are contained in B should be replaced by B's version, the rest of the
files should remain unchanged. This is quite different from 'theirs' strategy.

The solution depends on whether *all* files in B should be taken, or only
those files in B where there's a merge conflict. I don't know an easy way
to do the former, but the latter I'd do like this:

	$ git diff --name-only | xargs git checkout B --

-- Hannes

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-16 10:16   ` Johannes Sixt
@ 2008-06-16 21:16     ` Miklos Vajna
  2008-06-16 22:21     ` Sverre Rabbelier
  1 sibling, 0 replies; 23+ messages in thread
From: Miklos Vajna @ 2008-06-16 21:16 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Geoff Russell, git

[-- Attachment #1: Type: text/plain, Size: 465 bytes --]

On Mon, Jun 16, 2008 at 12:16:12PM +0200, Johannes Sixt <j.sixt@viscovery.net> wrote:
> I don't think that's what Geoff needs. The 'theirs' strategy replaces the
> entire tree by 'their' - B's - tree. But IIUC, only the subset of files
> that are contained in B should be replaced by B's version, the rest of the
> files should remain unchanged. This is quite different from 'theirs' strategy.

Thanks, I missed that difference, and sorry for the wrong suggestion.

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-16 10:16   ` Johannes Sixt
  2008-06-16 21:16     ` Miklos Vajna
@ 2008-06-16 22:21     ` Sverre Rabbelier
  2008-06-16 22:45       ` Geoff Russell
  2008-06-17  6:16       ` Guided merge with override Johannes Sixt
  1 sibling, 2 replies; 23+ messages in thread
From: Sverre Rabbelier @ 2008-06-16 22:21 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Miklos Vajna, Geoff Russell, git

On Mon, Jun 16, 2008 at 12:16 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> The solution depends on whether *all* files in B should be taken, or only
> those files in B where there's a merge conflict. I don't know an easy way
> to do the former, but the latter I'd do like this:
>
>        $ git diff --name-only | xargs git checkout B --

Wouldn't something similar work but do a 'git ls-files' and filter it
on files that have a merge conflict?

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-16 22:21     ` Sverre Rabbelier
@ 2008-06-16 22:45       ` Geoff Russell
  2008-06-17 20:04         ` Junio C Hamano
  2008-06-17  6:16       ` Guided merge with override Johannes Sixt
  1 sibling, 1 reply; 23+ messages in thread
From: Geoff Russell @ 2008-06-16 22:45 UTC (permalink / raw)
  To: sverre; +Cc: Johannes Sixt, Miklos Vajna, git

Thanks everybody,

On 6/17/08, Sverre Rabbelier <alturin@gmail.com> wrote:
> On Mon, Jun 16, 2008 at 12:16 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
>  > The solution depends on whether *all* files in B should be taken, or only
>  > those files in B where there's a merge conflict. I don't know an easy way
>  > to do the former, but the latter I'd do like this:
>  >
>  >        $ git diff --name-only | xargs git checkout B --

This looks like a manageable approach and better than the scripting I was
thinking about -- ie. scan the conflict files with perl and fix them!

Cheers,
Geoff

>
>
> Wouldn't something similar work but do a 'git ls-files' and filter it
>  on files that have a merge conflict?
>
>  --
>  Cheers,
>
>
>  Sverre Rabbelier
>


-- 
6 Fifth Ave,
St Morris, S.A. 5068
Australia
Ph: 041 8805 184 / 08 8332 5069

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-16 22:21     ` Sverre Rabbelier
  2008-06-16 22:45       ` Geoff Russell
@ 2008-06-17  6:16       ` Johannes Sixt
  2008-06-17  8:53         ` Sverre Rabbelier
  1 sibling, 1 reply; 23+ messages in thread
From: Johannes Sixt @ 2008-06-17  6:16 UTC (permalink / raw)
  To: sverre; +Cc: Miklos Vajna, Geoff Russell, git

Sverre Rabbelier schrieb:
> On Mon, Jun 16, 2008 at 12:16 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
>> The solution depends on whether *all* files in B should be taken, or only
>> those files in B where there's a merge conflict. I don't know an easy way
>> to do the former, but the latter I'd do like this:
>>
>>        $ git diff --name-only | xargs git checkout B --
> 
> Wouldn't something similar work but do a 'git ls-files' and filter it
> on files that have a merge conflict?

Well, you could 'git ls-files --unmerged', but that prints the whole index
entry, not just the name, and then you need a more complicated pipeline.

-- Hannes

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-17  6:16       ` Guided merge with override Johannes Sixt
@ 2008-06-17  8:53         ` Sverre Rabbelier
  2008-06-17  9:48           ` Johannes Schindelin
  0 siblings, 1 reply; 23+ messages in thread
From: Sverre Rabbelier @ 2008-06-17  8:53 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Miklos Vajna, Geoff Russell, git

On Tue, Jun 17, 2008 at 8:16 AM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> Sverre Rabbelier schrieb:
>> On Mon, Jun 16, 2008 at 12:16 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
>>> The solution depends on whether *all* files in B should be taken, or only
>>> those files in B where there's a merge conflict. I don't know an easy way
>>> to do the former, but the latter I'd do like this:
>>>
>>>        $ git diff --name-only | xargs git checkout B --
>>
>> Wouldn't something similar work but do a 'git ls-files' and filter it
>> on files that have a merge conflict?
>
> Well, you could 'git ls-files --unmerged', but that prints the whole index
> entry, not just the name, and then you need a more complicated pipeline.

How about 'git ls-files -t | grep "^M " | xargs git checkout B --',
that would list all files that are unmerged and check them out?

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-17  8:53         ` Sverre Rabbelier
@ 2008-06-17  9:48           ` Johannes Schindelin
  2008-06-17  9:53             ` Sverre Rabbelier
  0 siblings, 1 reply; 23+ messages in thread
From: Johannes Schindelin @ 2008-06-17  9:48 UTC (permalink / raw)
  To: sverre; +Cc: Johannes Sixt, Miklos Vajna, Geoff Russell, git

Hi,

On Tue, 17 Jun 2008, Sverre Rabbelier wrote:

> How about 'git ls-files -t | grep "^M " | xargs git checkout B --',

You probably meant 'sed -n "s/^M //p"' instead of 'grep "^M"', right?

Of course, I think that a better way would be to ask "git diff 
--name-only --diff-filter=U".

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-17  9:48           ` Johannes Schindelin
@ 2008-06-17  9:53             ` Sverre Rabbelier
  2008-06-17 10:17               ` Johannes Schindelin
  0 siblings, 1 reply; 23+ messages in thread
From: Sverre Rabbelier @ 2008-06-17  9:53 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Johannes Sixt, Miklos Vajna, Geoff Russell, git

On Tue, Jun 17, 2008 at 11:48 AM, Johannes Schindelin
<Johannes.Schindelin@gmx.de> wrote:
> On Tue, 17 Jun 2008, Sverre Rabbelier wrote:
>> How about 'git ls-files -t | grep "^M " | xargs git checkout B --',
>
> You probably meant 'sed -n "s/^M //p"' instead of 'grep "^M"', right?

Whoops, yes, that would be a lot better :P.

> Of course, I think that a better way would be to ask "git diff
> --name-only --diff-filter=U".

Hmmm, not having an unfinished merge at hand, would that require the
sed on top too?

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-17  9:53             ` Sverre Rabbelier
@ 2008-06-17 10:17               ` Johannes Schindelin
  0 siblings, 0 replies; 23+ messages in thread
From: Johannes Schindelin @ 2008-06-17 10:17 UTC (permalink / raw)
  To: sverre; +Cc: Johannes Sixt, Miklos Vajna, Geoff Russell, git

Hi,

On Tue, 17 Jun 2008, Sverre Rabbelier wrote:

> On Tue, Jun 17, 2008 at 11:48 AM, Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
>
> > Of course, I think that a better way would be to ask "git diff 
> > --name-only --diff-filter=U".
> 
> Hmmm, not having an unfinished merge at hand, would that require the
> sed on top too?

Nope.  The "--name-only" says it will print only the name.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-16 22:45       ` Geoff Russell
@ 2008-06-17 20:04         ` Junio C Hamano
  2008-06-18 15:19           ` Johannes Schindelin
  0 siblings, 1 reply; 23+ messages in thread
From: Junio C Hamano @ 2008-06-17 20:04 UTC (permalink / raw)
  To: geoffrey.russell
  Cc: Johannes Schindelin, sverre, Johannes Sixt, Miklos Vajna, git

"Geoff Russell" <geoffrey.russell@gmail.com> writes:

> Thanks everybody,
>
> On 6/17/08, Sverre Rabbelier <alturin@gmail.com> wrote:
>> On Mon, Jun 16, 2008 at 12:16 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
>>  > The solution depends on whether *all* files in B should be taken, or only
>>  > those files in B where there's a merge conflict. I don't know an easy way
>>  > to do the former, but the latter I'd do like this:
>>  >
>>  >        $ git diff --name-only | xargs git checkout B --
>
> This looks like a manageable approach and better than the scripting I was
> thinking about -- ie. scan the conflict files with perl and fix them!

Careful.

The above pipeline gives quite different result from "scan the conflict
files with perl and fix them".

If the result you want from the "scan and fix the conflicts" approach is
to take as much automerge as possible, and punt only on conflicting parts
by discarding your work (side note: I hear this wish often and still I
have not heard satisfactory explanation why people think that could be a
sane result, though), the above pipeline is not what you want.  It not
only discards your work in conflicting parts but also all your work from
even cleanly automerged parts of a path that has conflicts.

For example, suppose the original, our version and their version are like
these respectively:

        (orig)    (ours)     (theirs)
        1         one        uno
        2         2          2
        3         3          3
        4         4          4
        5         5          5
        6         6          6
        7         7          7
        8         eight      8

If you merge these with natural 3-way merge, you would get this:

        $ git-merge-file -p ours orig theirs
        <<<<<<< ours
        one
        =======
        uno
        >>>>>>> theirs
        2
        3
        4
        5
        6
        7
        eight

Note: git-merge-file mimicks the "merge" program from RCS suite.  The
      three file parameters are mine, old and yours (in alphabetical order
      as easy-to-remember mnemonic) and means "update mine taking the
      change that you made to old to reach yours".

That's a conflict.  The above suggested pipeline would give "their"
version.  That means the result does not have your change s/8/eight/.

It all depends on what you really mean by take "theirs", but you might
have wanted to have this instead, with the "scan and fix the conflicts"
approach you hinted in your message:

        $ git-merge-file -p --theirs ours orig theirs
        uno
        2
        3
        4
        5
        6
        7
        eight

That retains your change in non-conflicting part while favoring their
change where conflicts are.

No, neither --theirs nor --ours option exists in your version of git.
But here is a patch to add it to git-merge-file.

---

 builtin-merge-file.c |   10 ++++++++--
 xdiff/xdiff.h        |    8 +++++++-
 xdiff/xmerge.c       |   24 ++++++++++++++++--------
 3 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 3605960..7d4ca8c 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -4,7 +4,7 @@
 #include "xdiff-interface.h"
 
 static const char merge_file_usage[] =
-"git merge-file [-p | --stdout] [-q | --quiet] [-L name1 [-L orig [-L name2]]] file1 orig_file file2";
+"git merge-file [-p | --stdout] [-q | --quiet] [--ours|--theirs] [-L name1 [-L orig [-L name2]]] file1 orig_file file2";
 
 int cmd_merge_file(int argc, const char **argv, const char *prefix)
 {
@@ -13,6 +13,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	mmbuffer_t result = {NULL, 0};
 	xpparam_t xpp = {XDF_NEED_MINIMAL};
 	int ret = 0, i = 0, to_stdout = 0;
+	int flags, favor = 0;
 
 	while (argc > 4) {
 		if (!strcmp(argv[1], "-L") && i < 3) {
@@ -25,6 +26,10 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 		else if (!strcmp(argv[1], "-q") ||
 				!strcmp(argv[1], "--quiet"))
 			freopen("/dev/null", "w", stderr);
+		else if (!strcmp(argv[1], "--ours"))
+			favor = XDL_MERGE_FAVOR_OURS;
+		else if (!strcmp(argv[1], "--theirs"))
+			favor = XDL_MERGE_FAVOR_THEIRS;
 		else
 			usage(merge_file_usage);
 		argc--;
@@ -45,8 +50,9 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 					argv[i + 1]);
 	}
 
+	flags = XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS_ALNUM, favor);
 	ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
-			&xpp, XDL_MERGE_ZEALOUS_ALNUM, &result);
+			&xpp, flags, &result);
 
 	for (i = 0; i < 3; i++)
 		free(mmfs[i].ptr);
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 413082e..d40cf21 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -99,9 +99,15 @@ long xdl_mmfile_size(mmfile_t *mmf);
 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	     xdemitconf_t const *xecfg, xdemitcb_t *ecb);
 
+#define XDL_MERGE_FAVOR_OURS		1
+#define XDL_MERGE_FAVOR_THEIRS		2
+#define XDL_MERGE_FAVOR(flag)		(((flag)>>4) & 03)
+#define XDL_MERGE_LEVEL(flag)		((flag) & 07)
+#define XDL_MERGE_FLAGS(level,flag)	((level) | ((flag)<<4))
+
 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		mmfile_t *mf2, const char *name2,
-		xpparam_t const *xpp, int level, mmbuffer_t *result);
+		xpparam_t const *xpp, int flag, mmbuffer_t *result);
 
 #ifdef __cplusplus
 }
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index 82b3573..88c29ae 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -114,7 +114,9 @@ static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest)
 }
 
 static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
-		xdfenv_t *xe2, const char *name2, xdmerge_t *m, char *dest)
+				 xdfenv_t *xe2, const char *name2,
+				 int favor,
+				 xdmerge_t *m, char *dest)
 {
 	const int marker_size = 7;
 	int marker1_size = (name1 ? strlen(name1) + 1 : 0);
@@ -124,6 +126,9 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
 	int size, i1, j;
 
 	for (size = i1 = 0; m; m = m->next) {
+		if (favor && !m->mode)
+			m->mode = favor;
+
 		if (m->mode == 0) {
 			size += xdl_recs_copy(xe1, i1, m->i1 - i1, 0,
 					dest ? dest + size : NULL);
@@ -322,8 +327,9 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
  * returns < 0 on error, == 0 for no conflicts, else number of conflicts
  */
 static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
-		xdfenv_t *xe2, xdchange_t *xscr2, const char *name2,
-		int level, xpparam_t const *xpp, mmbuffer_t *result) {
+			xdfenv_t *xe2, xdchange_t *xscr2, const char *name2,
+			int level, int favor,
+			xpparam_t const *xpp, mmbuffer_t *result) {
 	xdmerge_t *changes, *c;
 	int i1, i2, chg1, chg2;
 
@@ -430,25 +436,27 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
 	/* output */
 	if (result) {
 		int size = xdl_fill_merge_buffer(xe1, name1, xe2, name2,
-			changes, NULL);
+						 favor, changes, NULL);
 		result->ptr = xdl_malloc(size);
 		if (!result->ptr) {
 			xdl_cleanup_merge(changes);
 			return -1;
 		}
 		result->size = size;
-		xdl_fill_merge_buffer(xe1, name1, xe2, name2, changes,
-				result->ptr);
+		xdl_fill_merge_buffer(xe1, name1, xe2, name2,
+				      favor, changes, result->ptr);
 	}
 	return xdl_cleanup_merge(changes);
 }
 
 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		mmfile_t *mf2, const char *name2,
-		xpparam_t const *xpp, int level, mmbuffer_t *result) {
+		xpparam_t const *xpp, int flag, mmbuffer_t *result) {
 	xdchange_t *xscr1, *xscr2;
 	xdfenv_t xe1, xe2;
 	int status;
+	int level = XDL_MERGE_LEVEL(flag);
+	int favor = XDL_MERGE_FAVOR(flag);
 
 	result->ptr = NULL;
 	result->size = 0;
@@ -482,7 +490,7 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		} else {
 			status = xdl_do_merge(&xe1, xscr1, name1,
 					      &xe2, xscr2, name2,
-					      level, xpp, result);
+					      level, favor, xpp, result);
 		}
 		xdl_free_script(xscr1);
 		xdl_free_script(xscr2);

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-17 20:04         ` Junio C Hamano
@ 2008-06-18 15:19           ` Johannes Schindelin
  2008-06-18 15:28             ` Johannes Schindelin
  0 siblings, 1 reply; 23+ messages in thread
From: Johannes Schindelin @ 2008-06-18 15:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Hi,

On Tue, 17 Jun 2008, Junio C Hamano wrote:

> No, neither --theirs nor --ours option exists in your version of git. 
> But here is a patch to add it to git-merge-file.

Looks good, thanks!  Just to be safe, this should be accompanied by tet 
cases.  But I did not see anything wrong with the patch.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-18 15:19           ` Johannes Schindelin
@ 2008-06-18 15:28             ` Johannes Schindelin
  2008-06-18 16:31               ` Junio C Hamano
  0 siblings, 1 reply; 23+ messages in thread
From: Johannes Schindelin @ 2008-06-18 15:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Hi,

On Wed, 18 Jun 2008, Johannes Schindelin wrote:

> On Tue, 17 Jun 2008, Junio C Hamano wrote:
> 
> > No, neither --theirs nor --ours option exists in your version of git. 
> > But here is a patch to add it to git-merge-file.
> 
> Looks good, thanks!  Just to be safe, this should be accompanied by tet 
> cases.  But I did not see anything wrong with the patch.

Thinking about this again, there could be a problem: in case of complex 
merges, it is possible that the sides are switched around for an 
intermediate merge.  IOW you'd expect it to take "theirs", but it really 
takes "ours".

Hrm.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-18 15:28             ` Johannes Schindelin
@ 2008-06-18 16:31               ` Junio C Hamano
  2008-06-18 19:29                 ` Johannes Schindelin
  2008-06-20  7:38                 ` [PATCH 1/2] git-merge-file --ours, --theirs Junio C Hamano
  0 siblings, 2 replies; 23+ messages in thread
From: Junio C Hamano @ 2008-06-18 16:31 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> Thinking about this again, there could be a problem: in case of complex 
> merges, it is possible that the sides are switched around for an 
> intermediate merge.  IOW you'd expect it to take "theirs", but it really 
> takes "ours".

Are you thinking about using this in merge-recursive?

I do not think there is any reason to use this during intermediate merges
done inside merge-recursive.  The point of recursive merge is to create a
neutral intermediate merge result, with conflicts and all.  Do this only
during the final round and you are fine (for some definition of "fine" ---
I still have not heard a convincing argument as to why it is even a good
thing to be able to take one side for only parts that did conflict, while
taking the change from the other side in places that did not).

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Guided merge with override
  2008-06-18 16:31               ` Junio C Hamano
@ 2008-06-18 19:29                 ` Johannes Schindelin
  2008-06-20  7:38                 ` [PATCH 1/2] git-merge-file --ours, --theirs Junio C Hamano
  1 sibling, 0 replies; 23+ messages in thread
From: Johannes Schindelin @ 2008-06-18 19:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Hi,

On Wed, 18 Jun 2008, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > Thinking about this again, there could be a problem: in case of complex 
> > merges, it is possible that the sides are switched around for an 
> > intermediate merge.  IOW you'd expect it to take "theirs", but it really 
> > takes "ours".
> 
> Are you thinking about using this in merge-recursive?

Indeed I was.

> I do not think there is any reason to use this during intermediate 
> merges done inside merge-recursive.

That is right, but for some stupid reason I did not realize that 
git-merge-file is not even called by merge-recursive.

So the accompanying patch for merge-recursive would use the --theirs or 
--ours logic only in the !index_only case, i.e. the final merge.

And I guess we'd have similar logic as for merge-subtree, introducing 
merge-recursive-ours and merge-recursive-theirs.

Very nice.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/2] git-merge-file --ours, --theirs
  2008-06-18 16:31               ` Junio C Hamano
  2008-06-18 19:29                 ` Johannes Schindelin
@ 2008-06-20  7:38                 ` Junio C Hamano
  2008-06-20  7:48                   ` [PATCH 2/2] git-merge-recursive-{ours,theirs} Junio C Hamano
  1 sibling, 1 reply; 23+ messages in thread
From: Junio C Hamano @ 2008-06-20  7:38 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Often people want their conflicting merges autoresolved by favouring
upstream changes (or their own --- it's the same thing), and hinted to run
"git diff --name-only | xargs git checkout MERGE_HEAD --".  This is
essentially to accept automerge results for the paths that are fully
resolved automatically while taking their version of the file in full for
paths that have conflicts.

This is problematic on two counts.

One problem is that this is not exactly what these people want.  They
usually want to salvage as much automerge result as possible.  In
particular, they want to keep autoresolved parts in conflicting paths, as
well as the paths that are fully autoresolved.

This patch teaches two new modes of operation to the lowest-lever merge
machinery, xdl_merge().  Instead of leaving the conflicted lines from both
sides enclosed in <<<, ===, and >>> markers, you can tell the conflicts to
be resolved favouring your side or their side of changes.

A larger problem is that this tends to encourage a bad workflow by
allowing them to record such a mixed up half-merge result as a full commit
without auditing.  This commit does not tackle this latter issue.  In git,
we usually give long enough rope to users with strange wishes as long as
the risky features is not on by default.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * Essentially the same patch but with documentation.

 Documentation/git-merge-file.txt |   12 ++++++++++--
 builtin-merge-file.c             |   10 ++++++++--
 xdiff/xdiff.h                    |    8 +++++++-
 xdiff/xmerge.c                   |   24 ++++++++++++++++--------
 4 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index 149f131..87e07d3 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -10,7 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git-merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
-	[-p|--stdout] [-q|--quiet] <current-file> <base-file> <other-file>
+	[--ours|--theirs] [-p|--stdout] [-q|--quiet]
+	<current-file> <base-file> <other-file>
 
 
 DESCRIPTION
@@ -34,7 +35,9 @@ normally outputs a warning and brackets the conflict with <<<<<<< and
 	>>>>>>> B
 
 If there are conflicts, the user should edit the result and delete one of
-the alternatives.
+the alternatives.  When `--ours` or `--theirs` option is in effect, however,
+these conflicts are resolved favouring lines from `<current-file>` or
+lines from `<other-file>` respectively.
 
 The exit value of this program is negative on error, and the number of
 conflicts otherwise. If the merge was clean, the exit value is 0.
@@ -62,6 +65,11 @@ OPTIONS
 -q::
 	Quiet;  do  not  warn about conflicts.
 
+--ours::
+--theirs::
+	Instead of leaving conflicts in the file, resolve conflicts
+	favouring our (or their) side of the lines.
+
 
 EXAMPLES
 --------
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 3605960..7d4ca8c 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -4,7 +4,7 @@
 #include "xdiff-interface.h"
 
 static const char merge_file_usage[] =
-"git merge-file [-p | --stdout] [-q | --quiet] [-L name1 [-L orig [-L name2]]] file1 orig_file file2";
+"git merge-file [-p | --stdout] [-q | --quiet] [--ours|--theirs] [-L name1 [-L orig [-L name2]]] file1 orig_file file2";
 
 int cmd_merge_file(int argc, const char **argv, const char *prefix)
 {
@@ -13,6 +13,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	mmbuffer_t result = {NULL, 0};
 	xpparam_t xpp = {XDF_NEED_MINIMAL};
 	int ret = 0, i = 0, to_stdout = 0;
+	int flags, favor = 0;
 
 	while (argc > 4) {
 		if (!strcmp(argv[1], "-L") && i < 3) {
@@ -25,6 +26,10 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 		else if (!strcmp(argv[1], "-q") ||
 				!strcmp(argv[1], "--quiet"))
 			freopen("/dev/null", "w", stderr);
+		else if (!strcmp(argv[1], "--ours"))
+			favor = XDL_MERGE_FAVOR_OURS;
+		else if (!strcmp(argv[1], "--theirs"))
+			favor = XDL_MERGE_FAVOR_THEIRS;
 		else
 			usage(merge_file_usage);
 		argc--;
@@ -45,8 +50,9 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 					argv[i + 1]);
 	}
 
+	flags = XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS_ALNUM, favor);
 	ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
-			&xpp, XDL_MERGE_ZEALOUS_ALNUM, &result);
+			&xpp, flags, &result);
 
 	for (i = 0; i < 3; i++)
 		free(mmfs[i].ptr);
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 413082e..d40cf21 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -99,9 +99,15 @@ long xdl_mmfile_size(mmfile_t *mmf);
 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	     xdemitconf_t const *xecfg, xdemitcb_t *ecb);
 
+#define XDL_MERGE_FAVOR_OURS		1
+#define XDL_MERGE_FAVOR_THEIRS		2
+#define XDL_MERGE_FAVOR(flag)		(((flag)>>4) & 03)
+#define XDL_MERGE_LEVEL(flag)		((flag) & 07)
+#define XDL_MERGE_FLAGS(level,flag)	((level) | ((flag)<<4))
+
 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		mmfile_t *mf2, const char *name2,
-		xpparam_t const *xpp, int level, mmbuffer_t *result);
+		xpparam_t const *xpp, int flag, mmbuffer_t *result);
 
 #ifdef __cplusplus
 }
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index 82b3573..88c29ae 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -114,7 +114,9 @@ static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest)
 }
 
 static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
-		xdfenv_t *xe2, const char *name2, xdmerge_t *m, char *dest)
+				 xdfenv_t *xe2, const char *name2,
+				 int favor,
+				 xdmerge_t *m, char *dest)
 {
 	const int marker_size = 7;
 	int marker1_size = (name1 ? strlen(name1) + 1 : 0);
@@ -124,6 +126,9 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
 	int size, i1, j;
 
 	for (size = i1 = 0; m; m = m->next) {
+		if (favor && !m->mode)
+			m->mode = favor;
+
 		if (m->mode == 0) {
 			size += xdl_recs_copy(xe1, i1, m->i1 - i1, 0,
 					dest ? dest + size : NULL);
@@ -322,8 +327,9 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
  * returns < 0 on error, == 0 for no conflicts, else number of conflicts
  */
 static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
-		xdfenv_t *xe2, xdchange_t *xscr2, const char *name2,
-		int level, xpparam_t const *xpp, mmbuffer_t *result) {
+			xdfenv_t *xe2, xdchange_t *xscr2, const char *name2,
+			int level, int favor,
+			xpparam_t const *xpp, mmbuffer_t *result) {
 	xdmerge_t *changes, *c;
 	int i1, i2, chg1, chg2;
 
@@ -430,25 +436,27 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
 	/* output */
 	if (result) {
 		int size = xdl_fill_merge_buffer(xe1, name1, xe2, name2,
-			changes, NULL);
+						 favor, changes, NULL);
 		result->ptr = xdl_malloc(size);
 		if (!result->ptr) {
 			xdl_cleanup_merge(changes);
 			return -1;
 		}
 		result->size = size;
-		xdl_fill_merge_buffer(xe1, name1, xe2, name2, changes,
-				result->ptr);
+		xdl_fill_merge_buffer(xe1, name1, xe2, name2,
+				      favor, changes, result->ptr);
 	}
 	return xdl_cleanup_merge(changes);
 }
 
 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		mmfile_t *mf2, const char *name2,
-		xpparam_t const *xpp, int level, mmbuffer_t *result) {
+		xpparam_t const *xpp, int flag, mmbuffer_t *result) {
 	xdchange_t *xscr1, *xscr2;
 	xdfenv_t xe1, xe2;
 	int status;
+	int level = XDL_MERGE_LEVEL(flag);
+	int favor = XDL_MERGE_FAVOR(flag);
 
 	result->ptr = NULL;
 	result->size = 0;
@@ -482,7 +490,7 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		} else {
 			status = xdl_do_merge(&xe1, xscr1, name1,
 					      &xe2, xscr2, name2,
-					      level, xpp, result);
+					      level, favor, xpp, result);
 		}
 		xdl_free_script(xscr1);
 		xdl_free_script(xscr2);
-- 
1.5.6.6.gd3e97

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/2] git-merge-recursive-{ours,theirs}
  2008-06-20  7:38                 ` [PATCH 1/2] git-merge-file --ours, --theirs Junio C Hamano
@ 2008-06-20  7:48                   ` Junio C Hamano
  2008-06-20 12:58                     ` Johannes Schindelin
  0 siblings, 1 reply; 23+ messages in thread
From: Junio C Hamano @ 2008-06-20  7:48 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

This uses the low-level mechanism for "ours" and "theirs" autoresolution
introduced by the previous commit to introduce two additional merge
strategies, merge-recursive-ours and merge-recursive-theirs.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Makefile                     |    3 ++
 builtin-merge-recursive.c    |   37 ++++++++++++++++++++++++---
 git-merge.sh                 |    3 +-
 git.c                        |    2 +
 ll-merge.c                   |   24 +++++++++++------
 ll-merge.h                   |    4 ++-
 t/t6034-merge-ours-theirs.sh |   56 ++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 114 insertions(+), 15 deletions(-)
 create mode 100755 t/t6034-merge-ours-theirs.sh

diff --git a/Makefile b/Makefile
index b003e3e..82d2892 100644
--- a/Makefile
+++ b/Makefile
@@ -304,6 +304,8 @@ BUILT_INS += git-format-patch$X
 BUILT_INS += git-fsck-objects$X
 BUILT_INS += git-get-tar-commit-id$X
 BUILT_INS += git-init$X
+BUILT_INS += git-merge-recursive-ours$X
+BUILT_INS += git-merge-recursive-theirs$X
 BUILT_INS += git-merge-subtree$X
 BUILT_INS += git-peek-remote$X
 BUILT_INS += git-repo-config$X
@@ -1381,6 +1383,7 @@ check-docs::
 	do \
 		case "$$v" in \
 		git-merge-octopus | git-merge-ours | git-merge-recursive | \
+		git-merge-recursive-ours | git-merge-recursive-theirs | \
 		git-merge-resolve | git-merge-stupid | git-merge-subtree | \
 		git-fsck-objects | git-init-db | \
 		git-?*--?* ) continue ;; \
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 4aa28a1..a355e7a 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -20,7 +20,11 @@
 #include "attr.h"
 #include "merge-recursive.h"
 
-static int subtree_merge;
+static enum {
+	MERGE_RECURSIVE_SUBTREE = 1,
+	MERGE_RECURSIVE_OURS,
+	MERGE_RECURSIVE_THEIRS,
+} merge_recursive_variants;
 
 static struct tree *shift_tree_object(struct tree *one, struct tree *two)
 {
@@ -642,6 +646,7 @@ static int merge_3way(mmbuffer_t *result_buf,
 	mmfile_t orig, src1, src2;
 	char *name1, *name2;
 	int merge_status;
+	int flag, favor;
 
 	name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
 	name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
@@ -650,9 +655,26 @@ static int merge_3way(mmbuffer_t *result_buf,
 	fill_mm(a->sha1, &src1);
 	fill_mm(b->sha1, &src2);
 
+	if (index_only)
+		favor = 0;
+	else {
+		switch (merge_recursive_variants) {
+		case MERGE_RECURSIVE_OURS:
+			favor = XDL_MERGE_FAVOR_OURS;
+			break;
+		case MERGE_RECURSIVE_THEIRS:
+			favor = XDL_MERGE_FAVOR_THEIRS;
+			break;
+		default:
+			favor = 0;
+			break;
+		}
+	}
+	flag = LL_MERGE_FLAGS(index_only, favor);
+
 	merge_status = ll_merge(result_buf, a->path, &orig,
 				&src1, name1, &src2, name2,
-				index_only);
+				flag);
 
 	free(name1);
 	free(name2);
@@ -1171,7 +1193,7 @@ int merge_trees(struct tree *head,
 {
 	int code, clean;
 
-	if (subtree_merge) {
+	if (merge_recursive_variants == MERGE_RECURSIVE_SUBTREE) {
 		merge = shift_tree_object(head, merge);
 		common = shift_tree_object(head, common);
 	}
@@ -1379,11 +1401,18 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
 	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
 	int index_fd;
 
+	merge_recursive_variants = 0;
 	if (argv[0]) {
 		int namelen = strlen(argv[0]);
 		if (8 < namelen &&
 		    !strcmp(argv[0] + namelen - 8, "-subtree"))
-			subtree_merge = 1;
+			merge_recursive_variants = MERGE_RECURSIVE_SUBTREE;
+		else if (5 < namelen &&
+			 !strcmp(argv[0] + namelen - 5, "-ours"))
+			merge_recursive_variants = MERGE_RECURSIVE_OURS;
+		else if (7 < namelen &&
+			 !strcmp(argv[0] + namelen - 7, "-theirs"))
+			merge_recursive_variants = MERGE_RECURSIVE_THEIRS;
 	}
 
 	git_config(merge_config, NULL);
diff --git a/git-merge.sh b/git-merge.sh
index 8026ccf..39b5cd9 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -31,10 +31,11 @@ LF='
 '
 
 all_strategies='recur recursive octopus resolve stupid ours subtree'
+all_strategies="$all_strategies recursive-ours recursive-theirs"
 default_twohead_strategies='recursive'
 default_octopus_strategies='octopus'
 no_fast_forward_strategies='subtree ours'
-no_trivial_strategies='recursive recur subtree ours'
+no_trivial_strategies='recursive recur subtree ours recursive-ours recursive-theirs'
 use_strategies=
 
 allow_fast_forward=t
diff --git a/git.c b/git.c
index 59f0fcc..44cb8eb 100644
--- a/git.c
+++ b/git.c
@@ -328,6 +328,8 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "merge-file", cmd_merge_file },
 		{ "merge-ours", cmd_merge_ours, RUN_SETUP },
 		{ "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+		{ "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+		{ "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 		{ "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 		{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
 		{ "name-rev", cmd_name_rev, RUN_SETUP },
diff --git a/ll-merge.c b/ll-merge.c
index 9837c84..c6a05bf 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -19,7 +19,7 @@ typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
 			   mmfile_t *orig,
 			   mmfile_t *src1, const char *name1,
 			   mmfile_t *src2, const char *name2,
-			   int virtual_ancestor);
+			   int flag);
 
 struct ll_merge_driver {
 	const char *name;
@@ -39,13 +39,15 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
 			   mmfile_t *orig,
 			   mmfile_t *src1, const char *name1,
 			   mmfile_t *src2, const char *name2,
-			   int virtual_ancestor)
+			   int flag)
 {
 	/*
 	 * The tentative merge result is "ours" for the final round,
 	 * or common ancestor for an internal merge.  Still return
 	 * "conflicted merge" status.
 	 */
+	int virtual_ancestor = flag & 01;
+
 	mmfile_t *stolen = virtual_ancestor ? orig : src1;
 
 	result->ptr = stolen->ptr;
@@ -60,9 +62,10 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 			mmfile_t *orig,
 			mmfile_t *src1, const char *name1,
 			mmfile_t *src2, const char *name2,
-			int virtual_ancestor)
+			int flag)
 {
 	xpparam_t xpp;
+	int favor = ((flag)>>1) & 03;
 
 	if (buffer_is_binary(orig->ptr, orig->size) ||
 	    buffer_is_binary(src1->ptr, src1->size) ||
@@ -73,14 +76,15 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 				       path_unused,
 				       orig, src1, name1,
 				       src2, name2,
-				       virtual_ancestor);
+				       flag);
 	}
 
 	memset(&xpp, 0, sizeof(xpp));
 	return xdl_merge(orig,
 			 src1, name1,
 			 src2, name2,
-			 &xpp, XDL_MERGE_ZEALOUS,
+			 &xpp,
+			 XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS, favor),
 			 result);
 }
 
@@ -90,11 +94,12 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
 			  mmfile_t *orig,
 			  mmfile_t *src1, const char *name1,
 			  mmfile_t *src2, const char *name2,
-			  int virtual_ancestor)
+			  int flag)
 {
 	char *src, *dst;
 	long size;
 	const int marker_size = 7;
+	int virtual_ancestor = flag & 01;
 
 	int status = ll_xdl_merge(drv_unused, result, path_unused,
 				  orig, src1, NULL, src2, NULL,
@@ -158,7 +163,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
 			mmfile_t *orig,
 			mmfile_t *src1, const char *name1,
 			mmfile_t *src2, const char *name2,
-			int virtual_ancestor)
+			int flag)
 {
 	char temp[3][50];
 	char cmdbuf[2048];
@@ -362,10 +367,11 @@ int ll_merge(mmbuffer_t *result_buf,
 	     mmfile_t *ancestor,
 	     mmfile_t *ours, const char *our_label,
 	     mmfile_t *theirs, const char *their_label,
-	     int virtual_ancestor)
+	     int flag)
 {
 	const char *ll_driver_name;
 	const struct ll_merge_driver *driver;
+	int virtual_ancestor = flag & 01;
 
 	ll_driver_name = git_path_check_merge(path);
 	driver = find_ll_merge_driver(ll_driver_name);
@@ -375,5 +381,5 @@ int ll_merge(mmbuffer_t *result_buf,
 	return driver->fn(driver, result_buf, path,
 			  ancestor,
 			  ours, our_label,
-			  theirs, their_label, virtual_ancestor);
+			  theirs, their_label, flag);
 }
diff --git a/ll-merge.h b/ll-merge.h
index 5388422..5daef58 100644
--- a/ll-merge.h
+++ b/ll-merge.h
@@ -5,11 +5,13 @@
 #ifndef LL_MERGE_H
 #define LL_MERGE_H
 
+#define LL_MERGE_FLAGS(virtual_ancestor,favor) ((!!(virtual_ancestor)) | ((favor)<<1))
+
 int ll_merge(mmbuffer_t *result_buf,
 	     const char *path,
 	     mmfile_t *ancestor,
 	     mmfile_t *ours, const char *our_label,
 	     mmfile_t *theirs, const char *their_label,
-	     int virtual_ancestor);
+	     int flag);
 
 #endif
diff --git a/t/t6034-merge-ours-theirs.sh b/t/t6034-merge-ours-theirs.sh
new file mode 100755
index 0000000..56a9247
--- /dev/null
+++ b/t/t6034-merge-ours-theirs.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description='Merge-recursive ours and theirs variants'
+. ./test-lib.sh
+
+test_expect_success setup '
+	for i in 1 2 3 4 5 6 7 8 9
+	do
+		echo "$i"
+	done >file &&
+	git add file &&
+	cp file elif &&
+	git commit -m initial &&
+
+	sed -e "s/1/one/" -e "s/9/nine/" >file <elif &&
+	git commit -a -m ours &&
+
+	git checkout -b side HEAD^ &&
+
+	sed -e "s/9/nueve/" >file <elif &&
+	git commit -a -m theirs &&
+
+	git checkout master^0
+'
+
+test_expect_success 'plain recursive - should conflict' '
+	git reset --hard master &&
+	test_must_fail git merge -s recursive side &&
+	grep nine file &&
+	grep nueve file &&
+	! grep 9 file &&
+	grep one file &&
+	! grep 1 file
+'
+
+test_expect_success 'recursive favouring theirs' '
+	git reset --hard master &&
+	git merge -s recursive-theirs side &&
+	! grep nine file &&
+	grep nueve file &&
+	! grep 9 file &&
+	grep one file &&
+	! grep 1 file
+'
+
+test_expect_success 'recursive favouring ours' '
+	git reset --hard master &&
+	git merge -s recursive-ours side &&
+	grep nine file &&
+	! grep nueve file &&
+	! grep 9 file &&
+	grep one file &&
+	! grep 1 file
+'
+
+test_done
-- 
1.5.6.6.gd3e97

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] git-merge-recursive-{ours,theirs}
  2008-06-20  7:48                   ` [PATCH 2/2] git-merge-recursive-{ours,theirs} Junio C Hamano
@ 2008-06-20 12:58                     ` Johannes Schindelin
  2008-06-21  9:46                       ` Junio C Hamano
  0 siblings, 1 reply; 23+ messages in thread
From: Johannes Schindelin @ 2008-06-20 12:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Hi,

On Fri, 20 Jun 2008, Junio C Hamano wrote:

> diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
> index 4aa28a1..a355e7a 100644
> --- a/builtin-merge-recursive.c
> +++ b/builtin-merge-recursive.c
> @@ -650,9 +655,26 @@ static int merge_3way(mmbuffer_t *result_buf,
>  	fill_mm(a->sha1, &src1);
>  	fill_mm(b->sha1, &src2);
>  
> +	if (index_only)
> +		favor = 0;
> +	else {
> +		switch (merge_recursive_variants) {
> +		case MERGE_RECURSIVE_OURS:
> +			favor = XDL_MERGE_FAVOR_OURS;
> +			break;
> +		case MERGE_RECURSIVE_THEIRS:
> +			favor = XDL_MERGE_FAVOR_THEIRS;
> +			break;
> +		default:
> +			favor = 0;
> +			break;
> +		}

Hrm.  I would have preferred something like this:

	if (!index_only && merge_recursive_variants == MERGE_RECURSIVE_OURS)
		favor = XDL_MERGE_FAVOR_OURS;
	if (!index_only && merge_recursive_variants == MERGE_RECURSIVE_THEIRS)
		favor = XDL_MERGE_FAVOR_THEIRS;
	else
		favor = 0;

> +	}
> +	flag = LL_MERGE_FLAGS(index_only, favor);
> +
>  	merge_status = ll_merge(result_buf, a->path, &orig,
>  				&src1, name1, &src2, name2,
> -				index_only);
> +				flag);

Sorry, but in my opinion this flag mangling makes the whole code uglier.  
Why not just add another parameter?

Or if you are really concerned about future enhancements to ll_merge(), 
use a struct.

> @@ -1379,11 +1401,18 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
>  	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
>  	int index_fd;
>  
> +	merge_recursive_variants = 0;
>  	if (argv[0]) {
>  		int namelen = strlen(argv[0]);
>  		if (8 < namelen &&
>  		    !strcmp(argv[0] + namelen - 8, "-subtree"))
> -			subtree_merge = 1;
> +			merge_recursive_variants = MERGE_RECURSIVE_SUBTREE;
> +		else if (5 < namelen &&
> +			 !strcmp(argv[0] + namelen - 5, "-ours"))
> +			merge_recursive_variants = MERGE_RECURSIVE_OURS;
> +		else if (7 < namelen &&
> +			 !strcmp(argv[0] + namelen - 7, "-theirs"))
> +			merge_recursive_variants = MERGE_RECURSIVE_THEIRS;

This just cries out loud for a new function suffixcmp().

I will not say anything about the long lines in git-merge.sh, since I 
fully expect builtin-merge to happen Real Soon Now.

Anyhow, your comments about this driving the wrong workflow still apply.  
Maybe we want to display them really, really prominently in 
Documentation/merge-strategies.txt.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] git-merge-recursive-{ours,theirs}
  2008-06-20 12:58                     ` Johannes Schindelin
@ 2008-06-21  9:46                       ` Junio C Hamano
  2008-06-21 16:29                         ` Johannes Schindelin
  2008-06-21 16:56                         ` Jakub Narebski
  0 siblings, 2 replies; 23+ messages in thread
From: Junio C Hamano @ 2008-06-21  9:46 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

>> @@ -1379,11 +1401,18 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
>>  	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
>>  	int index_fd;
>>  
>> +	merge_recursive_variants = 0;
>>  	if (argv[0]) {
>>  		int namelen = strlen(argv[0]);
>>  		if (8 < namelen &&
>>  		    !strcmp(argv[0] + namelen - 8, "-subtree"))
>> -			subtree_merge = 1;
>> +			merge_recursive_variants = MERGE_RECURSIVE_SUBTREE;
>> +		else if (5 < namelen &&
>> +			 !strcmp(argv[0] + namelen - 5, "-ours"))
>> +			merge_recursive_variants = MERGE_RECURSIVE_OURS;
>> +		else if (7 < namelen &&
>> +			 !strcmp(argv[0] + namelen - 7, "-theirs"))
>> +			merge_recursive_variants = MERGE_RECURSIVE_THEIRS;
>
> This just cries out loud for a new function suffixcmp().

Actually, I think "git-merge-recursive-theirs" is a mistake.  We should
bite the bullet and give "git-merge" an ability to pass backend specific
parameters to "git-merge-recursive".  The new convention could be that
anything that begins with -X is passed to the backend.

E.g.

	git merge -Xfavor=theirs foo
        git merge -Xsubtree=/=gitk-git paulus

As you noticed already, subtree is just a funny optional behaviour
attached to recursive, so are theirs and ours.  The above two would invoke
git-merge-recursive like so:

	git merge-recursive -Xfavor=theirs <base> -- HEAD MERGE_HEAD
	git merge-recursive -Xsubtree=/=gitk-git <base> -- HEAD MERGE_HEAD

We could even mix these two if we are ambitious.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] git-merge-recursive-{ours,theirs}
  2008-06-21  9:46                       ` Junio C Hamano
@ 2008-06-21 16:29                         ` Johannes Schindelin
  2008-06-21 16:56                         ` Jakub Narebski
  1 sibling, 0 replies; 23+ messages in thread
From: Johannes Schindelin @ 2008-06-21 16:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: geoffrey.russell, sverre, Johannes Sixt, Miklos Vajna, git

Hi,

On Sat, 21 Jun 2008, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> >> @@ -1379,11 +1401,18 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
> >>  	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
> >>  	int index_fd;
> >>  
> >> +	merge_recursive_variants = 0;
> >>  	if (argv[0]) {
> >>  		int namelen = strlen(argv[0]);
> >>  		if (8 < namelen &&
> >>  		    !strcmp(argv[0] + namelen - 8, "-subtree"))
> >> -			subtree_merge = 1;
> >> +			merge_recursive_variants = MERGE_RECURSIVE_SUBTREE;
> >> +		else if (5 < namelen &&
> >> +			 !strcmp(argv[0] + namelen - 5, "-ours"))
> >> +			merge_recursive_variants = MERGE_RECURSIVE_OURS;
> >> +		else if (7 < namelen &&
> >> +			 !strcmp(argv[0] + namelen - 7, "-theirs"))
> >> +			merge_recursive_variants = MERGE_RECURSIVE_THEIRS;
> >
> > This just cries out loud for a new function suffixcmp().
> 
> Actually, I think "git-merge-recursive-theirs" is a mistake.  We should
> bite the bullet and give "git-merge" an ability to pass backend specific
> parameters to "git-merge-recursive".

Fair enough.

> The new convention could be that anything that begins with -X is passed 
> to the backend.
> 
> E.g.
> 
> 	git merge -Xfavor=theirs foo
>         git merge -Xsubtree=/=gitk-git paulus
> 
> As you noticed already, subtree is just a funny optional behaviour
> attached to recursive, so are theirs and ours.  The above two would invoke
> git-merge-recursive like so:
> 
> 	git merge-recursive -Xfavor=theirs <base> -- HEAD MERGE_HEAD
> 	git merge-recursive -Xsubtree=/=gitk-git <base> -- HEAD MERGE_HEAD
> 
> We could even mix these two if we are ambitious.

Looks fine to me.  And much cleaner than the hardlinking.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] git-merge-recursive-{ours,theirs}
  2008-06-21  9:46                       ` Junio C Hamano
  2008-06-21 16:29                         ` Johannes Schindelin
@ 2008-06-21 16:56                         ` Jakub Narebski
  1 sibling, 0 replies; 23+ messages in thread
From: Jakub Narebski @ 2008-06-21 16:56 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Schindelin, geoffrey.russell, sverre, Johannes Sixt,
	Miklos Vajna, git

Junio C Hamano <gitster@pobox.com> writes:

> Actually, I think "git-merge-recursive-theirs" is a mistake.  We should
> bite the bullet and give "git-merge" an ability to pass backend specific
> parameters to "git-merge-recursive".  The new convention could be that
> anything that begins with -X is passed to the backend.
> 
> E.g.
> 
> 	git merge -Xfavor=theirs foo
>       git merge -Xsubtree=/=gitk-git paulus

Gaaah... only after reading it for third time I see that it isn't
some funky "=/=" symbol, but subtree with grafing '/' in one side
to 'gitk-git' subdirectory in other side.

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 2/2] git-merge-recursive-{ours,theirs}
  2008-06-23 12:45 [PATCH 0/2] jc/merge-theirs, rebased on top of mv/merge-in-c Miklos Vajna
@ 2008-06-23 12:45 ` Miklos Vajna
  0 siblings, 0 replies; 23+ messages in thread
From: Miklos Vajna @ 2008-06-23 12:45 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

From: Junio C Hamano <gitster@pobox.com>

This uses the low-level mechanism for "ours" and "theirs" autoresolution
introduced by the previous commit to introduce two additional merge
strategies, merge-recursive-ours and merge-recursive-theirs.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

The patch is the same, but I removed modifications to git-merge.sh and
added them to builtin-merge.c.

 Makefile                     |    3 ++
 builtin-merge-recursive.c    |   37 ++++++++++++++++++++++++---
 builtin-merge.c              |    2 +
 git.c                        |    2 +
 ll-merge.c                   |   24 +++++++++++------
 ll-merge.h                   |    4 ++-
 t/t6034-merge-ours-theirs.sh |   56 ++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 114 insertions(+), 14 deletions(-)
 create mode 100755 t/t6034-merge-ours-theirs.sh

diff --git a/Makefile b/Makefile
index 3d8c3d2..4e354fc 100644
--- a/Makefile
+++ b/Makefile
@@ -303,6 +303,8 @@ BUILT_INS += git-format-patch$X
 BUILT_INS += git-fsck-objects$X
 BUILT_INS += git-get-tar-commit-id$X
 BUILT_INS += git-init$X
+BUILT_INS += git-merge-recursive-ours$X
+BUILT_INS += git-merge-recursive-theirs$X
 BUILT_INS += git-merge-subtree$X
 BUILT_INS += git-peek-remote$X
 BUILT_INS += git-repo-config$X
@@ -1381,6 +1383,7 @@ check-docs::
 	do \
 		case "$$v" in \
 		git-merge-octopus | git-merge-ours | git-merge-recursive | \
+		git-merge-recursive-ours | git-merge-recursive-theirs | \
 		git-merge-resolve | git-merge-stupid | git-merge-subtree | \
 		git-fsck-objects | git-init-db | \
 		git-?*--?* ) continue ;; \
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 98b09fb..c535596 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -20,7 +20,11 @@
 #include "attr.h"
 #include "merge-recursive.h"
 
-static int subtree_merge;
+static enum {
+	MERGE_RECURSIVE_SUBTREE = 1,
+	MERGE_RECURSIVE_OURS,
+	MERGE_RECURSIVE_THEIRS,
+} merge_recursive_variants;
 
 static struct tree *shift_tree_object(struct tree *one, struct tree *two)
 {
@@ -634,6 +638,7 @@ static int merge_3way(mmbuffer_t *result_buf,
 	mmfile_t orig, src1, src2;
 	char *name1, *name2;
 	int merge_status;
+	int flag, favor;
 
 	name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
 	name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
@@ -642,9 +647,26 @@ static int merge_3way(mmbuffer_t *result_buf,
 	fill_mm(a->sha1, &src1);
 	fill_mm(b->sha1, &src2);
 
+	if (index_only)
+		favor = 0;
+	else {
+		switch (merge_recursive_variants) {
+		case MERGE_RECURSIVE_OURS:
+			favor = XDL_MERGE_FAVOR_OURS;
+			break;
+		case MERGE_RECURSIVE_THEIRS:
+			favor = XDL_MERGE_FAVOR_THEIRS;
+			break;
+		default:
+			favor = 0;
+			break;
+		}
+	}
+	flag = LL_MERGE_FLAGS(index_only, favor);
+
 	merge_status = ll_merge(result_buf, a->path, &orig,
 				&src1, name1, &src2, name2,
-				index_only);
+				flag);
 
 	free(name1);
 	free(name2);
@@ -1163,7 +1185,7 @@ int merge_trees(struct tree *head,
 {
 	int code, clean;
 
-	if (subtree_merge) {
+	if (merge_recursive_variants == MERGE_RECURSIVE_SUBTREE) {
 		merge = shift_tree_object(head, merge);
 		common = shift_tree_object(head, common);
 	}
@@ -1371,11 +1393,18 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
 	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
 	int index_fd;
 
+	merge_recursive_variants = 0;
 	if (argv[0]) {
 		int namelen = strlen(argv[0]);
 		if (8 < namelen &&
 		    !strcmp(argv[0] + namelen - 8, "-subtree"))
-			subtree_merge = 1;
+			merge_recursive_variants = MERGE_RECURSIVE_SUBTREE;
+		else if (5 < namelen &&
+			 !strcmp(argv[0] + namelen - 5, "-ours"))
+			merge_recursive_variants = MERGE_RECURSIVE_OURS;
+		else if (7 < namelen &&
+			 !strcmp(argv[0] + namelen - 7, "-theirs"))
+			merge_recursive_variants = MERGE_RECURSIVE_THEIRS;
 	}
 
 	git_config(merge_config, NULL);
diff --git a/builtin-merge.c b/builtin-merge.c
index dadde80..b7b1b71 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -52,6 +52,8 @@ static struct path_list_item strategy_items[] = {
 	{ "stupid",     (void *)0 },
 	{ "ours",       (void *)(NO_FAST_FORWARD | NO_TRIVIAL) },
 	{ "subtree",    (void *)(NO_FAST_FORWARD | NO_TRIVIAL) },
+	{ "recursive-ours", (void *)NO_TRIVIAL },
+	{ "recursive-theirs", (void *)NO_TRIVIAL },
 };
 static struct path_list strategies = { strategy_items,
 	ARRAY_SIZE(strategy_items), 0, 0 };
diff --git a/git.c b/git.c
index 770aadd..f2a8ce5 100644
--- a/git.c
+++ b/git.c
@@ -276,6 +276,8 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "merge-file", cmd_merge_file },
 		{ "merge-ours", cmd_merge_ours, RUN_SETUP },
 		{ "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+		{ "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+		{ "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 		{ "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 		{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
 		{ "name-rev", cmd_name_rev, RUN_SETUP },
diff --git a/ll-merge.c b/ll-merge.c
index 9837c84..c6a05bf 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -19,7 +19,7 @@ typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
 			   mmfile_t *orig,
 			   mmfile_t *src1, const char *name1,
 			   mmfile_t *src2, const char *name2,
-			   int virtual_ancestor);
+			   int flag);
 
 struct ll_merge_driver {
 	const char *name;
@@ -39,13 +39,15 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
 			   mmfile_t *orig,
 			   mmfile_t *src1, const char *name1,
 			   mmfile_t *src2, const char *name2,
-			   int virtual_ancestor)
+			   int flag)
 {
 	/*
 	 * The tentative merge result is "ours" for the final round,
 	 * or common ancestor for an internal merge.  Still return
 	 * "conflicted merge" status.
 	 */
+	int virtual_ancestor = flag & 01;
+
 	mmfile_t *stolen = virtual_ancestor ? orig : src1;
 
 	result->ptr = stolen->ptr;
@@ -60,9 +62,10 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 			mmfile_t *orig,
 			mmfile_t *src1, const char *name1,
 			mmfile_t *src2, const char *name2,
-			int virtual_ancestor)
+			int flag)
 {
 	xpparam_t xpp;
+	int favor = ((flag)>>1) & 03;
 
 	if (buffer_is_binary(orig->ptr, orig->size) ||
 	    buffer_is_binary(src1->ptr, src1->size) ||
@@ -73,14 +76,15 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 				       path_unused,
 				       orig, src1, name1,
 				       src2, name2,
-				       virtual_ancestor);
+				       flag);
 	}
 
 	memset(&xpp, 0, sizeof(xpp));
 	return xdl_merge(orig,
 			 src1, name1,
 			 src2, name2,
-			 &xpp, XDL_MERGE_ZEALOUS,
+			 &xpp,
+			 XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS, favor),
 			 result);
 }
 
@@ -90,11 +94,12 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
 			  mmfile_t *orig,
 			  mmfile_t *src1, const char *name1,
 			  mmfile_t *src2, const char *name2,
-			  int virtual_ancestor)
+			  int flag)
 {
 	char *src, *dst;
 	long size;
 	const int marker_size = 7;
+	int virtual_ancestor = flag & 01;
 
 	int status = ll_xdl_merge(drv_unused, result, path_unused,
 				  orig, src1, NULL, src2, NULL,
@@ -158,7 +163,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
 			mmfile_t *orig,
 			mmfile_t *src1, const char *name1,
 			mmfile_t *src2, const char *name2,
-			int virtual_ancestor)
+			int flag)
 {
 	char temp[3][50];
 	char cmdbuf[2048];
@@ -362,10 +367,11 @@ int ll_merge(mmbuffer_t *result_buf,
 	     mmfile_t *ancestor,
 	     mmfile_t *ours, const char *our_label,
 	     mmfile_t *theirs, const char *their_label,
-	     int virtual_ancestor)
+	     int flag)
 {
 	const char *ll_driver_name;
 	const struct ll_merge_driver *driver;
+	int virtual_ancestor = flag & 01;
 
 	ll_driver_name = git_path_check_merge(path);
 	driver = find_ll_merge_driver(ll_driver_name);
@@ -375,5 +381,5 @@ int ll_merge(mmbuffer_t *result_buf,
 	return driver->fn(driver, result_buf, path,
 			  ancestor,
 			  ours, our_label,
-			  theirs, their_label, virtual_ancestor);
+			  theirs, their_label, flag);
 }
diff --git a/ll-merge.h b/ll-merge.h
index 5388422..5daef58 100644
--- a/ll-merge.h
+++ b/ll-merge.h
@@ -5,11 +5,13 @@
 #ifndef LL_MERGE_H
 #define LL_MERGE_H
 
+#define LL_MERGE_FLAGS(virtual_ancestor,favor) ((!!(virtual_ancestor)) | ((favor)<<1))
+
 int ll_merge(mmbuffer_t *result_buf,
 	     const char *path,
 	     mmfile_t *ancestor,
 	     mmfile_t *ours, const char *our_label,
 	     mmfile_t *theirs, const char *their_label,
-	     int virtual_ancestor);
+	     int flag);
 
 #endif
diff --git a/t/t6034-merge-ours-theirs.sh b/t/t6034-merge-ours-theirs.sh
new file mode 100755
index 0000000..56a9247
--- /dev/null
+++ b/t/t6034-merge-ours-theirs.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description='Merge-recursive ours and theirs variants'
+. ./test-lib.sh
+
+test_expect_success setup '
+	for i in 1 2 3 4 5 6 7 8 9
+	do
+		echo "$i"
+	done >file &&
+	git add file &&
+	cp file elif &&
+	git commit -m initial &&
+
+	sed -e "s/1/one/" -e "s/9/nine/" >file <elif &&
+	git commit -a -m ours &&
+
+	git checkout -b side HEAD^ &&
+
+	sed -e "s/9/nueve/" >file <elif &&
+	git commit -a -m theirs &&
+
+	git checkout master^0
+'
+
+test_expect_success 'plain recursive - should conflict' '
+	git reset --hard master &&
+	test_must_fail git merge -s recursive side &&
+	grep nine file &&
+	grep nueve file &&
+	! grep 9 file &&
+	grep one file &&
+	! grep 1 file
+'
+
+test_expect_success 'recursive favouring theirs' '
+	git reset --hard master &&
+	git merge -s recursive-theirs side &&
+	! grep nine file &&
+	grep nueve file &&
+	! grep 9 file &&
+	grep one file &&
+	! grep 1 file
+'
+
+test_expect_success 'recursive favouring ours' '
+	git reset --hard master &&
+	git merge -s recursive-ours side &&
+	grep nine file &&
+	! grep nueve file &&
+	! grep 9 file &&
+	grep one file &&
+	! grep 1 file
+'
+
+test_done
-- 
1.5.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2008-06-23 12:46 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-16  4:16 Guided merge with override Geoff Russell
2008-06-16  9:25 ` Miklos Vajna
2008-06-16 10:16   ` Johannes Sixt
2008-06-16 21:16     ` Miklos Vajna
2008-06-16 22:21     ` Sverre Rabbelier
2008-06-16 22:45       ` Geoff Russell
2008-06-17 20:04         ` Junio C Hamano
2008-06-18 15:19           ` Johannes Schindelin
2008-06-18 15:28             ` Johannes Schindelin
2008-06-18 16:31               ` Junio C Hamano
2008-06-18 19:29                 ` Johannes Schindelin
2008-06-20  7:38                 ` [PATCH 1/2] git-merge-file --ours, --theirs Junio C Hamano
2008-06-20  7:48                   ` [PATCH 2/2] git-merge-recursive-{ours,theirs} Junio C Hamano
2008-06-20 12:58                     ` Johannes Schindelin
2008-06-21  9:46                       ` Junio C Hamano
2008-06-21 16:29                         ` Johannes Schindelin
2008-06-21 16:56                         ` Jakub Narebski
2008-06-17  6:16       ` Guided merge with override Johannes Sixt
2008-06-17  8:53         ` Sverre Rabbelier
2008-06-17  9:48           ` Johannes Schindelin
2008-06-17  9:53             ` Sverre Rabbelier
2008-06-17 10:17               ` Johannes Schindelin
  -- strict thread matches above, loose matches on Subject: below --
2008-06-23 12:45 [PATCH 0/2] jc/merge-theirs, rebased on top of mv/merge-in-c Miklos Vajna
2008-06-23 12:45 ` [PATCH 2/2] git-merge-recursive-{ours,theirs} Miklos Vajna

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).