Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git diff renamed file

Tags:

git

rename

diff

People also ask

How does git detect renamed files?

Git keeps track of changes to files in the working directory of a repository by their name. When you move or rename a file, Git doesn't see that a file was moved; it sees that there's a file with a new filename, and the file with the old filename was deleted (even if the contents remain the same).

What does git diff filename do?

The git diff HEAD [filename] command allows you to compare the file version in your working directory with the file version last committed in your remote repository. The HEAD in the git command refers to the remote repository.

What happens when you rename a file in git?

It does not rename or move the actual file, but rather deletes the existing file and creates a new file with a new name or in another folder.

How do I see changes in git diff?

You can run the git diff HEAD command to compare the both staged and unstaged changes with your last commit. You can also run the git diff <branch_name1> <branch_name2> command to compare the changes from the first branch with changes from the second branch.


The issue with the difference between HEAD^^ and HEAD is that you have an a.txt in both commits, so just considering those two commits (which is what diff does), there is no rename, there is a copy and a change.

To detect copies, you can use -C:

git diff -C HEAD^^ HEAD

Result:

index ce01362..dd7e1c6 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1 @@
-hello
+goodbye
diff --git a/a.txt b/test/a.txt
similarity index 100%
copy from a.txt
copy to test/a.txt

Incidentally, if you restrict your diff to just one path (as you do in git diff HEAD^^ HEAD a.txt you aren't ever going to see the renames or copies because you've excluded the everything apart from a single path and renames or copies - by definition - involve two paths.


To diff across a rename of a specific file, use -M -- <old-path> <new-path> (-C also works).

So if you both renamed and changed a file in the last commit, you can see the changes with:

git diff HEAD^ HEAD -M -- a.txt test/a.txt

This produces:

diff --git a/a.txt b/test/a.txt
similarity index 55%
rename from a.txt
rename to test/a.txt
index 3f855b5..949dd15 100644
--- a/a.txt
+++ b/test/a.txt
@@ -1,3 +1,3 @@
 // a.txt

-hello
+goodbye

(// a.txt lines added to help git detect the rename)


If git isn't detecting the rename, you can specify a low similarity threshold with -M[=n], say 1%:

git diff HEAD^ HEAD -M01 -- a.txt test/a.txt

From the git diff docs:

-M[<n>] --find-renames[=<n>]

Detect renames. If n is specified, it is a threshold on the similarity index (i.e. amount of addition/deletions compared to the file's size). For example, -M90% means Git should consider a delete/add pair to be a rename if more than 90% of the file hasn't changed. Without a % sign, the number is to be read as a fraction, with a decimal point before it. I.e., -M5 becomes 0.5, and is thus the same as -M50%. Similarly, -M05 is the same as -M5%. To limit detection to exact renames, use -M100%. The default similarity index is 50%.


You can also do:

git diff rev1:file1 rev2:file2

which, for your example, would be

git diff HEAD^^:./a.txt HEAD:./test/a.txt

Note the explicit ./ -- this format otherwise assumes the paths to be relative to the root of the repo. (If you're in the root of the repo, you can of course omit that.)

This doesn't depend on the rename detection at all, as the user is explicitly stating exactly what to compare. (Therefore, it also comes in handy in some other circumstances, such as comparing files between different svn branches in a git-svn environment.)


If your rename commit is staged but not committed yet, you can use:

git diff --cached -M -- file.txt renamed_file.txt