Skip to content

Commit 94883b4

Browse files
johnkeepinggitster
authored andcommitted
merge-tree: handle directory/empty conflict correctly
git-merge-tree causes a null pointer dereference when a directory entry exists in only one or two of the three trees being compared with no corresponding entry in the other tree(s). When this happens, we want to handle the entry as a directory and not attempt to mark it as a file merge. Do this by setting the entries bit in the directory mask when the entry is missing or when it is a directory, only performing the file comparison when we know that a file entry exists. Reported-by: Andreas Jacobsen <[email protected]> Signed-off-by: John Keeping <[email protected]> Tested-by: Andreas Jacobsen <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ab5f424 commit 94883b4

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

builtin/merge-tree.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,11 @@ static void unresolved(const struct traverse_info *info, struct name_entry n[3])
251251

252252
for (i = 0; i < 3; i++) {
253253
mask |= (1 << i);
254-
if (n[i].mode && S_ISDIR(n[i].mode))
254+
/*
255+
* Treat missing entries as directories so that we return
256+
* after unresolved_directory has handled this.
257+
*/
258+
if (!n[i].mode || S_ISDIR(n[i].mode))
255259
dirmask |= (1 << i);
256260
}
257261

t/t4300-merge-tree.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,57 @@ EXPECTED
259259
test_cmp expected actual
260260
'
261261

262+
test_expect_success 'tree add A, B (same)' '
263+
cat >expect <<-\EOF &&
264+
EOF
265+
git reset --hard initial &&
266+
mkdir sub &&
267+
test_commit "add sub/file" "sub/file" "file" add-tree-A &&
268+
git merge-tree initial add-tree-A add-tree-A >actual &&
269+
test_cmp expect actual
270+
'
271+
272+
test_expect_success 'tree add A, B (different)' '
273+
cat >expect <<-\EOF &&
274+
added in both
275+
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file
276+
their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 sub/file
277+
@@ -1 +1,5 @@
278+
+<<<<<<< .our
279+
AAA
280+
+=======
281+
+BBB
282+
+>>>>>>> .their
283+
EOF
284+
git reset --hard initial &&
285+
mkdir sub &&
286+
test_commit "add sub/file" "sub/file" "AAA" add-tree-a-b-A &&
287+
git reset --hard initial &&
288+
mkdir sub &&
289+
test_commit "add sub/file" "sub/file" "BBB" add-tree-a-b-B &&
290+
git merge-tree initial add-tree-a-b-A add-tree-a-b-B >actual &&
291+
test_cmp expect actual
292+
'
293+
294+
test_expect_success 'tree unchanged A, removed B' '
295+
cat >expect <<-\EOF &&
296+
removed in remote
297+
base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file
298+
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file
299+
@@ -1 +0,0 @@
300+
-AAA
301+
EOF
302+
git reset --hard initial &&
303+
mkdir sub &&
304+
test_commit "add sub/file" "sub/file" "AAA" tree-remove-b-initial &&
305+
git rm sub/file &&
306+
test_tick &&
307+
git commit -m "remove sub/file" &&
308+
git tag tree-remove-b-B &&
309+
git merge-tree tree-remove-b-initial tree-remove-b-initial tree-remove-b-B >actual &&
310+
test_cmp expect actual
311+
'
312+
262313
test_expect_success 'turn file to tree' '
263314
git reset --hard initial &&
264315
rm initial-file &&

0 commit comments

Comments
 (0)