Code

checkout -f: deal with a D/F conflict entry correctly
authorJunio C Hamano <gitster@pobox.com>
Sat, 18 Jul 2009 19:26:38 +0000 (12:26 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 18 Jul 2009 23:57:30 +0000 (16:57 -0700)
commit78d3b06e0f5e6aaea001ee8e3e7c8e401dc4b244
tree39ce7676e891ff709b13d6dbae15739e6118350e
parentb45a09c4b4a80ccc6eeb0f390ab8f4eb6f31c922
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>
unpack-trees.c