Zmieniono nazwę pliku git diff

105

Mam plik a.txt.

cat a.txt
> hello

Treść a.txtto „cześć”.

Zobowiązuję się.

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

Następnie przenoszę a.txtsię do testreż.

mkdir test
mv a.txt test

Następnie wykonuję drugie zobowiązanie.

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

Na koniec edytuję, a.txtaby zamiast tego powiedzieć „do widzenia”.

cat a.txt
> goodbye

Robię ostatnie zobowiązanie.

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

Oto moje pytanie:

Jak odróżnić zawartość a.txtmiędzy moim ostatnim zatwierdzeniem a pierwszym zatwierdzeniem?

Próbowałem: git diff HEAD^^..HEAD -M a.txtale to nie zadziałało. git log --follow a.txtpoprawnie wykrywa zmianę nazwy, ale nie mogę znaleźć odpowiednika dla git diff. Czy jest jeden?

Ken Hirakawa
źródło
Przypuszczam, że byłoby tak samo, gdybyś zrobił „test git mv a.txt”? IE właśnie zmieniłeś nazwę pliku, zamiast przenosić go do podkatalogu.
Max Waterman

Odpowiedzi:

107

Problem z różnicą między HEAD^^i HEADpolega na tym, że masz a.txtoba zatwierdzenia, więc biorąc pod uwagę te dwa zatwierdzenia (co robi diff), nie ma zmiany nazwy, jest kopia i zmiana.

Aby wykryć kopie, możesz użyć -C:

git diff -C HEAD^^ HEAD

Wynik:

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

Nawiasem mówiąc, jeśli ograniczysz swoją różnicę tylko do jednej ścieżki (tak jak w przypadku git diff HEAD^^ HEAD a.txt, nie zobaczysz zmian nazw ani kopii, ponieważ wykluczyłeś wszystko oprócz pojedynczej ścieżki, a zmiany nazw lub kopii - z definicji - obejmują dwa ścieżki.

CB Bailey
źródło
2
Powiedzmy, że zatwierdzenie zawierało wiele zmian w pliku. Jak zawęziłbym to do porównania pojedynczego pliku?
Ken Hirakawa
3
@KenHirakawa użyj -- <old-path> <new-path>... zobacz moją odpowiedź.
Nolan Amy,
W moim przypadku chciałem pokazać szczegóły zatwierdzenia, w którym zmieniono nazwę pliku, ale pokazywało mi tylko, że plik został usunięty, a plik został dodany ... Uruchomiłem git show -C [commit]i rozpoznałem zmianę nazwy pliku i pokazał mi różnica między plikami. Idealny.
Jason
83

Aby porównać zmianę nazwy określonego pliku, użyj -M -- <old-path> <new-path>( -Crównież działa).

Więc jeśli zarówno zmieniliście nazwę, jak i zmieniliście plik w ostatnim zatwierdzeniu, możesz zobaczyć zmiany za pomocą:

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

To daje:

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.txtdodano wiersze, aby pomóc gitowi wykryć zmianę nazwy)


Jeśli git nie wykrywa zmiany nazwy, możesz określić niski próg podobieństwa -M[=n], powiedzmy 1%:

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

Z dokumentacji git diff :

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

Wykryj zmiany nazw. Jeśli njest określony, jest to próg indeksu podobieństwa (tj. Ilość dodań / usunięć w porównaniu z rozmiarem pliku). Na przykład -M90%oznacza , że Git powinien uznać parę usuń / dodaj za zmianę nazwy, jeśli więcej niż 90% pliku nie uległo zmianie. %Liczbę bez znaku należy czytać jako ułamek, przed którym znajduje się przecinek dziesiętny. To -M5znaczy , staje się 0,5, a zatem jest tym samym co -M50%. Podobnie -M05jest z tym samym -M5%. Aby ograniczyć wykrywanie do dokładnych zmian nazw, użyj -M100%. Domyślny wskaźnik podobieństwa to 50%.

Nolan Amy
źródło
... Oczywiście działa również, gdy zmiana i zmiana nazwy są w osobnych zatwierdzeniach, jak w oryginalnym przykładzie:git diff HEAD^^ HEAD -M -- a.txt test/a.txt
Nolan Amy
1
Tylko wtedy, gdy zawartość plików jest wystarczająco blisko, aby diff wymyślił indeks podobieństwa. Użycie obu opcji (-M i -C) pokazuje różnicę do / dev / null i z / dev / null w pliku, którego nazwa została zmieniona i całkowicie się zmieniła (w tym pod względem wcięć), nie przechwytuje go nawet podczas ignorowania Biała przestrzeń.
DavidG,
37

Możesz też:

git diff rev1:file1 rev2:file2

co, na przykład, byłoby

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

Zwróć uwagę na jawne ./- w przeciwnym razie ten format zakłada, że ​​ścieżki są względne w stosunku do katalogu głównego repozytorium. (Jeśli jesteś w katalogu głównym repozytorium, możesz oczywiście to pominąć).

W ogóle nie zależy to od wykrywania zmiany nazwy, ponieważ użytkownik wyraźnie określa, co dokładnie porównać. (Dlatego przydaje się również w innych okolicznościach, takich jak porównywanie plików między różnymi gałęziami svn w środowisku git-svn).

benkc
źródło
1
Oooh, to jest miłe!
Nolan Amy
W przypadku zmiany nazwy z dodatkowymi zmianami plików wprowadzonymi przez scalenie jest to jedyna odpowiedź, która działała dla mnie. Dzięki!
Lane Rettig
1

Jeśli zmiana nazwy jest przygotowana, ale jeszcze nie została zatwierdzona, możesz użyć:

git diff --cached -M -- file.txt renamed_file.txt
Mr-IDE
źródło