Git Tip of the Day – detect moved files
Let’s prepare a commit where we rename a file:
$ mv foo bar $ git add -A $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: foo -> bar # $ git commit -m 'improve naming' [master 80d5850] improve naming 1 files changed, 0 insertions(+), 0 deletions(-) rename foo => bar (100%)
Now let’s show the default behavior of git:
$ git show commit 80d5850fa16ecc783fa86a1d474c4324ec9f4c2d Author: Kamil Páral Date: Wed Aug 3 13:49:01 2011 +0200 improve naming diff --git a/bar b/bar new file mode 100644 index 0000000..4e4b354 --- /dev/null +++ b/bar @@ -0,0 +1,2 @@ +this is a +sample file diff --git a/foo b/foo deleted file mode 100644 index 4e4b354..0000000 --- a/foo +++ /dev/null @@ -1,2 +0,0 @@ -this is a -sample file
You will get the same output with git diff, git format-patch or git log -p. Basically the whole file is removed and added back again in another location. This is not great, because if the file has 1000 lines, then it will really clutter your view. There is a better approach:
$ git show -M commit 80d5850fa16ecc783fa86a1d474c4324ec9f4c2d Author: Kamil Páral Date: Wed Aug 3 13:49:01 2011 +0200 improve naming diff --git a/foo b/bar similarity index 100% rename from foo rename to bar
We shortened the output to 4 simple lines. You see that similarity index is 100%, that means the files are the same, just at different locations (i.e. with different names). The similarity index can be lower, that means git can detect even files that changed a little during the move. The threshold can be set as an argument to the -M option.
If you use this option for patch creation, you may get a much shorter patches that are much more readable. The disadvantage? They are no longer “standard” patches that can be applied with patch command, you must use git to do that.