1Directory rename detection 2========================== 3 4Rename detection logic in diffcore-rename that checks for renames of 5individual files is aggregated and analyzed in merge-recursive for cases 6where combinations of renames indicate that a full directory has been 7renamed. 8 9Scope of abilities 10------------------ 11 12It 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 18More 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 41Limitations -- applicability of directory renames 42------------------------------------------------- 43 44In order to prevent edge and corner cases resulting in either conflicts 45that cannot be represented in the index or which might be too complex for 46users to try to understand and resolve, a couple basic rules limit when 47directory 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 62Limitations -- detailed rules and testcases 63------------------------------------------- 64 65t/t6043-merge-rename-directories.sh contains extensive tests and commentary 66which generate and explore the rules listed above. It also lists a few 67additional 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 78Limitations -- support in different commands 79-------------------------------------------- 80 81Directory rename detection is supported by 'merge' and 'cherry-pick'. 82Other git commands which users might be surprised to see limited or no 83directory 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.