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 <gitster@pobox.com> Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b45a09c4b4
commit
78d3b06e0f
@ -982,7 +982,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
|
||||
return error("Cannot do a oneway merge of %d trees",
|
||||
o->merge_size);
|
||||
|
||||
if (!a)
|
||||
if (!a || a == o->df_conflict_entry)
|
||||
return deleted_entry(old, old, o);
|
||||
|
||||
if (old && same(old, a)) {
|
||||
|
Loading…
Reference in New Issue
Block a user