问题
Consider following usecase:
I'm working on my local branch while refactoring has been done on the main branch. Now some files (classes) have been renamed and/or moved to new locations. When merging i get lots and lots of import-errors due to missing classes.
--A--B--C--D--E-- (master)
\ \
F--G--H--I--J (topic)
In A
there are the old names wich i used in F--G--H--I
.
In B--C--D--E
the files are refactored resulting in new file names in E
. This includes chained renames like
B: path/to/File.java
-> C: path/to/BetterName.java
-> D: better/package/BetterName.java
-> E: final/package/FinalName.java
Now merging results in J
with many (compilation) errors due to the missing refactorings on my branch. (Because i still refer to path.to.File
instead of final.package.FinalName
In order to fix the broken build, i need to know the new names for the old classes.
Is there a git command to get all the renames that have been applied to a particular file?
回答1:
Git should find the renames of the files. However, if the file has had 50% or more lines change in that file, it will no longer be considered a rename. You can change this threshold if you wish.
Here is the command to do it:
git log -M --diff-filter=R --stat
It will only show you the renames. If you want to change the threshold to something else other than the default 50%, you can just add the number to the M option:
git log -M90 --diff-filter=R --stat
will only consider a file as renamed if the contents have changed by no more than 10%
UPDATE:
To skip all the intermediate steps, use diff instead. Git will follow the renames for you:
git diff -M --diff-filter=R --name-status ..master | cut -f2-
when you are on your topic branch.
You can then pipe this to make a bunch of sed instructions to adjust your references.
回答2:
I couldn't find a satisfying answer on the web, so i've wrote a (awkward) script to go through the logs one by one (renaming by renaming)
Using the script with above example provides the follwing output:
$ git history path/to/File.java
final/package/FinalName.java
I added the script to my ~.bashrc
and added a the option alias.history=!bash -ic 'git_file_history "$@"' -
to my global git config
#! /bin/sh
### Takes a filename as parameter ($1)
### Echoes all filenames related to $1
function git_file_history() {
loc_var=$1;
old=""
while [ "$loc_var" != "$old" ] && [ "$loc_var" != "" ]
do
old=$loc_var;
#echo $loc_var;
hashes=$(git log --format="%P %H" -1 --follow -- $loc_var);
status=$(git diff --name-status --find-renames $hashes | grep $loc_var);
awks=`echo $status | awk '{print $3}'`
loc_var=$awks;
done
echo "$loc_var";
}
来源:https://stackoverflow.com/questions/10192285/how-to-find-the-new-path-of-a-renamed-file-whose-original-name-is-known