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