Commit 89ba9f1acc7d6f26ce45a6ccd128a2c270a5fe79

Edward Thomson 2015-03-18T13:17:04

Merge pull request #2967 from jacquesg/merge-whitespace Allow merges of files (and trees) with whitespace problems/fixes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34553aa..4c09582 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@ v0.22 + 1
 
 ### Changes or improvements
 
+* Patience and minimal diff drivers can now be used for merges.
+
+* Merges can now ignore whitespace changes.
+
 * Updated binary identification in CRLF filtering to avoid false positives in
   UTF-8 files.
 
@@ -26,6 +30,8 @@ v0.22 + 1
 
 ### API additions
 
+* The `git_merge_options` gained a `file_flags` member.
+
 * Parsing and retrieving a configuration value as a path is exposed
   via `git_config_parse_path()` and `git_config_get_path()`
   respectively.
@@ -55,6 +61,12 @@ v0.22 + 1
 
 ### Breaking API changes
 
+* The `git_merge_options` structure member `flags` has been renamed
+  to `tree_flags`.
+
+* The `git_merge_file_options` structure member `tree_flags` is now
+  an unsigned int. It was previously a `git_merge_file_flags_t`.
+
 * `GIT_CHECKOUT_SAFE_CREATE` has been removed.  Most users will generally
   be able to switch to `GIT_CHECKOUT_SAFE`, but if you require missing
   file handling during checkout, you may now use `GIT_CHECKOUT_SAFE |
diff --git a/include/git2/merge.h b/include/git2/merge.h
index 40330d0..d3360a7 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -63,7 +63,7 @@ GIT_EXTERN(int) git_merge_file_init_input(
 
 /**
  * Flags for `git_merge_tree` options.  A combination of these flags can be
- * passed in via the `flags` value in the `git_merge_options`.
+ * passed in via the `tree_flags` value in the `git_merge_options`.
  */
 typedef enum {
 	/**
@@ -125,6 +125,21 @@ typedef enum {
 
 	/** Condense non-alphanumeric regions for simplified diff file */
 	GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 2),
+
+	/** Ignore all whitespace */
+	GIT_MERGE_FILE_IGNORE_WHITESPACE = (1 << 3),
+
+	/** Ignore changes in amount of whitespace */
+	GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE = (1 << 4),
+
+	/** Ignore whitespace at end of line */
+	GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL = (1 << 5),
+
+	/** Use the "patience diff" algorithm */
+	GIT_MERGE_FILE_DIFF_PATIENCE = (1 << 6),
+
+	/** Take extra time to find minimal diff */
+	GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7),
 } git_merge_file_flags_t;
 
 /**
@@ -155,7 +170,7 @@ typedef struct {
 	git_merge_file_favor_t favor;
 
 	/** Merge file flags. */
-	git_merge_file_flags_t flags;
+	unsigned int flags;
 } git_merge_file_options;
 
 #define GIT_MERGE_FILE_OPTIONS_VERSION 1
@@ -205,7 +220,7 @@ typedef struct {
  */
 typedef struct {
 	unsigned int version;
-	git_merge_tree_flag_t flags;
+	git_merge_tree_flag_t tree_flags;
 
 	/**
 	 * Similarity to consider a file renamed (default 50).  If
@@ -230,6 +245,8 @@ typedef struct {
 
 	/** Flags for handling conflicting content. */
 	git_merge_file_favor_t file_favor;
+
+	unsigned int file_flags;
 } git_merge_options;
 
 #define GIT_MERGE_OPTIONS_VERSION 1
diff --git a/src/merge.c b/src/merge.c
index 449a178..bd676aa 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -658,7 +658,8 @@ static int merge_conflict_resolve_automerge(
 	int *resolved,
 	git_merge_diff_list *diff_list,
 	const git_merge_diff *conflict,
-	unsigned int merge_file_favor)
+	unsigned int merge_file_favor,
+	unsigned int file_flags)
 {
 	const git_index_entry *ancestor = NULL, *ours = NULL, *theirs = NULL;
 	git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
@@ -716,6 +717,7 @@ static int merge_conflict_resolve_automerge(
 		&conflict->their_entry : NULL;
 
 	opts.favor = merge_file_favor;
+	opts.flags = file_flags;
 
 	if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
 		(error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, &opts)) < 0 ||
@@ -749,7 +751,8 @@ static int merge_conflict_resolve(
 	int *out,
 	git_merge_diff_list *diff_list,
 	const git_merge_diff *conflict,
-	unsigned int merge_file_favor)
+	unsigned int merge_file_favor,
+	unsigned int file_flags)
 {
 	int resolved = 0;
 	int error = 0;
@@ -765,7 +768,8 @@ static int merge_conflict_resolve(
 	if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
 		goto done;
 
-	if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, merge_file_favor)) < 0)
+	if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict,
+		merge_file_favor, file_flags)) < 0)
 		goto done;
 
 	*out = resolved;
@@ -1158,7 +1162,7 @@ int git_merge_diff_list__find_renames(
 
 	assert(diff_list && opts);
 
-	if ((opts->flags & GIT_MERGE_TREE_FIND_RENAMES) == 0)
+	if ((opts->tree_flags & GIT_MERGE_TREE_FIND_RENAMES) == 0)
 		return 0;
 
 	similarity_ours = git__calloc(diff_list->conflicts.length,
@@ -1600,7 +1604,7 @@ static int merge_normalize_opts(
 		git_merge_options init = GIT_MERGE_OPTIONS_INIT;
 		memcpy(opts, &init, sizeof(init));
 
-		opts->flags = GIT_MERGE_TREE_FIND_RENAMES;
+		opts->tree_flags = GIT_MERGE_TREE_FIND_RENAMES;
 		opts->rename_threshold = GIT_MERGE_TREE_RENAME_THRESHOLD;
 	}
 
@@ -1790,7 +1794,7 @@ int git_merge_trees(
 	git_vector_foreach(&changes, i, conflict) {
 		int resolved = 0;
 
-		if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor)) < 0)
+		if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor, opts.file_flags)) < 0)
 			goto done;
 
 		if (!resolved)
diff --git a/src/merge_file.c b/src/merge_file.c
index ff03644..6d89b08 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -151,6 +151,19 @@ static int git_merge_file__from_inputs(
 	if (options.flags & GIT_MERGE_FILE_STYLE_DIFF3)
 		xmparam.style = XDL_MERGE_DIFF3;
 
+	if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE)
+		xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE;
+	if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE)
+		xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE_CHANGE;
+	if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL)
+		xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE_AT_EOL;
+
+	if (options.flags & GIT_MERGE_FILE_DIFF_PATIENCE)
+		xmparam.xpp.flags |= XDF_PATIENCE_DIFF;
+
+	if (options.flags & GIT_MERGE_FILE_DIFF_MINIMAL)
+		xmparam.xpp.flags |= XDF_NEED_MINIMAL;
+
 	if ((xdl_result = xdl_merge(&ancestor_mmfile, &our_mmfile,
 		&their_mmfile, &xmparam, &mmbuffer)) < 0) {
 		giterr_set(GITERR_MERGE, "Failed to merge files.");
diff --git a/tests/cherrypick/workdir.c b/tests/cherrypick/workdir.c
index f8b4ca2..787f1f4 100644
--- a/tests/cherrypick/workdir.c
+++ b/tests/cherrypick/workdir.c
@@ -300,7 +300,7 @@ void test_cherrypick_workdir__rename(void)
 		{ 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 0, "file3.txt.renamed" },
 	};
 
-	opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	opts.merge_opts.rename_threshold = 50;
 
 	git_oid_fromstr(&head_oid, "cfc4f0999a8367568e049af4f72e452d40828a15");
@@ -335,7 +335,7 @@ void test_cherrypick_workdir__both_renamed(void)
 		{ 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 2, "file3.txt.renamed_on_branch" },
 	};
 
-	opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	opts.merge_opts.rename_threshold = 50;
 
 	git_oid_fromstr(&head_oid, "44cd2ed2052c9c68f9a439d208e9614dc2a55c70");
diff --git a/tests/merge/files.c b/tests/merge/files.c
index c377471..7f461ab 100644
--- a/tests/merge/files.c
+++ b/tests/merge/files.c
@@ -173,3 +173,79 @@ void test_merge_files__automerge_from_index(void)
 
 	git_merge_file_result_free(&result);
 }
+
+void test_merge_files__automerge_whitespace_eol(void)
+{
+	git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
+		ours = GIT_MERGE_FILE_INPUT_INIT,
+		theirs = GIT_MERGE_FILE_INPUT_INIT;
+	git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
+	git_merge_file_result result = {0};
+	const char *expected = "Zero\n1\n2\n3\n4\n5\n6\n7\n8\n9\nTen\n";
+
+	ancestor.ptr = "0 \n1\n2\n3\n4\n5\n6\n7\n8\n9\n10 \n";
+	ancestor.size = strlen(ancestor.ptr);
+	ancestor.path = "testfile.txt";
+	ancestor.mode = 0100755;
+
+	ours.ptr = "Zero\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n";
+	ours.size = strlen(ours.ptr);
+	ours.path = "testfile.txt";
+	ours.mode = 0100755;
+
+	theirs.ptr = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\nTen\n";
+	theirs.size = strlen(theirs.ptr);
+	theirs.path = "testfile.txt";
+	theirs.mode = 0100755;
+
+	opts.flags |= GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL;
+	cl_git_pass(git_merge_file(&result, &ancestor, &ours, &theirs, &opts));
+
+	cl_assert_equal_i(1, result.automergeable);
+
+	cl_assert_equal_s("testfile.txt", result.path);
+	cl_assert_equal_i(0100755, result.mode);
+
+	cl_assert_equal_i(strlen(expected), result.len);
+	cl_assert_equal_strn(expected, result.ptr, result.len);
+
+	git_merge_file_result_free(&result);
+}
+
+void test_merge_files__automerge_whitespace_change(void)
+{
+	git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
+		ours = GIT_MERGE_FILE_INPUT_INIT,
+		theirs = GIT_MERGE_FILE_INPUT_INIT;
+	git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
+	git_merge_file_result result = {0};
+	const char *expected = "Zero\n1\n2\n3\n4\n5 XXX\n6 YYY\n7\n8\n9\nTen\n";
+
+	ancestor.ptr = "0\n1\n2\n3\n4\n5 XXX\n6YYY\n7\n8\n9\n10\n";
+	ancestor.size = strlen(ancestor.ptr);
+	ancestor.path = "testfile.txt";
+	ancestor.mode = 0100755;
+
+	ours.ptr = "Zero\n1\n2\n3\n4\n5 XXX\n6 YYY\n7\n8\n9\n10\n";
+	ours.size = strlen(ours.ptr);
+	ours.path = "testfile.txt";
+	ours.mode = 0100755;
+
+	theirs.ptr = "0\n1\n2\n3\n4\n5 XXX\n6  YYY\n7\n8\n9\nTen\n";
+	theirs.size = strlen(theirs.ptr);
+	theirs.path = "testfile.txt";
+	theirs.mode = 0100755;
+
+	opts.flags |= GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE;
+	cl_git_pass(git_merge_file(&result, &ancestor, &ours, &theirs, &opts));
+
+	cl_assert_equal_i(1, result.automergeable);
+
+	cl_assert_equal_s("testfile.txt", result.path);
+	cl_assert_equal_i(0100755, result.mode);
+
+	cl_assert_equal_i(strlen(expected), result.len);
+	cl_assert_equal_strn(expected, result.ptr, result.len);
+
+	git_merge_file_result_free(&result);
+}
diff --git a/tests/merge/trees/treediff.c b/tests/merge/trees/treediff.c
index 8b47f7d..eea651d 100644
--- a/tests/merge/trees/treediff.c
+++ b/tests/merge/trees/treediff.c
@@ -45,7 +45,7 @@ static void test_find_differences(
     git_tree *ancestor_tree, *ours_tree, *theirs_tree;
 
 	git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
-	opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	opts.target_limit = 1000;
 	opts.rename_threshold = 50;
 
diff --git a/tests/merge/trees/whitespace.c b/tests/merge/trees/whitespace.c
new file mode 100644
index 0000000..b99583c
--- /dev/null
+++ b/tests/merge/trees/whitespace.c
@@ -0,0 +1,82 @@
+#include "clar_libgit2.h"
+#include "git2/repository.h"
+#include "git2/merge.h"
+#include "buffer.h"
+#include "merge.h"
+#include "../merge_helpers.h"
+#include "fileops.h"
+
+static git_repository *repo;
+
+#define TEST_REPO_PATH "merge-whitespace"
+
+#define BRANCH_A_EOL  "branch_a_eol"
+#define BRANCH_B_EOL  "branch_b_eol"
+
+#define BRANCH_A_CHANGE  "branch_a_change"
+#define BRANCH_B_CHANGE  "branch_b_change"
+
+// Fixture setup and teardown
+void test_merge_trees_whitespace__initialize(void)
+{
+	repo = cl_git_sandbox_init(TEST_REPO_PATH);
+}
+
+void test_merge_trees_whitespace__cleanup(void)
+{
+	cl_git_sandbox_cleanup();
+}
+
+void test_merge_trees_whitespace__conflict(void)
+{
+	git_index *index;
+	git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
+
+	struct merge_index_entry merge_index_entries[] = {
+		{ 0100644, "4026a6c83f39c56881c9ac62e7582db9e3d33a4f", 1, "test.txt" },
+		{ 0100644, "c3b1fb31424c98072542cc8e42b48c92e52f494a", 2, "test.txt" },
+		{ 0100644, "262f67de0de2e535a59ae1bc3c739601e98c354d", 3, "test.txt" },
+	};
+
+	cl_git_pass(merge_trees_from_branches(&index, repo, BRANCH_A_EOL, BRANCH_B_EOL, &opts));
+
+	cl_assert(merge_test_index(index, merge_index_entries, 3));
+
+	git_index_free(index);
+}
+
+void test_merge_trees_whitespace__eol(void)
+{
+	git_index *index;
+	git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
+
+	struct merge_index_entry merge_index_entries[] = {
+		{ 0100644, "ee3c2aac8e03224c323b58ecb1f9eef616745467", 0, "test.txt" },
+	};
+
+	opts.file_flags |= GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL;
+
+	cl_git_pass(merge_trees_from_branches(&index, repo, BRANCH_A_EOL, BRANCH_B_EOL, &opts));
+
+	cl_assert(merge_test_index(index, merge_index_entries, 1));
+
+	git_index_free(index);
+}
+
+void test_merge_trees_whitespace__change(void)
+{
+	git_index *index;
+	git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
+
+	struct merge_index_entry merge_index_entries[] = {
+		{ 0100644, "a827eab4fd66ab37a6ebcfaa7b7e341abfd55947", 0, "test.txt" },
+	};
+
+	opts.file_flags |= GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE;
+
+	cl_git_pass(merge_trees_from_branches(&index, repo, BRANCH_A_CHANGE, BRANCH_B_CHANGE, &opts));
+
+	cl_assert(merge_test_index(index, merge_index_entries, 1));
+
+	git_index_free(index);
+}
diff --git a/tests/merge/workdir/renames.c b/tests/merge/workdir/renames.c
index 807a88f..83006a7 100644
--- a/tests/merge/workdir/renames.c
+++ b/tests/merge/workdir/renames.c
@@ -63,7 +63,7 @@ void test_merge_workdir_renames__renames(void)
 		{ 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" },
 	};
 
-	merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	merge_opts.rename_threshold = 50;
 
 	cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &merge_opts, NULL));
@@ -99,7 +99,7 @@ void test_merge_workdir_renames__ours(void)
 		{ 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt" },
 	};
 
-	merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	merge_opts.rename_threshold = 50;
 	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS;
 
@@ -147,7 +147,7 @@ void test_merge_workdir_renames__similar(void)
 		{ 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" },
 	};
 
-	merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	merge_opts.rename_threshold = 50;
 
 	cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &merge_opts, NULL));
diff --git a/tests/resources/merge-whitespace/.gitted/HEAD b/tests/resources/merge-whitespace/.gitted/HEAD
new file mode 100644
index 0000000..cb089cd
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/merge-whitespace/.gitted/config b/tests/resources/merge-whitespace/.gitted/config
new file mode 100644
index 0000000..6c9406b
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/config
@@ -0,0 +1,7 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+	ignorecase = true
+	precomposeunicode = true
diff --git a/tests/resources/merge-whitespace/.gitted/index b/tests/resources/merge-whitespace/.gitted/index
new file mode 100644
index 0000000..534804a
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/index differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/01/bd650462136a4f0a266dfc91ab93b3fef0f7cb b/tests/resources/merge-whitespace/.gitted/objects/01/bd650462136a4f0a266dfc91ab93b3fef0f7cb
new file mode 100644
index 0000000..074a77a
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/01/bd650462136a4f0a266dfc91ab93b3fef0f7cb differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/08/3f868fb4324e32a4999173b2437b31d7a1ef25 b/tests/resources/merge-whitespace/.gitted/objects/08/3f868fb4324e32a4999173b2437b31d7a1ef25
new file mode 100644
index 0000000..ec6ed4d
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/08/3f868fb4324e32a4999173b2437b31d7a1ef25 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/0a/a2acaa63cacc7a99fab0c2ce3d56572911df19 b/tests/resources/merge-whitespace/.gitted/objects/0a/a2acaa63cacc7a99fab0c2ce3d56572911df19
new file mode 100644
index 0000000..a2178ce
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/0a/a2acaa63cacc7a99fab0c2ce3d56572911df19
@@ -0,0 +1 @@
+xA @Qלb&fR!1Ɲ[Lqb#L&z~K:F*3g
)qJZ&B{;xk-2_78s-˻mSIhr
Zq{C%Ӥ>4?
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/objects/11/89e10a62aadf2fea8cd018afb52c1980f40b4f b/tests/resources/merge-whitespace/.gitted/objects/11/89e10a62aadf2fea8cd018afb52c1980f40b4f
new file mode 100644
index 0000000..f9f5984
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/11/89e10a62aadf2fea8cd018afb52c1980f40b4f differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/24/2c8f6cf388e96e2c12b6e49cb7ae60167cba1e b/tests/resources/merge-whitespace/.gitted/objects/24/2c8f6cf388e96e2c12b6e49cb7ae60167cba1e
new file mode 100644
index 0000000..7cfc318
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/24/2c8f6cf388e96e2c12b6e49cb7ae60167cba1e differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/25/246acb001858ffeffb03ea399fd2c0a163b832 b/tests/resources/merge-whitespace/.gitted/objects/25/246acb001858ffeffb03ea399fd2c0a163b832
new file mode 100644
index 0000000..f7160ce
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/25/246acb001858ffeffb03ea399fd2c0a163b832 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/26/2f67de0de2e535a59ae1bc3c739601e98c354d b/tests/resources/merge-whitespace/.gitted/objects/26/2f67de0de2e535a59ae1bc3c739601e98c354d
new file mode 100644
index 0000000..c5a33b4
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/26/2f67de0de2e535a59ae1bc3c739601e98c354d differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/2f/6727d2e570bf962d9dd926423cf6fe5072071a b/tests/resources/merge-whitespace/.gitted/objects/2f/6727d2e570bf962d9dd926423cf6fe5072071a
new file mode 100644
index 0000000..02bb788
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/2f/6727d2e570bf962d9dd926423cf6fe5072071a differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/3c/43e7fc2a56fc825c31dfee65abd6dda8d16dca b/tests/resources/merge-whitespace/.gitted/objects/3c/43e7fc2a56fc825c31dfee65abd6dda8d16dca
new file mode 100644
index 0000000..0ec95b5
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/3c/43e7fc2a56fc825c31dfee65abd6dda8d16dca differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/40/26a6c83f39c56881c9ac62e7582db9e3d33a4f b/tests/resources/merge-whitespace/.gitted/objects/40/26a6c83f39c56881c9ac62e7582db9e3d33a4f
new file mode 100644
index 0000000..50bdfc5
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/40/26a6c83f39c56881c9ac62e7582db9e3d33a4f differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/42/dabb8d5dba2de103815a77e4369bb3966e64ef b/tests/resources/merge-whitespace/.gitted/objects/42/dabb8d5dba2de103815a77e4369bb3966e64ef
new file mode 100644
index 0000000..ae6dab7
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/42/dabb8d5dba2de103815a77e4369bb3966e64ef differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/43/9230587f2eb38e9540a5c99e9831f65641eab9 b/tests/resources/merge-whitespace/.gitted/objects/43/9230587f2eb38e9540a5c99e9831f65641eab9
new file mode 100644
index 0000000..1b6354d
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/43/9230587f2eb38e9540a5c99e9831f65641eab9 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/43/ad73e75e15f03bb0b4398a48a57ecfc20788e2 b/tests/resources/merge-whitespace/.gitted/objects/43/ad73e75e15f03bb0b4398a48a57ecfc20788e2
new file mode 100644
index 0000000..1936bc3
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/43/ad73e75e15f03bb0b4398a48a57ecfc20788e2 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/tests/resources/merge-whitespace/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
new file mode 100644
index 0000000..adf6411
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/54/74989173042512ab630191ad71cdcedb646b9a b/tests/resources/merge-whitespace/.gitted/objects/54/74989173042512ab630191ad71cdcedb646b9a
new file mode 100644
index 0000000..cf12d4d
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/54/74989173042512ab630191ad71cdcedb646b9a differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/5e/fb9bc29c482e023e40e0a2b3b7e49cec842034 b/tests/resources/merge-whitespace/.gitted/objects/5e/fb9bc29c482e023e40e0a2b3b7e49cec842034
new file mode 100644
index 0000000..d615c02
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/5e/fb9bc29c482e023e40e0a2b3b7e49cec842034 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/70/d3d2e7d51a18fcc6f035a67e5c3f33069be04d b/tests/resources/merge-whitespace/.gitted/objects/70/d3d2e7d51a18fcc6f035a67e5c3f33069be04d
new file mode 100644
index 0000000..1718878
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/70/d3d2e7d51a18fcc6f035a67e5c3f33069be04d differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/74/e83b6c5df14f1fba7c4ea1f99c6d007b591002 b/tests/resources/merge-whitespace/.gitted/objects/74/e83b6c5df14f1fba7c4ea1f99c6d007b591002
new file mode 100644
index 0000000..779e1bc
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/74/e83b6c5df14f1fba7c4ea1f99c6d007b591002 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/77/f40c621ceae77ad8d756ef507bdbafe2713aa7 b/tests/resources/merge-whitespace/.gitted/objects/77/f40c621ceae77ad8d756ef507bdbafe2713aa7
new file mode 100644
index 0000000..f2efa93
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/77/f40c621ceae77ad8d756ef507bdbafe2713aa7 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/9c/5362069759fb37ae036cef6e4b2f95c6c5eaab b/tests/resources/merge-whitespace/.gitted/objects/9c/5362069759fb37ae036cef6e4b2f95c6c5eaab
new file mode 100644
index 0000000..cc6ad10
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/9c/5362069759fb37ae036cef6e4b2f95c6c5eaab differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/a2/9e7dabd68dfb38a717e6b1648713cd5c7adee2 b/tests/resources/merge-whitespace/.gitted/objects/a2/9e7dabd68dfb38a717e6b1648713cd5c7adee2
new file mode 100644
index 0000000..6e03437
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/a2/9e7dabd68dfb38a717e6b1648713cd5c7adee2 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/a4/e6a86e07ef5afe036e26602fbbaa27496d00a9 b/tests/resources/merge-whitespace/.gitted/objects/a4/e6a86e07ef5afe036e26602fbbaa27496d00a9
new file mode 100644
index 0000000..95e0d71
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/a4/e6a86e07ef5afe036e26602fbbaa27496d00a9
@@ -0,0 +1,2 @@
+xMJ@])j7A:]"3U5ՓIYx{#'p<uCMKP3[d
+0Tq6|PӥCX>ZEk(DA	EPk!Xs}\|yk>oMA	ϱL_t3`ZdAe
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/objects/a8/27eab4fd66ab37a6ebcfaa7b7e341abfd55947 b/tests/resources/merge-whitespace/.gitted/objects/a8/27eab4fd66ab37a6ebcfaa7b7e341abfd55947
new file mode 100644
index 0000000..fe2bdf4
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/a8/27eab4fd66ab37a6ebcfaa7b7e341abfd55947 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/a9/66acc271e50b5d4595911752a77def0a5e5d40 b/tests/resources/merge-whitespace/.gitted/objects/a9/66acc271e50b5d4595911752a77def0a5e5d40
new file mode 100644
index 0000000..cd6f64d
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/a9/66acc271e50b5d4595911752a77def0a5e5d40 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/b2/a69114f4897109fedf1aafea363cb2d2557029 b/tests/resources/merge-whitespace/.gitted/objects/b2/a69114f4897109fedf1aafea363cb2d2557029
new file mode 100644
index 0000000..b95a7be
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/b2/a69114f4897109fedf1aafea363cb2d2557029 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/bc/83ac0422ba1082c80e406234910377984cfbb6 b/tests/resources/merge-whitespace/.gitted/objects/bc/83ac0422ba1082c80e406234910377984cfbb6
new file mode 100644
index 0000000..0ea77e8
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/bc/83ac0422ba1082c80e406234910377984cfbb6 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/bf/e4ea5805af22a5b194259bda6f5f634486f891 b/tests/resources/merge-whitespace/.gitted/objects/bf/e4ea5805af22a5b194259bda6f5f634486f891
new file mode 100644
index 0000000..a27169e
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/bf/e4ea5805af22a5b194259bda6f5f634486f891
@@ -0,0 +1 @@
+xMj0F)flA)%B/x4Jcho_!}T׵X?HcC)iL`??`ʎffnxЈ	tf4Y!;M$,'>/_}wiT70u)FF8i:*ԈZp!1(-MozX 
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/objects/c3/b1fb31424c98072542cc8e42b48c92e52f494a b/tests/resources/merge-whitespace/.gitted/objects/c3/b1fb31424c98072542cc8e42b48c92e52f494a
new file mode 100644
index 0000000..4006460
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/c3/b1fb31424c98072542cc8e42b48c92e52f494a differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/c7/e2f386736445936f5ba181269a0e0967e280e8 b/tests/resources/merge-whitespace/.gitted/objects/c7/e2f386736445936f5ba181269a0e0967e280e8
new file mode 100644
index 0000000..821336f
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/c7/e2f386736445936f5ba181269a0e0967e280e8
@@ -0,0 +1,2 @@
+xAj0E)fEȒFA)
+=CQFY^MI{><>^YyЛ*5X|&Ęl"Rg>!٘*>Z֨A\XbAeT
H:(C9Vч@R}\qyk;&TG57zK/yvQKpߓ`ZOl$e
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/objects/d9/5182053c31f8aa09df4fa225f4e668c5320b59 b/tests/resources/merge-whitespace/.gitted/objects/d9/5182053c31f8aa09df4fa225f4e668c5320b59
new file mode 100644
index 0000000..6b9483a
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/d9/5182053c31f8aa09df4fa225f4e668c5320b59
@@ -0,0 +1,5 @@
+xM
+0@a9$M/z:
+1I^#4Eh.:M'6uv&k
`JY
+Z 5D1$9zgXI:,nįM
+\%OcwgsyJ^ƸC, ~WQaRVbh~,3\gR
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests/resources/merge-whitespace/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
new file mode 100644
index 0000000..7112238
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/ec/5a35c75b8d3ee29bed37996b14e909d04fdcee b/tests/resources/merge-whitespace/.gitted/objects/ec/5a35c75b8d3ee29bed37996b14e909d04fdcee
new file mode 100644
index 0000000..d7fc301
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/ec/5a35c75b8d3ee29bed37996b14e909d04fdcee differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/ee/3c2aac8e03224c323b58ecb1f9eef616745467 b/tests/resources/merge-whitespace/.gitted/objects/ee/3c2aac8e03224c323b58ecb1f9eef616745467
new file mode 100644
index 0000000..1acec06
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/ee/3c2aac8e03224c323b58ecb1f9eef616745467 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/ef/e94a4bf4e697f7f0270f0d1b8a93af784a19d0 b/tests/resources/merge-whitespace/.gitted/objects/ef/e94a4bf4e697f7f0270f0d1b8a93af784a19d0
new file mode 100644
index 0000000..ca5af40
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/ef/e94a4bf4e697f7f0270f0d1b8a93af784a19d0 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/f0/0c965d8307308469e537302baa73048488f162 b/tests/resources/merge-whitespace/.gitted/objects/f0/0c965d8307308469e537302baa73048488f162
new file mode 100644
index 0000000..343037e
Binary files /dev/null and b/tests/resources/merge-whitespace/.gitted/objects/f0/0c965d8307308469e537302baa73048488f162 differ
diff --git a/tests/resources/merge-whitespace/.gitted/objects/f1/90a0d111ca1688778657798743ddfb4ed4bd64 b/tests/resources/merge-whitespace/.gitted/objects/f1/90a0d111ca1688778657798743ddfb4ed4bd64
new file mode 100644
index 0000000..4e22912
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/f1/90a0d111ca1688778657798743ddfb4ed4bd64
@@ -0,0 +1,2 @@
+xM
+0@a9Eo.o1IZ![nZԥad!y![fCԎQaVn̉Y%0PJk!;@@=>xS%h{E^iyE?&tHv0g+t[WD\ܷqM
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/objects/f4/9b2c244e9d3b0647fdfb95954c38fbfeecf3ad b/tests/resources/merge-whitespace/.gitted/objects/f4/9b2c244e9d3b0647fdfb95954c38fbfeecf3ad
new file mode 100644
index 0000000..437f667
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/f4/9b2c244e9d3b0647fdfb95954c38fbfeecf3ad
@@ -0,0 +1,2 @@
+x=
+1@abzAfI-!,.xۯx/mСWU(dRt}@j9.2;O"KTelV{h֒:>
.=oz8\ab^ĞHf}R<
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/objects/f8/7905f99f0e66d179a8379d8ca4d8cbbd32c231 b/tests/resources/merge-whitespace/.gitted/objects/f8/7905f99f0e66d179a8379d8ca4d8cbbd32c231
new file mode 100644
index 0000000..d568dc1
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/objects/f8/7905f99f0e66d179a8379d8ca4d8cbbd32c231
@@ -0,0 +1 @@
+xKj0D)E tg50@ g0-e;`;#ˋ> WEQe2ZQaoj7{L9IH}sLgrvŊ!9!:G͞mz*2aM:kzѦNCv.uם׽ՙmySx=3h&*>b5Mr!iu׶=܁i
\ No newline at end of file
diff --git a/tests/resources/merge-whitespace/.gitted/refs/heads/branch_a_change b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_a_change
new file mode 100644
index 0000000..3a46eff
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_a_change
@@ -0,0 +1 @@
+d95182053c31f8aa09df4fa225f4e668c5320b59
diff --git a/tests/resources/merge-whitespace/.gitted/refs/heads/branch_a_eol b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_a_eol
new file mode 100644
index 0000000..a59d5b5
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_a_eol
@@ -0,0 +1 @@
+9c5362069759fb37ae036cef6e4b2f95c6c5eaab
diff --git a/tests/resources/merge-whitespace/.gitted/refs/heads/branch_b_change b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_b_change
new file mode 100644
index 0000000..c14ced3
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_b_change
@@ -0,0 +1 @@
+b2a69114f4897109fedf1aafea363cb2d2557029
diff --git a/tests/resources/merge-whitespace/.gitted/refs/heads/branch_b_eol b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_b_eol
new file mode 100644
index 0000000..9e25c6e
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/refs/heads/branch_b_eol
@@ -0,0 +1 @@
+bfe4ea5805af22a5b194259bda6f5f634486f891
diff --git a/tests/resources/merge-whitespace/.gitted/refs/heads/master b/tests/resources/merge-whitespace/.gitted/refs/heads/master
new file mode 100644
index 0000000..61e8ae7
--- /dev/null
+++ b/tests/resources/merge-whitespace/.gitted/refs/heads/master
@@ -0,0 +1 @@
+1189e10a62aadf2fea8cd018afb52c1980f40b4f
diff --git a/tests/resources/merge-whitespace/test.txt b/tests/resources/merge-whitespace/test.txt
new file mode 100644
index 0000000..74e83b6
--- /dev/null
+++ b/tests/resources/merge-whitespace/test.txt
@@ -0,0 +1,11 @@
+0
+1
+2
+3
+4
+5 XXX
+6
+7
+8
+9
+10
diff --git a/tests/revert/workdir.c b/tests/revert/workdir.c
index 171cacb..7ccf0f9 100644
--- a/tests/revert/workdir.c
+++ b/tests/revert/workdir.c
@@ -408,7 +408,7 @@ void test_revert_workdir__rename_1_of_2(void)
 		{ 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 2, "file6.txt" },
 	};
 
-	opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	opts.merge_opts.rename_threshold = 50;
 
 	git_oid_fromstr(&head_oid, "cef56612d71a6af8d8015691e4865f7fece905b5");
@@ -442,7 +442,7 @@ void test_revert_workdir__rename(void)
 		{ "file4.txt", "file5.txt", "" },
 	};
 
-	opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
+	opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES;
 	opts.merge_opts.rename_threshold = 50;
 
 	git_oid_fromstr(&head_oid, "55568c8de5322ff9a95d72747a239cdb64a19965");