directory-rename-detection.txt: technical docs on abilities and limitations

Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Jun 27, 2018 at 00:23 UTC 4d34dffbdd2226034df9d7612f1e221b7143fc6a
1 file changed +92
Documentation/technical/directory-rename-detection.txt new
+92
@@ -0,0 +1,92 @@
1 +Directory rename detection
2 +==========================
3 +
4 +Rename detection logic in diffcore-rename that checks for renames of
5 +individual files is aggregated and analyzed in merge-recursive for cases
6 +where combinations of renames indicate that a full directory has been
7 +renamed.
8 +
9 +Scope of abilities
10 +------------------
11 +
12 +It is perhaps easiest to start with an example:
13 +
14 + * When all of x/a, x/b and x/c have moved to z/a, z/b and z/c, it is
15 + likely that x/d added in the meantime would also want to move to z/d by
16 + taking the hint that the entire directory 'x' moved to 'z'.
17 +
18 +More interesting possibilities exist, though, such as:
19 +
20 + * one side of history renames x -> z, and the other renames some file to
21 + x/e, causing the need for the merge to do a transitive rename.
22 +
23 + * one side of history renames x -> z, but also renames all files within
24 + x. For example, x/a -> z/alpha, x/b -> z/bravo, etc.
25 +
26 + * both 'x' and 'y' being merged into a single directory 'z', with a
27 + directory rename being detected for both x->z and y->z.
28 +
29 + * not all files in a directory being renamed to the same location;
30 + i.e. perhaps most the files in 'x' are now found under 'z', but a few
31 + are found under 'w'.
32 +
33 + * a directory being renamed, which also contained a subdirectory that was
34 + renamed to some entirely different location. (And perhaps the inner
35 + directory itself contained inner directories that were renamed to yet
36 + other locations).
37 +
38 + * combinations of the above; see t/t6043-merge-rename-directories.sh for
39 + various interesting cases.
40 +
41 +Limitations -- applicability of directory renames
42 +-------------------------------------------------
43 +
44 +In order to prevent edge and corner cases resulting in either conflicts
45 +that cannot be represented in the index or which might be too complex for
46 +users to try to understand and resolve, a couple basic rules limit when
47 +directory rename detection applies:
48 +
49 + 1) If a given directory still exists on both sides of a merge, we do
50 + not consider it to have been renamed.
51 +
52 + 2) If a subset of to-be-renamed files have a file or directory in the
53 + way (or would be in the way of each other), "turn off" the directory
54 + rename for those specific sub-paths and report the conflict to the
55 + user.
56 +
57 + 3) If the other side of history did a directory rename to a path that
58 + your side of history renamed away, then ignore that particular
59 + rename from the other side of history for any implicit directory
60 + renames (but warn the user).
61 +
62 +Limitations -- detailed rules and testcases
63 +-------------------------------------------
64 +
65 +t/t6043-merge-rename-directories.sh contains extensive tests and commentary
66 +which generate and explore the rules listed above. It also lists a few
67 +additional rules:
68 +
69 + a) If renames split a directory into two or more others, the directory
70 + with the most renames, "wins".
71 +
72 + b) Avoid directory-rename-detection for a path, if that path is the
73 + source of a rename on either side of a merge.
74 +
75 + c) Only apply implicit directory renames to directories if the other side
76 + of history is the one doing the renaming.
77 +
78 +Limitations -- support in different commands
79 +--------------------------------------------
80 +
81 +Directory rename detection is supported by 'merge' and 'cherry-pick'.
82 +Other git commands which users might be surprised to see limited or no
83 +directory rename detection support in:
84 +
85 + * diff
86 +
87 + Folks have requested in the past that `git diff` detect directory
88 + renames and somehow simplify its output. It is not clear whether this
89 + would be desirable or how the output should be simplified, so this was
90 + simply not implemented. Further, to implement this, directory rename
91 + detection logic would need to move from merge-recursive to
92 + diffcore-rename.