I would like to rename/move a project subtree in Git moving it from
/project/xyz
to
/components/xyz
If I
I would like to rename/move a project subtree in Git moving it from
/project/xyzto
/components/xyz
If I use a plain
git mv project components, then all the commit history for thexyzproject gets lost.
No (8 years later, Git 2.19, Q3 2018), because Git will detect the directory rename, and this is now better documented.
See commit b00bf1c, commit 1634688, commit 0661e49, commit 4d34dff, commit 983f464, commit c840e1a, commit 9929430 (27 Jun 2018), and commit d4e8062, commit 5dacd4a (25 Jun 2018) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit 0ce5a69, 24 Jul 2018)
That is now explained in Documentation/technical/directory-rename-detection.txt:
Example:
When all of
x/a,x/bandx/chave moved toz/a,z/bandz/c, it is likely thatx/dadded in the meantime would also want to move toz/dby taking the hint that the entire directory 'x' moved to 'z'.
But they are many other cases, like:
one side of history renames
x -> z, and the other renames some file tox/e, causing the need for the merge to do a transitive rename.
To simplify directory rename detection, those rules are enforced by Git:
a couple basic rules limit when directory rename detection applies:
- If a given directory still exists on both sides of a merge, we do not consider it to have been renamed.
- If a subset of to-be-renamed files have a file or directory in the way (or would be in the way of each other), "turn off" the directory rename for those specific sub-paths and report the conflict to the user.
- If the other side of history did a directory rename to a path that your side of history renamed away, then ignore that particular rename from the other side of history for any implicit directory renames (but warn the user).
You can see a lot of tests in t/t6043-merge-rename-directories.sh, which also point out that:
- a) If renames split a directory into two or more others, the directory with the most renames, "wins".
- b) Avoid directory-rename-detection for a path, if that path is the source of a rename on either side of a merge.
- c) Only apply implicit directory renames to directories if the other side of history is the one doing the renaming.