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:
You can always compare 2 files in 2 different commits:
git diff commit1:file1_path commit2:file2_path
回答2:
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.
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.