Background
It's important to note that renames work in git are special.
Due to the fundamental nature of how git works, renames are not recorded into the version control system. They are reconstructed after the fact, in the same way that diff hunks are, by comparing the binary content of files between revisions.
This means that file_a
and file_b
, are considered "renamed" between two revisions if file_a
is deleted, file_a
is added and they are "similar" enough. (I believe the default is 50%). Note that this means finding renames requires a bit more computation.
It also means that renames can often only be detected by walking the entire range of revisions. Unless, the rename is basically the only change in the range, say HEAD
and HEAD~100
, in such case it can also be detected using git diff --name-status --diff-filter=R
.
How to list all renames in current branch
You can't use git-rev-list
for this, you need to use git-log
.
git log --name-status -M90%\
--diff-filter=R --pretty=format: |
sed\
-e '/^$/{N;s@^\n$@@}'\
-e 's@\(^\n\{0,1\}\)R[0-9]\{3\}\t@\1@'
--name-status
, --pretty=format:
just display the old name <tab>
new name, no subject etc. of regular git-log
.
-M90%
, how similar counts as difference -M100%
for identical (only renamed).
--diff-filter=R
, only show renames
sed
massage the output
-e '/^$/{N;s@^\n$@@}'
strip output from commits with no renames (2x+ \n
)
-e 's@\(^\n\{0,1\}\)R[0-9]\{3\}\t@\1@'
, massage the output to old_name <tab>
new_name
Example
Running in the Git projects repository.
$ git log --name-status -M100%\
--diff-filter=R --pretty=format: \
v2.38.0..v2.39.0 |
sed\
-e '/^$/{N;s@^\n$@@}'\
-e 's@\(^\n\{0,1\}\)R[0-9]\{3\}\t@\1@' |
cat -A
fuzz-commit-graph.c^Ioss-fuzz/fuzz-commit-graph.c$
fuzz-pack-headers.c^Ioss-fuzz/fuzz-pack-headers.c$
fuzz-pack-idx.c^Ioss-fuzz/fuzz-pack-idx.c$
you can see that a couple of files were moved to oss-fuzz/
directory, between git versions 2.38.0
and 2.39.0
.