Làm thế nào để thực hiện một git diff trên tập tin di chuyển / đổi tên?


128

Tôi đã chuyển một tập tin bằng cách sử dụng git mv. Bây giờ tôi muốn làm một khác biệt trên tệp mới để so sánh nó với tệp cũ (với tên cũ, bây giờ không tồn tại).

Làm thế nào để tôi làm điều này?


4
Sớm thôi (git 2.9, tháng 6 năm 2016), một đơn giản git diff -- yourRenamedFilesẽ là đủ. Xem câu trả lời của tôi dưới đây
VonC

Câu trả lời:


145

Bạn cần sử dụng -M để cho phép git tự động phát hiện tệp đã di chuyển khi khác. Sử dụng git diffnhư knittl đã đề cập không làm việc cho tôi.

Vì vậy, đơn giản: git diff -Mnên làm điều đó.

Tài liệu cho việc chuyển đổi này là:

-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.

7
Phao cứu sinh! Git diff của tôi bây giờ tốt hơn nhiều. 1) Có an toàn không khi luôn sử dụng tùy chọn này? 2) Tôi có thể thêm tùy chọn này làm hành vi mặc định cho mình ~/.gitconfigkhông?
kevinarpe

5
Lưu ý rằng đổi tên phát hiện chỉ hoạt động khi cả tệp cũ và tệp mới xuất hiện trong bộ sưu tập tệp được xử lý bởi git diff. Chạy git diff -Mtrên một tệp (đã đổi tên) không báo cáo đổi tên.
Leon

1
Điều này không làm việc cho tôi, nhưng git log --follow -- file_after_move.txthoạt động tốt. Nó cho thấy toàn bộ lịch sử, bao gồm cả trước khi di chuyển. Có ý kiến ​​gì không? Tôi đang chạy git version 2.11.0.windows.1.
bouvierr

1
Các -Ctùy chọn cho việc phát hiện bản rất hữu ích và tương tự. Tôi đã sử dụng nó -Mđể xem xét một khác biệt nơi tôi đã tái cấu trúc một tệp thành hai (không có tên nào khớp với bản gốc).
cp.engr

85

Ngoài những gì knittl đã viết , bạn luôn có thể sử dụng:

git diff HEAD:./oldfilename newfilename

trong đó HEAD:./oldfilenamecó nghĩa là oldfilename trong lần xác nhận cuối cùng (trong HEAD), liên quan đến thư mục hiện tại.

Nếu bạn không có đủ git mới, bạn sẽ phải sử dụng thay thế:

git diff HEAD:path/to/oldfilename newfilename

8
Cảm ơn vì điều đó. Bạn cũng có thể chỉ định một cam kết cụ thể thay vì đầu, tức làgit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom

8
Trong trường hợp không rõ ràng, bạn cũng có thể chỉ định tên chi nhánh hoặc bất kỳ tham chiếu nào khác, chẳng hạn như:git diff branch:old/filen.name newfilename
jricher

Mẫu đầu tiên hoạt động với tôi, nếu bạn cdvào thư mục và không thêm --trước commit:pathcặp. Git dường như rất kén chọn với cú pháp ở đây.
dhardy

1
@dhardy <commit-ish>:<pathname>Cú pháp là một định danh đối tượng, một cái gì đó Git-ish; sau khi --Git chỉ mong đợi tên tập tin.
Jakub Narębski

18

Với git 2.9 (tháng 6 năm 2016), bạn sẽ không phải thêm -Mnữa. git diffsử dụng -Mtheo mặc định.

Xem cam kết 5404c11 , cam kết 9501d19 , cam kết a9276a6 , cam kết f07fc9e , cam kết 62df1e6 (25 tháng 2 năm 2016) của Matthieu Moy ( moy) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 5d2a30d , ngày 03 tháng 4 năm 2016)

diff: kích hoạt diff.renamestheo mặc định

Đổi tên phát hiện là một tính năng rất thuận tiện và người dùng mới không cần phải tìm hiểu tài liệu để hưởng lợi từ nó.

Sự phản đối tiềm năng để kích hoạt phát hiện đổi tên là đôi khi nó thất bại, và đôi khi nó chậm. Nhưng phát hiện đổi tên đã được kích hoạt theo mặc định trong một số trường hợp như " git status" và " git merge", vì vậy kích hoạt diff.renameskhông làm thay đổi căn bản tình hình. Khi phát hiện đổi tên không thành công, giờ đây nó không thành công giữa " git diff" và " git status".

Cài đặt này không ảnh hưởng đến các lệnh hệ thống ống nước, do đó các tập lệnh được viết tốt sẽ không bị ảnh hưởng.

Các thử nghiệm mới cho tính năng này có ở đây .


1

git diff -Mkích hoạt phát hiện đổi tên như những người khác đã nói (và như @VonC đã chỉ ra, nó được kích hoạt theo mặc định từ git 2.9). Nhưng nếu bạn có một bộ thay đổi lớn, phát hiện đổi tên không chính xác vẫn có thể bị tắt một lần nữa. Git sẽ hiển thị một cảnh báo như sau, rất dễ bỏ lỡ giữa các khác biệt bạn đang xem:

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.

Trong trường hợp đó, hãy đặt tùy chọn cấu hình theo đề xuất của git, ví dụ:

git config diff.renamelimit 450

và chạy lại lệnh diff của bạn.


0

Vì bất kỳ lý do gì, việc sử dụng HEAD:./oldfilename(hoặc đường dẫn tuyệt đối) không hiệu quả với tôi, nhưng HEAD:oldfilenameđã làm (cảm ơn cmn):

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

HTH


Có lẽ git của bạn quá cũ để hiểu HEAD:./oldfilename?
Jakub Narębski

-4

chỉ đơn giản là chạy git diffmà không có bất kỳ đối số, hoặc git diff -- newfilename. git đủ thông minh để so sánh các tệp / nội dung phù hợp (nghĩa là nội dung gốc trước khi đổi tên với nội dung bị thay đổi sau khi đổi tên)


2
git hoàn toàn không đủ thông minh trong hầu hết các trường hợp. Chỉ cần lấy git mvmột tệp duy nhất và sau đó so sánh trạng thái theo giai đoạn với một nhánh khác giống hệt nhau sẽ tạo ra "mọi thứ đã bị xóa và được tạo lại" khác trừ khi -Mđược sử dụng.
Reinderien
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.