directory rename detection: partially renamed directory testcase/discussion

Add a long note about why we are not considering "partial directory renames" for the current directory rename detection implementation. Reviewed-by: Stefan Beller <sbeller@google.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Apr 19, 2018 at 10:57 UTC de632e4ed3cada91f9043363eb1e24f771cd0e0a
1 file changed +115
t/t6043-merge-rename-directories.sh
+115
@@ -735,4 +735,119 @@ test_expect_success '3b-check: Avoid implicit rename if involved as source on cu
735 # of a rename on either side of a merge.
736 ###########################################################################
737
738 +
739 +###########################################################################
740 +# SECTION 4: Partially renamed directory; still exists on both sides of merge
741 +#
742 +# What if we were to attempt to do directory rename detection when someone
743 +# "mostly" moved a directory but still left some files around, or,
744 +# equivalently, fully renamed a directory in one commmit and then recreated
745 +# that directory in a later commit adding some new files and then tried to
746 +# merge?
747 +#
748 +# It's hard to divine user intent in these cases, because you can make an
749 +# argument that, depending on the intermediate history of the side being
750 +# merged, that some users will want files in that directory to
751 +# automatically be detected and renamed, while users with a different
752 +# intermediate history wouldn't want that rename to happen.
753 +#
754 +# I think that it is best to simply not have directory rename detection
755 +# apply to such cases. My reasoning for this is four-fold: (1) it's
756 +# easiest for users in general to figure out what happened if we don't
757 +# apply directory rename detection in any such case, (2) it's an easy rule
758 +# to explain ["We don't do directory rename detection if the directory
759 +# still exists on both sides of the merge"], (3) we can get some hairy
760 +# edge/corner cases that would be really confusing and possibly not even
761 +# representable in the index if we were to even try, and [related to 3] (4)
762 +# attempting to resolve this issue of divining user intent by examining
763 +# intermediate history goes against the spirit of three-way merges and is a
764 +# path towards crazy corner cases that are far more complex than what we're
765 +# already dealing with.
766 +#
767 +# Note that the wording of the rule ("We don't do directory rename
768 +# detection if the directory still exists on both sides of the merge.")
769 +# also excludes "renaming" of a directory into a subdirectory of itself
770 +# (e.g. /some/dir/* -> /some/dir/subdir/*). It may be possible to carve
771 +# out an exception for "renaming"-beneath-itself cases without opening
772 +# weird edge/corner cases for other partial directory renames, but for now
773 +# we are keeping the rule simple.
774 +#
775 +# This section contains a test for a partially-renamed-directory case.
776 +###########################################################################
777 +
778 +# Testcase 4a, Directory split, with original directory still present
779 +# (Related to testcase 1f)
780 +# Commit O: z/{b,c,d,e}
781 +# Commit A: y/{b,c,d}, z/e
782 +# Commit B: z/{b,c,d,e,f}
783 +# Expected: y/{b,c,d}, z/{e,f}
784 +# NOTE: Even though most files from z moved to y, we don't want f to follow.
785 +
786 +test_expect_success '4a-setup: Directory split, with original directory still present' '
787 + test_create_repo 4a &&
788 + (
789 + cd 4a &&
790 +
791 + mkdir z &&
792 + echo b >z/b &&
793 + echo c >z/c &&
794 + echo d >z/d &&
795 + echo e >z/e &&
796 + git add z &&
797 + test_tick &&
798 + git commit -m "O" &&
799 +
800 + git branch O &&
801 + git branch A &&
802 + git branch B &&
803 +
804 + git checkout A &&
805 + mkdir y &&
806 + git mv z/b y/ &&
807 + git mv z/c y/ &&
808 + git mv z/d y/ &&
809 + test_tick &&
810 + git commit -m "A" &&
811 +
812 + git checkout B &&
813 + echo f >z/f &&
814 + git add z/f &&
815 + test_tick &&
816 + git commit -m "B"
817 + )
818 +'
819 +
820 +test_expect_success '4a-check: Directory split, with original directory still present' '
821 + (
822 + cd 4a &&
823 +
824 + git checkout A^0 &&
825 +
826 + git merge -s recursive B^0 &&
827 +
828 + git ls-files -s >out &&
829 + test_line_count = 5 out &&
830 + git ls-files -u >out &&
831 + test_line_count = 0 out &&
832 + git ls-files -o >out &&
833 + test_line_count = 1 out &&
834 +
835 + git rev-parse >actual \
836 + HEAD:y/b HEAD:y/c HEAD:y/d HEAD:z/e HEAD:z/f &&
837 + git rev-parse >expect \
838 + O:z/b O:z/c O:z/d O:z/e B:z/f &&
839 + test_cmp expect actual
840 + )
841 +'
842 +
843 +###########################################################################
844 +# Rules suggested by section 4:
845 +#
846 +# Directory-rename-detection should be turned off for any directories (as
847 +# a source for renames) that exist on both sides of the merge. (The "as
848 +# a source for renames" clarification is due to cases like 1c where
849 +# the target directory exists on both sides and we do want the rename
850 +# detection.) But, sadly, see testcase 8b.
851 +###########################################################################
852 +
853 test_done