Bagaimana cara melakukan git diff pada file yang dipindahkan / diubah namanya?

128

Saya memindahkan file menggunakan git mv. Sekarang saya ingin melakukan diff pada file baru untuk membandingkannya dengan file lama (dengan yang lama, sekarang tidak ada nama).

Bagaimana saya melakukan ini?

dr jerry
sumber
4
Segera (git 2.9, Juni 2016), sederhana git diff -- yourRenamedFileakan cukup. Lihat jawaban saya di bawah ini
VonC

Jawaban:

145

Anda perlu menggunakan -M untuk membiarkan git mendeteksi secara otomatis file yang dipindahkan saat melakukan diffing. Menggunakan sama git diffseperti knittl yang disebutkan tidak bekerja untuk saya.

Jadi sederhananya: git diff -Mharus melakukannya.

Dokumentasi untuk sakelar ini adalah:

-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.
Zitrax
sumber
7
Penyelamat! Perbedaan git saya jauh lebih baik sekarang. 1) Apakah aman untuk selalu menggunakan opsi ini? 2) Dapatkah saya menambahkan opsi ini sebagai perilaku default ke saya ~/.gitconfig?
kevinarpe
5
Perhatikan bahwa deteksi nama hanya berfungsi bila file lama dan baru muncul di kumpulan file yang diproses oleh git diff. Berjalan git diff -Mpada satu file (diganti nama) tidak melaporkan penggantian nama.
Leon
1
Ini tidak berhasil untuk saya, tetapi git log --follow -- file_after_move.txtbekerja dengan baik. Ini menunjukkan seluruh sejarah, termasuk sebelum pindah. Ada ide? Saya sedang berlari git version 2.11.0.windows.1.
bouvierr
1
The -Cpilihan untuk mendeteksi salinan berguna dan serupa. Saya menggunakannya dengan -Muntuk melihat diff di mana saya telah refactored satu file menjadi dua (tanpa nama yang cocok dengan aslinya).
cp.engr
85

Selain apa yang ditulis knittl , Anda selalu dapat menggunakan:

git diff HEAD:./oldfilename newfilename

di mana HEAD:./oldfilenameberarti oldfilename di commit terakhir (di HEAD), relatif terhadap direktori saat ini.

Jika Anda tidak memiliki git yang cukup baru, Anda harus menggunakannya:

git diff HEAD:path/to/oldfilename newfilename
Jakub Narębski
sumber
8
Terima kasih untuk ini. Anda juga dapat menentukan komit tertentu alih-alih kepala, yaitugit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom
8
Jika tidak jelas, Anda juga dapat menentukan nama cabang atau referensi lainnya, seperti:git diff branch:old/filen.name newfilename
jricher
Bentuk pertama berfungsi untuk saya, jika Anda cdke direktori dan tidak menambahkan --sebelum commit:pathpasangan. Git tampaknya sangat pemilih dengan sintaksis di sini.
dhardy
1
@ Hardy <commit-ish>:<pathname>Sintaks adalah pengidentifikasi objek, sesuatu Git-ish; setelah --Git hanya mengharapkan nama file.
Jakub Narębski
18

Dengan git 2.9 (Juni 2016), Anda tidak perlu menambahkan -Mlagi. git diffgunakan -Msecara default.

Lihat komit 5404c11 , komit 9501d19 , komit a9276a6 , komit f07fc9e , komit 62df1e6 (25 Feb 2016) oleh Matthieu Moy ( moy) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit 5d2a30d , 03 Apr 2016)

diff: aktifkan diff.renamessecara default

Ganti nama deteksi adalah fitur yang sangat nyaman, dan pengguna baru tidak harus menggali dokumentasi untuk mendapat manfaat darinya.

Keberatan potensial untuk mengaktifkan deteksi ganti nama adalah bahwa kadang-kadang gagal, dan kadang-kadang lambat. Tetapi mengubah nama deteksi sudah diaktifkan secara default dalam beberapa kasus seperti " git status" dan " git merge", jadi mengaktifkannya diff.renamestidak secara mendasar mengubah situasi. Saat deteksi ganti nama gagal, sekarang gagal secara konsisten antara " git diff" dan " git status".

Pengaturan ini tidak memengaruhi perintah pipa ledeng, karenanya skrip yang ditulis dengan baik tidak akan terpengaruh.

Tes baru untuk fitur ini ada di sini .

VONC
sumber
1

git diff -Mmengaktifkan rename detection seperti yang dikatakan orang lain (dan seperti yang ditunjukkan @VonC, ini diaktifkan secara default dari git 2.9). Tetapi jika Anda memiliki perubahan besar, deteksi nama yang tidak tepat masih dapat dimatikan lagi. Git akan menampilkan peringatan seperti berikut, yang mudah terlewatkan di tengah-tengah perbedaan yang Anda lihat:

warning: inexact rename detection was skipped due to too many files.
warning: you may want to set your diff.renameLimit variable to at least 450 and retry the command.

Dalam hal ini, setel opsi konfigurasi seperti yang disarankan oleh git, misalnya

git config diff.renamelimit 450

dan jalankan kembali perintah diff Anda.

mindriot
sumber
0

Untuk alasan apa pun menggunakan HEAD:./oldfilename(atau jalur absolut) tidak berfungsi untuk saya, tetapi HEAD:oldfilenameberhasil (terima kasih cmn):

git diff HEAD:oldfilename newfilename
git diff 2a80f45:oldfilename f65f3b3:newfilename

HTH

Oli Studholme
sumber
Mungkin git Anda terlalu tua untuk mengerti HEAD:./oldfilename?
Jakub Narębski
-4

jalankan git difftanpa argumen, atau git diff -- newfilename. git cukup pintar untuk membandingkan file / konten yang tepat (yaitu konten asli sebelum mengganti nama dengan konten yang diubah setelah mengganti nama)

rajutan
sumber
2
git sama sekali tidak cukup pintar dalam banyak kasus. Cukup git mvdengan memasukkan satu file dan kemudian membandingkan status yang dipentaskan dengan cabang lain yang identik akan menghasilkan perbedaan "semuanya telah dihapus dan diciptakan kembali" kecuali jika -Mdigunakan.
Reinderien