Let’s talk a bit more about how Git keeps track of file renames.
Subversion, as an example of traditional revision control, does a lot of work when tracking when a file is renamed and moved around, because it keeps track only of diffs between files. If you move a file, it’s essentially the same as deleting all the lines from the old file and adding them to the new one. But it would be very inefficient to transfer and store all the contents of the file again whenever you do a simple rename; imagine renaming a whole subdirectory that contains thousands of files.
To alleviate this situation, Subversion tracks each rename explicitly. If you want to
rename hello.txt to
subdir/hello.txt, you must use
mv instead of
svn rm and
add on the files. Otherwise, Subversion has no way to see that
it’s a rename and must go through the inefficient delete/add sequence
Next, given this exceptional feature of tracking a rename, the Subversion server needs a special protocol to tell its clients, “Please move hello.txt into subdir/hello.txt.” Furthermore, each Subversion client must ensure that it performs this (relatively rare) operation correctly.
Git, on the other hand, doesn’t keep track of a rename. You can move or copy hello.txt anywhere you want, but doing so affects only tree objects. (Remember that tree objects store the relationships between content, whereas the content itself is stored in blobs.) A look at the differences between two trees makes ...