Skip to content

Commit 78d3b06

Browse files
committed
checkout -f: deal with a D/F conflict entry correctly
When we switch branches with "checkout -f", unpack_trees() feeds two cache_entries to oneway_merge() function in its src[] array argument. The zeroth entry comes from the current index, and the first entry represents what the merge result should be, taken from the tree recorded in the commit we are switching to. When we have a blob (either regular file or a symlink) in the index and in the work tree at path "foo", and the switched-to tree has "foo/bar", i.e. "foo" becomes a directory, src[0] is obviously that blob currently registered at "foo". Even though we do not have anything at "foo" in the switched-to tree, src[1] is _not_ NULL in this case. The unpack_trees() machinery places a special marker df_conflict_entry to signal that no blob exists at "foo", but it will become a directory that may have somthing underneath it (namely "foo/bar"), so a usual 3-way merge can notice the situation. But oneway_merge() codepath failed to notice this and passed the special marker directly to merged_entry(). This happens to remove the "foo" in the end because the df_conflict_entry does not have any name (hence the "error" message) and its addition in add_index_entry() is rejected, but it is wrong. Signed-off-by: Junio C Hamano <[email protected]> Acked-by: Linus Torvalds <[email protected]>
1 parent b45a09c commit 78d3b06

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

unpack-trees.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
982982
return error("Cannot do a oneway merge of %d trees",
983983
o->merge_size);
984984

985-
if (!a)
985+
if (!a || a == o->df_conflict_entry)
986986
return deleted_entry(old, old, o);
987987

988988
if (old && same(old, a)) {

0 commit comments

Comments
 (0)