summaryrefslogtreecommitdiff
path: root/merge-recursive.c
diff options
context:
space:
mode:
Diffstat (limited to 'merge-recursive.c')
-rw-r--r--merge-recursive.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/merge-recursive.c b/merge-recursive.c
index 0684dab779..acc2f64a4e 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -228,7 +228,26 @@ static inline void setup_rename_conflict_info(enum rename_type rename_type,
struct stage_data *src_entry1,
struct stage_data *src_entry2)
{
- struct rename_conflict_info *ci = xcalloc(1, sizeof(struct rename_conflict_info));
+ struct rename_conflict_info *ci;
+
+ /*
+ * When we have two renames involved, it's easiest to get the
+ * correct things into stage 2 and 3, and to make sure that the
+ * content merge puts HEAD before the other branch if we just
+ * ensure that branch1 == o->branch1. So, simply flip arguments
+ * around if we don't have that.
+ */
+ if (dst_entry2 && branch1 != o->branch1) {
+ setup_rename_conflict_info(rename_type,
+ pair2, pair1,
+ branch2, branch1,
+ dst_entry2, dst_entry1,
+ o,
+ src_entry2, src_entry1);
+ return;
+ }
+
+ ci = xcalloc(1, sizeof(struct rename_conflict_info));
ci->rename_type = rename_type;
ci->pair1 = pair1;
ci->branch1 = branch1;
@@ -1084,7 +1103,8 @@ static int merge_3way(struct merge_options *o,
read_mmblob(&src2, &b->oid);
merge_status = ll_merge(result_buf, a->path, &orig, base_name,
- &src1, name1, &src2, name2, &ll_opts);
+ &src1, name1, &src2, name2,
+ &the_index, &ll_opts);
free(base_name);
free(name1);
@@ -1115,7 +1135,7 @@ static int find_first_merges(struct object_array *result, const char *path,
/* get all revisions that merge commit a */
xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
oid_to_hex(&a->object.oid));
- init_revisions(&revs, NULL);
+ repo_init_revisions(the_repository, &revs, NULL);
rev_opts.submodule = path;
/* FIXME: can't handle linked worktrees in submodules yet */
revs.single_worktree = path != NULL;
@@ -1283,6 +1303,17 @@ static int merge_mode_and_contents(struct merge_options *o,
const char *branch2,
struct merge_file_info *result)
{
+ if (o->branch1 != branch1) {
+ /*
+ * It's weird getting a reverse merge with HEAD on the bottom
+ * side of the conflict markers and the other branch on the
+ * top. Fix that.
+ */
+ return merge_mode_and_contents(o, one, b, a,
+ filename,
+ branch2, branch1, result);
+ }
+
result->merge = 0;
result->clean = 1;
@@ -1674,8 +1705,8 @@ static int handle_rename_rename_2to1(struct merge_options *o,
remove_file(o, 1, a->path, o->call_depth || would_lose_untracked(a->path));
remove_file(o, 1, b->path, o->call_depth || would_lose_untracked(b->path));
- path_side_1_desc = xstrfmt("%s (was %s)", path, a->path);
- path_side_2_desc = xstrfmt("%s (was %s)", path, b->path);
+ path_side_1_desc = xstrfmt("version of %s from %s", path, a->path);
+ path_side_2_desc = xstrfmt("version of %s from %s", path, b->path);
if (merge_mode_and_contents(o, a, c1, &ci->ren1_other, path_side_1_desc,
o->branch1, o->branch2, &mfi_c1) ||
merge_mode_and_contents(o, b, &ci->ren2_other, c2, path_side_2_desc,
@@ -1756,7 +1787,7 @@ static struct diff_queue_struct *get_diffpairs(struct merge_options *o,
struct diff_queue_struct *ret;
struct diff_options opts;
- diff_setup(&opts);
+ repo_diff_setup(the_repository, &opts);
opts.flags.recursive = 1;
opts.flags.rename_empty = 0;
opts.detect_rename = merge_detect_rename(o);