I have a repository where a number of files have been renamed from .html to .php and further edited in a number of commits since my last pull. Using git diff
to shows all the html
contents removed and all the php
content added. Is there a neat way to have git diff
detect the renames (something like git log --follow
does), or directly compare different filenames across different commits (something like the solution in Git: How to diff two different files in different branches? , but for commits)?

- 1
- 1

- 373
- 3
- 6
-
Did you use `git mv` when changing the files originally? – dave Mar 27 '17 at 08:55
-
9git diff commit1:file1_path commit2:file2_path – ElpieKay Mar 27 '17 at 09:29
-
This does the trick, thanks, please convert to an answer so I can accept. (It is at the individual file level, unfortunately, but I can do what needs to be done with it for now.) – Steve Kroon Mar 27 '17 at 10:04
-
@dave: not actually sure - someone else moved the files. – Steve Kroon Mar 27 '17 at 10:04
-
1@dave: that does not actually matter. Git normally *detects* renames (rather than recording them) by doing tree comparisons. That, however, requires that you diff two complete trees, not two specific files within the tree. – torek Mar 27 '17 at 15:19
2 Answers
You can always compare 2 files in 2 different commits:
git diff commit1:file1_path commit2:file2_path

- 2,356
- 28
- 39
-
1Answers with just code get flagged as 'Low Quality Posts', try explaining your answer a little to avoid it being deleted. – piman314 Mar 08 '18 at 19:42
-
@ElpieKay provided this answer as a comment on my question a year back - tagging him here to provide it as an answer. If I don't get a response from him in a week, Eugene, ping me here and I'll accept your answer. – Steve Kroon Mar 27 '18 at 23:05
-
@SteveKroon It would be already 3 weeks tomorrow since the time of your comment. I appreciate ElpieKay input, he really added good commented, but looks like he is not available. If you like, feel free to accept my answer/ – Eugene Kaurov Apr 16 '18 at 18:17
As said previously, the format needed is:
$ git diff commit1:file1_path commit2:file2_path
But there are a couple gotchas:
XXX$ git diff file1_path commit2:file2_path
This will not work, even if file1_path is in HEAD
; if you want to specify a commit for one file you must specify it for both. This will attempt to interpret "commit2:file2_path" as a file path with the first directory it steps into being, e.g., HEAD^:foo/
. This will rarely exist so it generally gives an informative error message. (Note: @philh says that git diff commit1:file1_path file2_path
works fine, but I haven't confirmed that myself.)
file1_path
format: The paths given will be treated as relative to the repository's root. Absolute paths are not permitted, and relative paths must be explicit. For a concrete example; say your directory structure looks like the below, and your working directory is ~/repo/proj
:
~/repo
.git
proj
tests
foo
bar.sh
utils
baz
quux.sh
If you are trying to compare HEAD^:(...)/bar.sh
to HEAD:(...)/quux.sh
, the only permissible paths for bar.sh
are:
proj/tests/foo/bar.sh
./tests/foo/bar.sh
The explicit relative path with ./
works, but the more common implicit path tests/foo/bar.sh
will not work. That version will sometimes fail silently - I think this is based on the format used in the other arguments but I'm not sure. Absolute paths will also not work; ~/repo/proj/tests/foo/bar.sh
and /home/username/repo/proj/tests/foo/bar.sh
will fail. AFAICT that will never fail silently.

- 392
- 3
- 13
-
2"if you want to specify a commit for one file you must specify it for both" Not entirely - it seems that `git diff path1 foo:path2` doesn't work, but `git diff foo:path2 path1` does. – philh Aug 03 '20 at 11:11
-