Git diff переименованный файл

У меня есть файл a.txt.

cat a.txt
> hello

Содержимое a.txt - "привет".

Я делаю фиксацию.

git add a.txt
git commit -m "first commit"

Затем переместите a.txt в директорию test.

mkdir test
mv a.txt test

Затем я делаю свою вторую фиксацию.

git add -A
git commit -m "second commit"

Наконец, я редактирую a.txt, чтобы сказать "до свидания".

cat a.txt
> goodbye

Я делаю последнее коммит.

git add a.txt
git commit -m "final commit"

Теперь вот мой вопрос:

Как мне различать содержимое a.txt между моим последним фиксатором и моим первым фиксацией?

Я пробовал:   git diff HEAD^^..HEAD -M a.txt, но это не сработало. git log --follow a.txt правильно определяет переименование, но я не могу найти эквивалент для git diff. Есть один?

Ответ 1

Проблема с разницей между HEAD^^ и HEAD заключается в том, что у вас есть a.txt в обеих коммитах, поэтому просто рассматривая эти две коммиты (это то, что делает diff), нет переименования, существует копия и изменение.

Чтобы обнаружить копии, вы можете использовать -C:

git diff -C HEAD^^ HEAD

Результат:

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

Кстати, если вы ограничиваете свой diff только одним путем (как вы это делаете в git diff HEAD^^ HEAD a.txt, вы никогда не увидите переименование или копии, потому что вы исключили все отдельно от одного пути и переименовали или копировали - по определению - задействовать два пути.

Ответ 2

Чтобы изменить переименование определенного файла, используйте -M -- <old-path> <new-path> (-C).

Итак, если вы оба переименовали и изменили файл в последнем коммите, вы можете увидеть изменения с помощью:

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

Это дает:

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 строки добавлены, чтобы помочь git обнаружить переименование)


Если git не обнаруживает переименование,, вы можете указать порог с низким уровнем подобия с -M[=n], скажем, 1%:

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

Из git diff docs:

-M [< п > ] --find-переименовывает [= < п > ]

Обнаружение переименований. Если указано n, это пороговое значение для индекса подобия (то есть количество сложения/удаления по сравнению с размером файла). Например, -M90% означает git should рассмотрите пару delete/add как переименование, если более 90% файла не изменилось. Без знака % число должно быть считано как с точностью до десятичной точки. I.e., -M5 становится 0,5, и таким образом, совпадает с -M50%. Аналогично, -M05 совпадает с -M5%. к ограничить обнаружение для точных переименований, используйте -M100%. По умолчанию сходство индекс равен 50%.

Ответ 3

Вы также можете сделать:

git diff rev1:file1 rev2:file2

который для вашего примера будет

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

Обратите внимание на явный ./ - этот формат в противном случае предполагает, что пути будут относиться к корню репо. (Если вы находитесь в корне репо, вы можете, конечно, опустить это.)

Это не зависит от обнаружения переименования вообще, так как пользователь явно указывает, что сравнивать. (Поэтому он также пригодится в некоторых других обстоятельствах, таких как сравнение файлов между различными ветвями svn в среде git -svn.)