Skip to content

Commit 4d34dff

Browse files
newrengitster
authored andcommitted
directory-rename-detection.txt: technical docs on abilities and limitations
Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 983f464 commit 4d34dff

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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.

0 commit comments

Comments
 (0)