git diff tập tin được đổi tên


105

Tôi có một tập tin a.txt.

cat a.txt
> hello

Nội dung của a.txtlà "xin chào".

Tôi thực hiện một cam kết.

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

Sau đó tôi chuyển a.txtđến một testdir.

mkdir test
mv a.txt test

Sau đó tôi thực hiện cam kết thứ hai của mình.

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

Cuối cùng, tôi chỉnh sửa a.txtđể nói "tạm biệt" thay thế.

cat a.txt
> goodbye

Tôi thực hiện cam kết cuối cùng của mình.

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

Bây giờ đây là câu hỏi của tôi:

Làm cách nào để tôi khác biệt nội dung a.txtgiữa cam kết cuối cùng và cam kết đầu tiên?

Tôi đã thử:, git diff HEAD^^..HEAD -M a.txtnhưng điều đó không hiệu quả. git log --follow a.txtphát hiện đúng cách đổi tên, nhưng tôi không thể tìm thấy tên tương đương cho git diff. Có một cái?


Tôi cho rằng nó sẽ giống như vậy nếu bạn thực hiện 'kiểm tra git mv a.txt'? IE bạn chỉ cần đổi tên tệp thay vì chuyển nó vào một thư mục con.
Max Waterman

Câu trả lời:


107

Vấn đề với sự khác biệt giữa HEAD^^HEADlà bạn có một a.txttrong cả hai cam kết, vì vậy chỉ cần xem xét hai cam kết đó (đó là những gì khác biệt), không có đổi tên, có một bản sao và một sự thay đổi.

Để phát hiện các bản sao, bạn có thể sử dụng -C:

git diff -C HEAD^^ HEAD

Kết quả:

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

Ngẫu nhiên, nếu bạn hạn chế sự khác biệt của mình chỉ ở một đường dẫn (như cách bạn làm ở đây, git diff HEAD^^ HEAD a.txtbạn sẽ không bao giờ nhìn thấy các tên hoặc bản sao vì bạn đã loại trừ mọi thứ ra khỏi một đường dẫn duy nhất và đổi tên hoặc bản sao - theo định nghĩa - liên quan đến hai các lối đi.


2
Giả sử cam kết chứa nhiều thay đổi tệp. Làm cách nào để thu hẹp nó thành một khác biệt của một tệp?
Ken Hirakawa 14/10/11

3
@KenHirakawa sử dụng -- <old-path> <new-path>... xem câu trả lời của tôi.
Nolan Amy

Trong trường hợp của tôi, tôi muốn hiển thị chi tiết của một cam kết nơi tệp đã được đổi tên, nhưng nó chỉ cho tôi thấy rằng một tệp đã bị xóa và một tệp đã được thêm vào ... Tôi đã chạy git show -C [commit]và nó nhận dạng được tên tệp và hiển thị cho tôi khác nhau giữa các tệp. Hoàn hảo.
Jason

83

Để thay đổi tên của một tệp cụ thể, hãy sử dụng -M -- <old-path> <new-path>( -Ccũng hoạt động).

Vì vậy, nếu bạn vừa đổi tên thay đổi tệp trong lần cam kết cuối cùng, bạn có thể thấy các thay đổi với:

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

Điều này tạo ra:

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.txtcác dòng được thêm vào để giúp git phát hiện việc đổi tên)


Nếu git không phát hiện ra việc đổi tên, bạn có thể chỉ định ngưỡng tương tự thấp với -M[=n], giả sử 1%:

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

Từ các tài liệu git diff :

-M [<n>] --tìm tên [= <n>]

Phát hiện đổi tên. Nếu nđược chỉ định, nó là một ngưỡng về chỉ số tương tự (tức là số lượng thêm / xóa so với kích thước của tệp). Ví dụ: -M90%có nghĩa là Git nên coi một cặp xóa / thêm là một sự đổi tên nếu hơn 90% tệp không thay đổi. Nếu không có %dấu, số sẽ được đọc dưới dạng phân số, với dấu thập phân trước nó. Tức là, -M5trở thành 0,5, và do đó giống như -M50%. Tương tự, -M05cũng giống như -M5%. Để hạn chế phát hiện đối với các tên chính xác, hãy sử dụng -M100%. Chỉ số tương tự mặc định là 50%.


... Tất nhiên, cũng hoạt động khi thay đổi và đổi tên nằm trong các cam kết riêng biệt như trong ví dụ ban đầu:git diff HEAD^^ HEAD -M -- a.txt test/a.txt
Nolan Amy

1
Chỉ khi nội dung của các tệp đủ gần để khác biệt mới đưa ra chỉ mục tương tự. Sử dụng cả hai tùy chọn (-M và -C) đang hiển thị sự khác biệt đến / dev / null an from / dev / null trong một tệp đã được đổi tên và đã thay đổi hoàn toàn (bao gồm cả thụt lề khôn ngoan), nó thậm chí không bắt được nó khi bỏ qua khoảng trắng.
DavidG

37

Bạn cũng có thể làm:

git diff rev1:file1 rev2:file2

mà, ví dụ của bạn, sẽ là

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

Lưu ý rõ ràng ./- định dạng này giả sử các đường dẫn liên quan đến gốc của repo. (Nếu bạn đang ở thư mục gốc của repo, tất nhiên bạn có thể bỏ qua điều đó.)

Điều này hoàn toàn không phụ thuộc vào phát hiện đổi tên, vì người dùng đang nói rõ ràng chính xác những gì cần so sánh. (Do đó, nó cũng có ích trong một số trường hợp khác, chẳng hạn như so sánh tệp giữa các nhánh svn khác nhau trong môi trường git-svn.)


1
Oooh, điều này thật tuyệt!
Nolan Amy

Đối với việc đổi tên với các thay đổi tệp bổ sung được đưa vào thông qua hợp nhất, đây là câu trả lời duy nhất phù hợp với tôi. Cảm ơn!
Lane Rettig

1

Nếu cam kết đổi tên của bạn được tổ chức nhưng chưa được cam kết, bạn có thể sử dụng:

git diff --cached -M -- file.txt renamed_file.txt
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.