summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/merge.c67
-rw-r--r--tests/merge/conflict_data.h31
-rw-r--r--tests/merge/trees/recursive.c80
-rw-r--r--tests/merge/workdir/recursive.c35
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/15/311229e70fa62653f73dde1d4deef1a8e47a11bin0 -> 710 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/37/185b25a204309bf74817da1a607518f13ca3edbin0 -> 715 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/37/a5054a9f9b4628e3924c5cb8f2147c6e2a3efcbin0 -> 630 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/42/44d13e2bbc38510320443bbb003f3967d12436bin0 -> 207 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/4f/4e85a0ab8515e34302721fbcec06fa9d9c1a9abin0 -> 631 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/56/07a8c4601a737daadd1f470bde3142aff570261
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/63/e8773becdea9c3699c95a5740be5baa8be8d69bin0 -> 207 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/6c/778edd0e4cf394f5a3df8b96db516024cc1bb8bin0 -> 636 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d1
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/7a/9277e0c5ec75339f011c176d0c20e513c4de1c1
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3bin0 -> 208 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/98/1c79eb38518d3821e73bb159dc413bb42d6614bin0 -> 208 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/a0/2d4fd126e0cc8fb46ee48cf38bad36d44f2dbcbin0 -> 649 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/aa/9e263294fd2f6f6fd9ceab23ca8ce3ea2ce707bin0 -> 175 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/b9/1ef5ffa8612616c8e76051901caafd723f0e2cbin0 -> 712 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/ca/fa936d25f0b397432a27201f6b3284c47df8bebin0 -> 712 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/d6/04c75019c282144bdbbf3fd3462ba74b240efcbin0 -> 620 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/db/203155a789fb749aa3c14e93eea2c744a9c6c71
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/e1/512550f09d980214e46e6d3f5a2b20c3d75755bin0 -> 208 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/f7/929c5a67a4bdc98247fb4b5098675723932a64bin0 -> 207 bytes
-rw-r--r--tests/resources/merge-recursive/.gitted/refs/heads/branchH-11
-rw-r--r--tests/resources/merge-recursive/.gitted/refs/heads/branchH-21
-rw-r--r--tests/resources/merge-recursive/.gitted/refs/heads/branchI-11
-rw-r--r--tests/resources/merge-recursive/.gitted/refs/heads/branchI-21
28 files changed, 201 insertions, 20 deletions
diff --git a/src/merge.c b/src/merge.c
index 64c8f1116..f05e45c9f 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -49,6 +49,19 @@
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
+
+/** Internal merge flags. */
+enum {
+ /** The merge is for a virtual base in a recursive merge. */
+ GIT_MERGE__VIRTUAL_BASE = (1 << 31),
+};
+
+enum {
+ /** Accept the conflict file, staging it as the merge result. */
+ GIT_MERGE_FILE_FAVOR__CONFLICTED = 4,
+};
+
+
typedef enum {
TREE_IDX_ANCESTOR = 0,
TREE_IDX_OURS = 1,
@@ -801,11 +814,9 @@ 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 file_flags)
+ const git_merge_file_options *file_opts)
{
const git_index_entry *ancestor = NULL, *ours = NULL, *theirs = NULL;
- git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_result result = {0};
git_index_entry *index_entry;
git_odb *odb = NULL;
@@ -852,12 +863,9 @@ static int merge_conflict_resolve_automerge(
theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
&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 ||
- !result.automergeable ||
+ (error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, file_opts)) < 0 ||
+ (!result.automergeable && !(file_opts->flags & GIT_MERGE_FILE_FAVOR__CONFLICTED)) ||
(error = git_odb_write(&automerge_oid, odb, result.ptr, result.len, GIT_OBJ_BLOB)) < 0)
goto done;
@@ -887,8 +895,7 @@ 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 file_flags)
+ const git_merge_file_options *file_opts)
{
int resolved = 0;
int error = 0;
@@ -904,8 +911,7 @@ 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, file_flags)) < 0)
+ if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, file_opts)) < 0)
goto done;
*out = resolved;
@@ -1829,6 +1835,7 @@ int git_merge__iterators(
*empty_theirs = NULL;
git_merge_diff_list *diff_list;
git_merge_options opts;
+ git_merge_file_options file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_diff *conflict;
git_vector changes;
size_t i;
@@ -1844,6 +1851,17 @@ int git_merge__iterators(
if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0)
return error;
+ file_opts.favor = opts.file_favor;
+ file_opts.flags = opts.file_flags;
+
+ /* use the git-inspired labels when virtual base building */
+ if (opts.flags & GIT_MERGE__VIRTUAL_BASE) {
+ file_opts.ancestor_label = "merged common ancestors";
+ file_opts.our_label = "Temporary merge branch 1";
+ file_opts.their_label = "Temporary merge branch 2";
+ file_opts.flags |= GIT_MERGE_FILE_FAVOR__CONFLICTED;
+ }
+
diff_list = git_merge_diff_list__alloc(repo);
GITERR_CHECK_ALLOC(diff_list);
@@ -1862,7 +1880,8 @@ int git_merge__iterators(
git_vector_foreach(&changes, i, conflict) {
int resolved = 0;
- if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor, opts.file_flags)) < 0)
+ if ((error = merge_conflict_resolve(
+ &resolved, diff_list, conflict, &file_opts)) < 0)
goto done;
if (!resolved) {
@@ -1962,16 +1981,27 @@ static int create_virtual_base(
git_repository *repo,
git_annotated_commit *one,
git_annotated_commit *two,
+ const git_merge_options *opts,
size_t recursion_level)
{
git_annotated_commit *result = NULL;
git_index *index = NULL;
+ git_merge_options virtual_opts = GIT_MERGE_OPTIONS_INIT;
result = git__calloc(1, sizeof(git_annotated_commit));
GITERR_CHECK_ALLOC(result);
+ /* Conflicts in the merge base creation do not propagate to conflicts
+ * in the result; the conflicted base will act as the common ancestor.
+ */
+ if (opts)
+ memcpy(&virtual_opts, opts, sizeof(git_merge_options));
+
+ virtual_opts.flags &= ~GIT_MERGE_FAIL_ON_CONFLICT;
+ virtual_opts.flags |= GIT_MERGE__VIRTUAL_BASE;
+
if ((merge_annotated_commits(&index, NULL, repo, one, two,
- recursion_level + 1, NULL)) < 0)
+ recursion_level + 1, &virtual_opts)) < 0)
return -1;
result->type = GIT_ANNOTATED_COMMIT_VIRTUAL;
@@ -1989,7 +2019,7 @@ static int compute_base(
git_repository *repo,
const git_annotated_commit *one,
const git_annotated_commit *two,
- bool recurse,
+ const git_merge_options *opts,
size_t recursion_level)
{
git_array_oid_t head_ids = GIT_ARRAY_INIT;
@@ -2007,7 +2037,7 @@ static int compute_base(
if ((error = git_merge_bases_many(&bases, repo,
head_ids.size, head_ids.ptr)) < 0 ||
(error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0 ||
- !recurse)
+ (opts && (opts->flags & GIT_MERGE_NO_RECURSIVE)))
goto done;
for (i = 1; i < bases.count; i++) {
@@ -2015,7 +2045,7 @@ static int compute_base(
if ((error = git_annotated_commit_lookup(&other, repo,
&bases.ids[i])) < 0 ||
- (error = create_virtual_base(&new_base, repo, base, other,
+ (error = create_virtual_base(&new_base, repo, base, other, opts,
recursion_level)) < 0)
goto done;
@@ -2076,10 +2106,9 @@ static int merge_annotated_commits(
{
git_annotated_commit *base = NULL;
git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL;
- bool recurse = !opts || !(opts->flags & GIT_MERGE_NO_RECURSIVE);
int error;
- if ((error = compute_base(&base, repo, ours, theirs, recurse,
+ if ((error = compute_base(&base, repo, ours, theirs, opts,
recursion_level)) < 0) {
if (error != GIT_ENOTFOUND)
diff --git a/tests/merge/conflict_data.h b/tests/merge/conflict_data.h
index b6c51332f..e6394a9e8 100644
--- a/tests/merge/conflict_data.h
+++ b/tests/merge/conflict_data.h
@@ -70,3 +70,34 @@
"This is a mighty fine recipe!\n" \
">>>>>>> branchF-2\n"
+#define CONFLICTING_RECURSIVE_H1_TO_H2_WITH_DIFF3 \
+ "VEAL SOUP.\n" \
+ "\n" \
+ "<<<<<<< HEAD\n" \
+ "put into a pot three quarts of water, three onions cut small, one\n" \
+ "||||||| merged common ancestors\n" \
+ "<<<<<<< Temporary merge branch 1\n" \
+ "Put into a pot three quarts of water, THREE ONIONS CUT SMALL, one\n" \
+ "||||||| merged common ancestors\n" \
+ "Put into a pot three quarts of water, three onions cut small, one\n" \
+ "=======\n" \
+ "PUT INTO A POT three quarts of water, three onions cut small, one\n" \
+ ">>>>>>> Temporary merge branch 2\n" \
+ "=======\n" \
+ "Put Into A Pot Three Quarts of Water, Three Onions Cut Small, One\n" \
+ ">>>>>>> branchH-2\n" \
+ "spoonful of black pepper pounded, and two of salt, with two or three\n" \
+ "slices of lean ham; let it boil steadily two hours; skim it\n" \
+ "occasionally, then put into it a shin of veal, let it boil two hours\n" \
+ "longer; take out the slices of ham, and skim off the grease if any\n" \
+ "should rise, take a gill of good cream, mix with it two table-spoonsful\n" \
+ "of flour very nicely, and the yelks of two eggs beaten well, strain this\n" \
+ "mixture, and add some chopped parsley; pour some soup on by degrees,\n" \
+ "stir it well, and pour it into the pot, continuing to stir until it has\n" \
+ "boiled two or three minutes to take off the raw taste of the eggs. If\n" \
+ "the cream be not perfectly sweet, and the eggs quite new, the thickening\n" \
+ "will curdle in the soup. For a change you may put a dozen ripe tomatos\n" \
+ "in, first taking off their skins, by letting them stand a few minutes in\n" \
+ "hot water, when they may be easily peeled. When made in this way you\n" \
+ "must thicken it with the flour only. Any part of the veal may be used,\n" \
+ "but the shin or knuckle is the nicest.\n"
diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c
index 1e5f61391..693c91065 100644
--- a/tests/merge/trees/recursive.c
+++ b/tests/merge/trees/recursive.c
@@ -297,3 +297,83 @@ void test_merge_trees_recursive__oh_so_many_levels_of_recursion(void)
git_index_free(index);
}
+
+/* Branch H-1 and H-2 have two common ancestors (aa9e263, 6ef31d3). The two
+ * ancestors themselves conflict.
+ */
+void test_merge_trees_recursive__conflicting_merge_base(void)
+{
+ git_index *index;
+ git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
+ { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
+ { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
+ { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
+ { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
+ { 0100644, "3a66812fed1e03ea4a6a7ee28d8a57aec1ca6537", 1, "veal.txt" },
+ { 0100644, "d604c75019c282144bdbbf3fd3462ba74b240efc", 2, "veal.txt" },
+ { 0100644, "37a5054a9f9b4628e3924c5cb8f2147c6e2a3efc", 3, "veal.txt" },
+ };
+
+ cl_git_pass(merge_commits_from_branches(&index, repo, "branchH-1", "branchH-2", &opts));
+
+ cl_assert(merge_test_index(index, merge_index_entries, 8));
+
+ git_index_free(index);
+}
+
+/* Branch H-1 and H-2 have two common ancestors (aa9e263, 6ef31d3). The two
+ * ancestors themselves conflict. The generated common ancestor file will
+ * have diff3 style conflicts inside it.
+ */
+void test_merge_trees_recursive__conflicting_merge_base_with_diff3(void)
+{
+ git_index *index;
+ git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
+ { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
+ { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
+ { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
+ { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
+ { 0100644, "cd17a91513f3aee9e44114d1ede67932dd41d2fc", 1, "veal.txt" },
+ { 0100644, "d604c75019c282144bdbbf3fd3462ba74b240efc", 2, "veal.txt" },
+ { 0100644, "37a5054a9f9b4628e3924c5cb8f2147c6e2a3efc", 3, "veal.txt" },
+ };
+
+ opts.file_flags |= GIT_MERGE_FILE_STYLE_DIFF3;
+
+ cl_git_pass(merge_commits_from_branches(&index, repo, "branchH-1", "branchH-2", &opts));
+
+ cl_assert(merge_test_index(index, merge_index_entries, 8));
+
+ git_index_free(index);
+}
+
+/* Branch I-1 and I-2 have two common ancestors (aa9e263, 6ef31d3). The two
+ * ancestors themselves conflict, but when each was merged, the conflicts were
+ * resolved identically, thus merging I-1 into I-2 does not conflict.
+ */
+void test_merge_trees_recursive__conflicting_merge_base_since_resolved(void)
+{
+ git_index *index;
+ git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
+ { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
+ { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
+ { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
+ { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
+ { 0100644, "a02d4fd126e0cc8fb46ee48cf38bad36d44f2dbc", 0, "veal.txt" },
+ };
+
+ cl_git_pass(merge_commits_from_branches(&index, repo, "branchI-1", "branchI-2", &opts));
+
+ cl_assert(merge_test_index(index, merge_index_entries, 6));
+
+ git_index_free(index);
+}
diff --git a/tests/merge/workdir/recursive.c b/tests/merge/workdir/recursive.c
index a7326009a..795126255 100644
--- a/tests/merge/workdir/recursive.c
+++ b/tests/merge/workdir/recursive.c
@@ -36,7 +36,6 @@ void test_merge_workdir_recursive__writes_conflict_with_virtual_base(void)
{ 0100644, "3855170cef875708da06ab9ad7fc6a73b531cda1", 3, "veal.txt" },
};
-
cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR "branchF-1", GIT_REFS_HEADS_DIR "branchF-2", &opts, NULL));
cl_git_pass(git_repository_index(&index, repo));
@@ -49,3 +48,37 @@ void test_merge_workdir_recursive__writes_conflict_with_virtual_base(void)
git_index_free(index);
git_buf_free(&conflicting_buf);
}
+
+void test_merge_workdir_recursive__conflicting_merge_base_with_diff3(void)
+{
+ git_index *index;
+ git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
+ git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
+ { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
+ { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
+ { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
+ { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
+ { 0100644, "cd17a91513f3aee9e44114d1ede67932dd41d2fc", 1, "veal.txt" },
+ { 0100644, "d604c75019c282144bdbbf3fd3462ba74b240efc", 2, "veal.txt" },
+ { 0100644, "37a5054a9f9b4628e3924c5cb8f2147c6e2a3efc", 3, "veal.txt" },
+ };
+
+ opts.file_flags |= GIT_MERGE_FILE_STYLE_DIFF3;
+ checkout_opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
+
+ cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR "branchH-1", GIT_REFS_HEADS_DIR "branchH-2", &opts, &checkout_opts));
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_assert(merge_test_index(index, merge_index_entries, 8));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf, "merge-recursive/veal.txt"));
+
+ cl_assert_equal_s(CONFLICTING_RECURSIVE_H1_TO_H2_WITH_DIFF3, conflicting_buf.ptr);
+
+ git_index_free(index);
+ git_buf_free(&conflicting_buf);
+}
diff --git a/tests/resources/merge-recursive/.gitted/objects/15/311229e70fa62653f73dde1d4deef1a8e47a11 b/tests/resources/merge-recursive/.gitted/objects/15/311229e70fa62653f73dde1d4deef1a8e47a11
new file mode 100644
index 000000000..8c21bb357
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/15/311229e70fa62653f73dde1d4deef1a8e47a11
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/37/185b25a204309bf74817da1a607518f13ca3ed b/tests/resources/merge-recursive/.gitted/objects/37/185b25a204309bf74817da1a607518f13ca3ed
new file mode 100644
index 000000000..a8cf005bc
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/37/185b25a204309bf74817da1a607518f13ca3ed
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/37/a5054a9f9b4628e3924c5cb8f2147c6e2a3efc b/tests/resources/merge-recursive/.gitted/objects/37/a5054a9f9b4628e3924c5cb8f2147c6e2a3efc
new file mode 100644
index 000000000..4591f0e04
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/37/a5054a9f9b4628e3924c5cb8f2147c6e2a3efc
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/42/44d13e2bbc38510320443bbb003f3967d12436 b/tests/resources/merge-recursive/.gitted/objects/42/44d13e2bbc38510320443bbb003f3967d12436
new file mode 100644
index 000000000..a19b19120
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/42/44d13e2bbc38510320443bbb003f3967d12436
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/4f/4e85a0ab8515e34302721fbcec06fa9d9c1a9a b/tests/resources/merge-recursive/.gitted/objects/4f/4e85a0ab8515e34302721fbcec06fa9d9c1a9a
new file mode 100644
index 000000000..4752ea07a
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/4f/4e85a0ab8515e34302721fbcec06fa9d9c1a9a
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/56/07a8c4601a737daadd1f470bde3142aff57026 b/tests/resources/merge-recursive/.gitted/objects/56/07a8c4601a737daadd1f470bde3142aff57026
new file mode 100644
index 000000000..bf3639d05
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/56/07a8c4601a737daadd1f470bde3142aff57026
@@ -0,0 +1 @@
+xMJ1])#?<čp:3w=Ԧ((~`MxCrBYMSP-}tjzL`JRvR jBV8Ze&6zsTr͵̍2.9>~I~Gs1G!j1IcS1xW(܎u#rbV \ No newline at end of file
diff --git a/tests/resources/merge-recursive/.gitted/objects/63/e8773becdea9c3699c95a5740be5baa8be8d69 b/tests/resources/merge-recursive/.gitted/objects/63/e8773becdea9c3699c95a5740be5baa8be8d69
new file mode 100644
index 000000000..6d5c320fe
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/63/e8773becdea9c3699c95a5740be5baa8be8d69
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/6c/778edd0e4cf394f5a3df8b96db516024cc1bb8 b/tests/resources/merge-recursive/.gitted/objects/6c/778edd0e4cf394f5a3df8b96db516024cc1bb8
new file mode 100644
index 000000000..ec1db19e6
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/6c/778edd0e4cf394f5a3df8b96db516024cc1bb8
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d b/tests/resources/merge-recursive/.gitted/objects/6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d
new file mode 100644
index 000000000..e95a5e2db
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d
@@ -0,0 +1 @@
+xAN!]sahcx$2gpWE:z8‡5UA-YG zAl+&LLd>cW.-&͊)BI5o&p<gq/`n,<"!^C#anr]]Bɧ_*PV \ No newline at end of file
diff --git a/tests/resources/merge-recursive/.gitted/objects/7a/9277e0c5ec75339f011c176d0c20e513c4de1c b/tests/resources/merge-recursive/.gitted/objects/7a/9277e0c5ec75339f011c176d0c20e513c4de1c
new file mode 100644
index 000000000..9fb34f7ee
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/7a/9277e0c5ec75339f011c176d0c20e513c4de1c
@@ -0,0 +1 @@
+xOANE!sN>1nLܸ0ނc nڦiSӠwsP!gwaZB,CiB@HT ԰P(g@(*h7+,N*ĕd.5P6{|(mOaOo{8"Pbrױ^uɃO_.`s?o0Xa \ No newline at end of file
diff --git a/tests/resources/merge-recursive/.gitted/objects/88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3 b/tests/resources/merge-recursive/.gitted/objects/88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3
new file mode 100644
index 000000000..44efd3315
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/98/1c79eb38518d3821e73bb159dc413bb42d6614 b/tests/resources/merge-recursive/.gitted/objects/98/1c79eb38518d3821e73bb159dc413bb42d6614
new file mode 100644
index 000000000..d5787b44d
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/98/1c79eb38518d3821e73bb159dc413bb42d6614
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/a0/2d4fd126e0cc8fb46ee48cf38bad36d44f2dbc b/tests/resources/merge-recursive/.gitted/objects/a0/2d4fd126e0cc8fb46ee48cf38bad36d44f2dbc
new file mode 100644
index 000000000..566976715
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/a0/2d4fd126e0cc8fb46ee48cf38bad36d44f2dbc
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/aa/9e263294fd2f6f6fd9ceab23ca8ce3ea2ce707 b/tests/resources/merge-recursive/.gitted/objects/aa/9e263294fd2f6f6fd9ceab23ca8ce3ea2ce707
new file mode 100644
index 000000000..0ec6cd891
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/aa/9e263294fd2f6f6fd9ceab23ca8ce3ea2ce707
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/b9/1ef5ffa8612616c8e76051901caafd723f0e2c b/tests/resources/merge-recursive/.gitted/objects/b9/1ef5ffa8612616c8e76051901caafd723f0e2c
new file mode 100644
index 000000000..e19652394
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/b9/1ef5ffa8612616c8e76051901caafd723f0e2c
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/ca/fa936d25f0b397432a27201f6b3284c47df8be b/tests/resources/merge-recursive/.gitted/objects/ca/fa936d25f0b397432a27201f6b3284c47df8be
new file mode 100644
index 000000000..fb012eea3
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/ca/fa936d25f0b397432a27201f6b3284c47df8be
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/d6/04c75019c282144bdbbf3fd3462ba74b240efc b/tests/resources/merge-recursive/.gitted/objects/d6/04c75019c282144bdbbf3fd3462ba74b240efc
new file mode 100644
index 000000000..059fcfe72
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/d6/04c75019c282144bdbbf3fd3462ba74b240efc
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/db/203155a789fb749aa3c14e93eea2c744a9c6c7 b/tests/resources/merge-recursive/.gitted/objects/db/203155a789fb749aa3c14e93eea2c744a9c6c7
new file mode 100644
index 000000000..e9f7fd8fd
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/db/203155a789fb749aa3c14e93eea2c744a9c6c7
@@ -0,0 +1 @@
+xMJ1]$_q;/t;D Ԧ((K k2S A,J*b[,'KG dyRP0PuF1 o$jL 81}l}6'q/}9nC#$mQ'=-DŽzN<h{XkE\cZ \ No newline at end of file
diff --git a/tests/resources/merge-recursive/.gitted/objects/e1/512550f09d980214e46e6d3f5a2b20c3d75755 b/tests/resources/merge-recursive/.gitted/objects/e1/512550f09d980214e46e6d3f5a2b20c3d75755
new file mode 100644
index 000000000..a5f506fb3
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/e1/512550f09d980214e46e6d3f5a2b20c3d75755
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/objects/f7/929c5a67a4bdc98247fb4b5098675723932a64 b/tests/resources/merge-recursive/.gitted/objects/f7/929c5a67a4bdc98247fb4b5098675723932a64
new file mode 100644
index 000000000..2861579e8
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/f7/929c5a67a4bdc98247fb4b5098675723932a64
Binary files differ
diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchH-1 b/tests/resources/merge-recursive/.gitted/refs/heads/branchH-1
new file mode 100644
index 000000000..ffe9f8cf3
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/refs/heads/branchH-1
@@ -0,0 +1 @@
+7a9277e0c5ec75339f011c176d0c20e513c4de1c
diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchH-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchH-2
new file mode 100644
index 000000000..84ed1a2a9
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/refs/heads/branchH-2
@@ -0,0 +1 @@
+db203155a789fb749aa3c14e93eea2c744a9c6c7
diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchI-1 b/tests/resources/merge-recursive/.gitted/refs/heads/branchI-1
new file mode 100644
index 000000000..2d1ecd026
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/refs/heads/branchI-1
@@ -0,0 +1 @@
+5607a8c4601a737daadd1f470bde3142aff57026
diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchI-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchI-2
new file mode 100644
index 000000000..fc360bae2
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/refs/heads/branchI-2
@@ -0,0 +1 @@
+f7929c5a67a4bdc98247fb4b5098675723932a64