Skip to content

Commit e6d29a4

Browse files
committed
Merge branch 'jc/ll-merge-binary-ours'
"git merge -Xtheirs" did not help content-level merge of binary files; it should just take their version. Also "*.jpg binary" in the attributes did not imply they should use the binary ll-merge driver. * jc/ll-merge-binary-ours: ll-merge: warn about inability to merge binary files only when we can't attr: "binary" attribute should choose built-in "binary" merge driver merge: teach -Xours/-Xtheirs to binary ll-merge driver
2 parents 1b96965 + e0e2065 commit e6d29a4

File tree

5 files changed

+41
-12
lines changed

5 files changed

+41
-12
lines changed

Documentation/gitattributes.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ file at the toplevel (i.e. not in any subdirectory). The built-in
927927
macro attribute "binary" is equivalent to:
928928

929929
------------
930-
[attr]binary -diff -text
930+
[attr]binary -diff -merge -text
931931
------------
932932

933933

Documentation/merge-strategies.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@ ours;;
3232
This option forces conflicting hunks to be auto-resolved cleanly by
3333
favoring 'our' version. Changes from the other tree that do not
3434
conflict with our side are reflected to the merge result.
35+
For a binary file, the entire contents are taken from our side.
3536
+
3637
This should not be confused with the 'ours' merge strategy, which does not
3738
even look at what the other tree contains at all. It discards everything
3839
the other tree did, declaring 'our' history contains all that happened in it.
3940

4041
theirs;;
41-
This is opposite of 'ours'.
42+
This is the opposite of 'ours'.
4243

4344
patience;;
4445
With this option, 'merge-recursive' spends a little extra time

attr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ static void free_attr_elem(struct attr_stack *e)
306306
}
307307

308308
static const char *builtin_attr[] = {
309-
"[attr]binary -diff -text",
309+
"[attr]binary -diff -merge -text",
310310
NULL,
311311
};
312312

ll-merge.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct ll_merge_driver {
3535
*/
3636
static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
3737
mmbuffer_t *result,
38-
const char *path_unused,
38+
const char *path,
3939
mmfile_t *orig, const char *orig_name,
4040
mmfile_t *src1, const char *name1,
4141
mmfile_t *src2, const char *name2,
@@ -46,16 +46,34 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
4646
assert(opts);
4747

4848
/*
49-
* The tentative merge result is "ours" for the final round,
50-
* or common ancestor for an internal merge. Still return
51-
* "conflicted merge" status.
49+
* The tentative merge result is the or common ancestor for an internal merge.
5250
*/
53-
stolen = opts->virtual_ancestor ? orig : src1;
51+
if (opts->virtual_ancestor) {
52+
stolen = orig;
53+
} else {
54+
switch (opts->variant) {
55+
default:
56+
warning("Cannot merge binary files: %s (%s vs. %s)",
57+
path, name1, name2);
58+
/* fallthru */
59+
case XDL_MERGE_FAVOR_OURS:
60+
stolen = src1;
61+
break;
62+
case XDL_MERGE_FAVOR_THEIRS:
63+
stolen = src2;
64+
break;
65+
}
66+
}
5467

5568
result->ptr = stolen->ptr;
5669
result->size = stolen->size;
5770
stolen->ptr = NULL;
58-
return 1;
71+
72+
/*
73+
* With -Xtheirs or -Xours, we have cleanly merged;
74+
* otherwise we got a conflict.
75+
*/
76+
return (opts->variant ? 0 : 1);
5977
}
6078

6179
static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
@@ -73,8 +91,6 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
7391
if (buffer_is_binary(orig->ptr, orig->size) ||
7492
buffer_is_binary(src1->ptr, src1->size) ||
7593
buffer_is_binary(src2->ptr, src2->size)) {
76-
warning("Cannot merge binary files: %s (%s vs. %s)",
77-
path, name1, name2);
7894
return ll_binary_merge(drv_unused, result,
7995
path,
8096
orig, orig_name,

t/t6037-merge-ours-theirs.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,19 @@ test_expect_success 'recursive favouring ours' '
5353
! grep 1 file
5454
'
5555

56-
test_expect_success 'pull with -X' '
56+
test_expect_success 'binary file with -Xours/-Xtheirs' '
57+
echo file binary >.gitattributes &&
58+
59+
git reset --hard master &&
60+
git merge -s recursive -X theirs side &&
61+
git diff --exit-code side HEAD -- file &&
62+
63+
git reset --hard master &&
64+
git merge -s recursive -X ours side &&
65+
git diff --exit-code master HEAD -- file
66+
'
67+
68+
test_expect_success 'pull passes -X to underlying merge' '
5769
git reset --hard master && git pull -s recursive -Xours . side &&
5870
git reset --hard master && git pull -s recursive -X ours . side &&
5971
git reset --hard master && git pull -s recursive -Xtheirs . side &&

0 commit comments

Comments
 (0)