@@ -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;
@@ -1283,6 +1302,18 @@ 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,
+ extra_marker_size, result);
+ }
+
result->merge = 0;
result->clean = 1;
@@ -230,13 +230,13 @@ test_expect_success 'git detects differently handled merges conflict' '
:2:new_a :3:new_a &&
test_cmp expect actual &&
- git cat-file -p B:new_a >ours &&
- git cat-file -p C:new_a >theirs &&
+ git cat-file -p C:new_a >ours &&
+ git cat-file -p B:new_a >theirs &&
>empty &&
test_must_fail git merge-file \
- -L "Temporary merge branch 2" \
- -L "" \
-L "Temporary merge branch 1" \
+ -L "" \
+ -L "Temporary merge branch 2" \
ours empty theirs &&
sed -e "s/^\([<=>]\)/\1\1\1/" ours >expect &&
git cat-file -p :1:new_a >actual &&