From Wikipedia:
Renames are handled implicitly rather than explicitly. A common
complaint with CVS is that it uses the name of a file to identify its
revision history, so moving or renaming a file is not possible without
either interrupting its history, or renaming the history and thereby
making the history inaccurate. Most post-CVS revision control systems
solve this by giving a file a unique long-lived name (a sort of inode
number) that survives renaming. Git does not record such an
identifier, and this is claimed as an advantage.[34][35] Source code
files are sometimes split or merged as well as simply renamed,[36] and
recording this as a simple rename would freeze an inaccurate
description of what happened in the (immutable) history. Git addresses
the issue by detecting renames while browsing the history of snapshots
rather than recording it when making the snapshot.[37] (Briefly, given
a file in revision N, a file of the same name in revision N−1 is its
default ancestor. However, when there is no like-named file in
revision N−1, Git searches for a file that existed only in revision
N−1 and is very similar to the new file.) However, it does require
more CPU-intensive work every time history is reviewed, and a number
of options to adjust the heuristics. This mechanism does not always
work; sometimes a file that is renamed with changes in the same commit
is read as a deletion of the old file and the creation of a new file.
Developers can work around this limitation by committing the rename
and changes separately.