'git status' hiển thị các tệp đã thay đổi, nhưng 'git diff' thì không


181

Tôi đã xem xét tất cả các câu hỏi tương tự. Tuy nhiên, tôi đã kiểm tra lại và điều gì đó kỳ lạ chắc chắn đang xảy ra.

Trên một máy chủ (Solaris với Git 1.8.1) Tôi đã sao chép kho lưu trữ Git sau đó sao chép thư mục .git vào các tệp trực tiếp hiện có của tôi. Điều này hoạt động hoàn hảo, tôi có thể chạy

git status

sau đó

git diff [filename]

để kiểm tra bất kỳ tập tin nào khác nhau

Trên một máy chủ khác (Solaris với Git 1.7.6) Tuy nhiên, tôi đang làm chính xác như vậy

git diff [filename]

không hiển thị gì, ngay cả khi nội dung của tệp chắc chắn khác nhau. Tôi cũng đã thử nghiệm thêm một tệp mới, cam kết nó và sau đó chỉnh sửa. Vấn đề tương tự, git statushiển thị các tập tin như đã thay đổi, nhưng git diffkhông hiển thị gì. Nếu tôi tải xuống tệp đã thay đổi và chạy khác cục bộ thì tôi nhận được đầu ra khác.


9
Có phải trong chỉ mục của bạn? Nếu vậy, bạn có thể xem khác với git diff --cached.
jeremyharris

2
git diff --cachedchỉ cho tôi đầu ra trống là tốt.
Oliver P

git logcũng không cho đầu ra.
Oliver P

Giả sử rằng thực sự có một lỗi, bạn sẽ có thể tạo một ví dụ tối thiểu. Cố gắng tái tạo nó và chia sẻ mẫu.
mheinzerling

1) Chế độ tập tin đã được thay đổi? Tìm core.fileModetùy chọn ở đây 2) Ngoài ra, tôi đang gặp vấn đề tương tự với cấu hình Console2 (tôi có nó dưới git) khi Console2 thực sự đang chạy. Có thể một loại khóa tệp làm cho git điều điều mà tệp đã thay đổi.
madhead

Câu trả lời:



63

Có một vài lý do tại sao git statuscó thể cho thấy một sự khác biệt nhưng git diffcó thể không.

  • Chế độ (bit cho phép) của tệp đã thay đổi-- ví dụ: từ 777 thành 700.

  • Kiểu nguồn cấp dữ liệu dòng đã thay đổi từ CRLF (DOS) thành LF (UNIX)

Cách dễ nhất để tìm hiểu những gì đã xảy ra là chạy git format-patch HEAD^và xem bản vá được tạo ra nói gì.


11
nếu thay đổi tập tin quyền áp dụng: git config core.filemode false để bỏ qua quyền của tập tin
jruzafa

Làm thế nào bạn phát hiện ra rằng thay đổi nguồn cấp dữ liệu từ CRLF sang LF là một trong những tình huống trong đó trạng thái git sẽ hiển thị sự khác biệt và git diff sẽ không?
Alex Spurling

Có đồng nghiệp sử dụng Windows sẽ giúp bạn tìm ra tất cả những điều thú vị về kết thúc dòng. Tôi nghĩ có thể là trường hợp "git diff" hiển thị sự thay đổi từ CRLF sang LF, tuy nhiên-- nó có thể phụ thuộc vào cấu hình của bạn. Tôi đã không làm việc với Windows trong một thời gian, vì vậy tôi không biết mặc định bây giờ là như thế nào.
cmccabe

59

Đối với tôi, nó có một cái gì đó để làm với quyền truy cập tập tin. Ai đó có Mac / Linux trong dự án của tôi dường như cam kết một số tệp có quyền không mặc định mà máy khách Windows git của tôi không thể sao chép. Giải pháp cho tôi là bảo git bỏ qua quyền truy cập tệp:

git config core.fileMode false

Thông tin chi tiết khác: Làm cách nào để Git bỏ qua thay đổi chế độ tệp (chmod)?


Điều này đã giải quyết một vấn đề tôi gặp phải với một loạt các tệp, mặc dù tôi nghĩ rằng đó là với tệp được tạo / sửa đổi thời gian thay thế.
Derek

Điều này đã giải quyết nó cho tôi. Giá trị fileMode xuất hiện mặc định là true trên các tập Mac / Linux và false trên các tập Windows. Tôi đã chuyển một dự án từ Mac sang Windows và nó cần phải được chuyển thành false.
geekinit

1
Điều này cũng hữu ích nếu bạn đang chạy VSCode bằng cách sử dụng bộ chứa Docker gắn thư mục của bạn trên Windows 10. Ở bên ngoài bộ chứa, kiểm tra trạng thái git, cho thấy chính xác rằng bạn không thay đổi bất kỳ tệp nào. Nhưng nếu bạn kiểm tra trạng thái git bên trong container, nó sẽ hiển thị các tệp được thay đổi. Chạy lệnh trên bên trong container đã khắc phục sự cố của tôi.
Frederick Ollinger

39

Tôi đã gặp sự cố khi hàng trăm kết thúc dòng đã được sửa đổi bởi một số chương trình và git diffliệt kê tất cả các tệp nguồn đã được thay đổi. Sau khi sửa các kết thúc dòng, git statusvẫn liệt kê các tệp như đã sửa đổi.

Tôi đã có thể khắc phục vấn đề này bằng cách thêm tất cả các tệp vào chỉ mục và sau đó đặt lại chỉ mục.

git add -A
git reset

core.filemode được đặt thành false.


Cảm ơn bạn! Làm việc như người ở!
Starwave

1
Tôi giải quyết với git add --renormalize ., xem câu trả lời của tôi dưới đây.
Stefano M

17

Tôi nghi ngờ có gì đó không đúng với cài đặt Git hoặc kho lưu trữ của bạn.

Hãy thử chạy:

GIT_TRACE=2 git <command>

Xem nếu bạn nhận được bất cứ điều gì hữu ích. Nếu điều đó không có ích, chỉ cần sử dụng strace và xem điều gì đang xảy ra:

strace git <command>

6
@towi: Vì đây là giá trị tiền thưởng cho bạn, tôi rất muốn xem những gì bạn đã học về lý do cho những thất bại tương tự của bạn.
cfi

5
Trong trường hợp của tôi, tôi đã thêm -Fcờ vào LESSbiến env để báo ra ít thoát hơn nếu có ít hơn một màn hình hiển thị đầy đủ thông tin. Vì git sử dụng ít hơn như một máy nhắn tin, và tôi có một khác biệt nhỏ, không có gì được hiển thị. Hoặc tôi phải thêm -Xvào LESSenv để hiển thị nội dung trên màn hình ngay cả sau khi thoát ít hơn hoặc chỉ cần loại bỏ -F. GIT_TRACEcho thấy rằng lessđã được thực hiện mà nhắc nhở tôi rằng tôi đã thay đổi LESSbiến gần đây. Lý do tương tự trong câu trả lời của @ RCwxok, nhưng muốn bình luận về cách GIT_TRACEgiúp đỡ.
Raghu Dodda

Câu trả lời này cung cấp cho tôi gợi ý của "pager" và dẫn tôi đến giải pháp của khung cảnh core.pagertrong .gitconfig, mà hoạt động hoàn hảo cho tôi.
ytu

10

Tôi đã có một vấn đề tương tự: git diffsẽ cho thấy sự khác biệt, nhưng git diff <filename>sẽ không. Hóa ra tôi đặt LESSthành một chuỗi bao gồm -F( --quit-if-one-screen). Loại bỏ cờ đó đã giải quyết vấn đề.


1
Thay vì loại bỏ -F, thêm -Xcũng có thể hoạt động, xem câu trả lời của tôi dưới đây cho một trường hợp tương tự.
avivr

Cảm ơn vì điều này! Đã làm tôi phát điên.
hackel

8

Như đã lưu ý trong một câu trả lời trước , tình huống này có thể phát sinh do các vấn đề kết thúc dòng (CR / LF so với LF). Tôi đã giải quyết vấn đề này (theo phiên bản Git 2.22.0) bằng lệnh này:

git add --renormalize .

Theo hướng dẫn:

       --renormalize
           Apply the "clean" process freshly to all tracked files to
           forcibly add them again to the index. This is useful after
           changing core.autocrlf configuration or the text attribute in
           order to correct files added with wrong CRLF/LF line endings.
           This option implies -u.

5

Câu trả lời ngắn

Đang chạy git add đôi khi giúp.

Thí dụ

Trạng thái Git đang hiển thị các tệp đã thay đổi và git diff không hiển thị gì cả ...

> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   package.json

no changes added to commit (use "git add" and/or "git commit -a")
> git diff
> 

... Chạy git add giải quyết sự không nhất quán.

> git add
> git status
On branch master
nothing to commit, working directory clean
> 

2
Điều này nghe với tôi như 'chiến đấu với các triệu chứng' thay vì 'chữa khỏi bệnh' ...;)
einjohn

@einjohn Bạn nghĩ bệnh gì trong trường hợp này?
Shaun Luttin

1
Bệnh có thể là một số điều. Như đã đề cập bởi những người khác, nó có thể là một vấn đề quyền hoặc một cái gì đó với kết thúc dòng. Nó cũng có thể đã được dàn dựng thay đổi. Tuy nhiên, khả năng cuối cùng này không phù hợp với ví dụ của bạn. Tuy nhiên, với giải pháp của bạn, bạn sẽ không biết lý do (bệnh), bạn chỉ cần loại bỏ vấn đề (về một khác biệt trống rỗng (triệu chứng) dường như bị lỗi. Để rõ ràng: Tôi không nói rằng đó là một giải pháp tồi. Nó có thể giúp ai đó, nếu anh ấy / cô ấy chỉ muốn vấn đề biến mất. ... Hy vọng rằng tôi đã làm sáng tỏ về siêu nhân bệnh tật của mình. :)
einjohn

@einjohn Có vẻ như là kết thúc dòng hầu hết thời gian. Có vẻ như statusdiffcó cách xử lý riêng biệt.
Shaun Luttin

5

Tôi gặp vấn đề này. Trường hợp của tôi cũng tương tự như các LESSvấn đề đăng bởi rcwxok .

Trong trường hợp của tôi, tôi đặt PAGERbiến môi trường thành PAGER='less -RSF'.

Tuy nhiên, không giống như các câu trả lời trước đó, tôi không muốn loại bỏ -Ftùy chọn này, vì tôi rõ ràng đặt nó ở đó với hy vọng ngăn chặn hiển thị sự khác biệt lessnếu nó ngắn hơn một màn hình.

Để có được kết quả mong muốn, thay vì xóa -F, tôi đã thêm -X: PAGER='less -RSFX'. Điều này cả hai đã giải quyết git diffvấn đề và ngoài ra nó ngăn chặn hiển thị các khác biệt ngắn với less.


Viết hoa có vẻ kỳ lạ. Bạn có nghĩa là "ít -RSFX" thay vì "LESS -RSFX"? Là các tùy chọn trường hợp chính xác?
StackzOfZtuff

1
Vâng, cảm ơn, đó là một sai lầm. Không chắc nó đã xảy ra như thế nào. Bây giờ đã sửa.
avivr

3

Tôi vừa mới chạy trong một vấn đề tương tự. git diff filekhông hiển thị gì vì tôi đã thêm tệp vào chỉ mục Git với một phần tên của nó bằng chữ in hoa : GeoJSONContainer.js.

Sau đó, tôi đã đổi tên thành GeoJsonContainer.jsvà thay đổi đã bị theo dõi. git diff GeoJsonContainer.jskhông cho thấy gì Tôi đã phải xóa tệp khỏi chỉ mục bằng cờ lực và thêm lại tệp:

git rm -f GeoJSONContainer.js
git add GeoJSONContainer.js

2

Bạn đã không thực sự hỏi một câu hỏi thực tế, nhưng vì đây là trường hợp sử dụng chung nên tôi thường xuyên sử dụng đây là những gì tôi làm. Bạn có thể tự thử điều này và xem nếu lỗi vẫn còn.

Giả định của tôi về trường hợp sử dụng của bạn:

Bạn có một thư mục hiện có chứa các tệp và thư mục và bây giờ muốn chuyển đổi nó thành kho lưu trữ Git được sao chép từ một nơi khác mà không có thay đổi bất kỳ dữ liệu nào trong thư mục hiện tại của bạn.

Thực sự có hai cách.

Bản sao repo - mv .git- git thiết lập lại - có

Phương pháp này là những gì bạn đã làm - sao chép kho lưu trữ hiện có vào một thư mục trống, sau đó di chuyển .gitthư mục vào thư mục đích. Để làm việc mà không gặp vấn đề gì, điều này thường đòi hỏi bạn phải chạy

git reset --hard

Tuy nhiên, điều đó sẽ thay đổi trạng thái của các tệp trong thư mục hiện tại của bạn. Bạn có thể thử điều này trên một bản sao đầy đủ / rsync của thư mục của bạn và nghiên cứu những thay đổi. Ít nhất sau đó bạn sẽ không còn thấy sự khác biệt giữagit logstatus.

Khởi tạo kho lưu trữ mới - trỏ đến nguồn gốc

Thứ hai là ít đáng lo ngại hơn: cdvào đích của bạn và bắt đầu một kho lưu trữ mới với

git init

Sau đó, bạn nói với kho lưu trữ mới, rằng nó có tổ tiên ở một nơi khác:

git remote add origin original_git_repo_path

Sau đó an toàn

git fetch origin master

để sao chép dữ liệu mà không thay đổi các tệp cục bộ của bạn. Mọi thứ sẽ ổn ngay bây giờ.

Tôi luôn đề xuất cách thứ hai để ít bị lỗi hơn.


Bạn dường như ngụ ý rằng đây là một lỗi git . Ok, có thể được. Tôi vẫn cho rằng tôi thiếu hiểu biết về git thích hợp, bởi vì tôi không thông minh như Linus ;-)
Towi

@towi: Không, tôi không ngụ ý rằng đây là lỗi git, tôi cũng không ngụ ý ngược lại. Tôi không quen thuộc với nội bộ git. Nhưng như một quy tắc chung, bằng cách di chuyển xung quanh .gitcác thư mục vào các khu vực làm việc khác, chúng tôi có khả năng vi phạm các giả định của git. Nếu điều này dẫn đến hành vi thất thường, chúng ta không thể đổ lỗi cho git, chúng ta phải tự trách mình vì đã chơi trò bịp với git. git cung cấp phương tiện để khắc phục điều đó, ví dụ như các reset --hard. Chỉ là đó không phải là những gì chúng ta muốn. Đây chính xác là lý do tại sao init/remote addcách này được khuyến nghị, và tất cả đều tốt.
cfi

@towi và Oliver P: Mặc dù tôi hiểu rằng bạn muốn giải quyết trường hợp lỗi cụ thể của mình, đôi khi bạn chỉ nên đi theo các khuyến nghị chung - đặc biệt là nếu chúng phù hợp hoàn hảo với trường hợp sử dụng của bạn. Cũng không mất dữ liệu. Và remote addcách làm việc vẫn có thể được áp dụng cho một tình huống lộn xộn như tình huống được mô tả bởi Oliver P
cfi

1
Một downvote không có bình luận không giúp cải thiện câu trả lời này, cũng như toàn bộ trang web. Bất cứ ai downvote, xin vui lòng để lại nhận xét để vấn đề có thể được giải quyết.
cfi

1

Tôi vấp phải vấn đề này một lần nữa. Nhưng lần này nó xảy ra vì một lý do khác. Tôi đã sao chép các tập tin vào repo để ghi đè lên các phiên bản trước. Bây giờ tôi có thể thấy các tập tin được sửa đổi nhưng diff không trả về diffs.

Ví dụ: tôi có tệp mainpage.xaml. Trong File Explorer, tôi đã dán một tệp mainpage.xaml mới so với tệp trong repo hiện tại của tôi. Tôi đã làm việc trên một máy khác và chỉ cần dán tập tin ở đây.
git cho thấy sửa đổi

Các tập tin hiển thị sửa đổi, nhưng khi tôi chạy git diff, nó sẽ không hiển thị các thay đổi. Có thể là do fileinfo trên tệp đã thay đổi và git biết rằng nó không thực sự là cùng một tệp. Hấp dẫn.

git diff không cho thấy gì

Bạn có thể thấy rằng khi tôi chạy diff trên tệp, nó không hiển thị gì, chỉ trả về dấu nhắc.


1

Tôi đã có cùng một vấn đề được mô tả theo cách sau: Nếu tôi gõ

$ git diff

Git chỉ đơn giản là trở lại dấu nhắc mà không có lỗi.

Nếu tôi gõ

$ git diff <filename>

Git chỉ đơn giản là trở lại dấu nhắc mà không có lỗi.

Cuối cùng, bằng cách đọc xung quanh tôi nhận thấy rằng git diff thực sự gọimingw64\bin\diff.exe hiện công việc.

Đây là thỏa thuận. Tôi đang chạy Windows và đã cài đặt một tiện ích Bash khác và nó đã thay đổi đường dẫn của tôi để nó không còn trỏ đến tôi nữa mingw64 \ bin nữa.

Vì vậy, nếu bạn gõ:

git diff

và nó chỉ trở về dấu nhắc bạn có thể gặp vấn đề này.

Diff.exe thực tế được điều hành bởi git nằm trong thư mục mingw64 \ bin của bạn

Cuối cùng, để khắc phục điều này, tôi thực sự đã sao chép mingw64\bin thư mục vào vị trí mà Git đang tìm kiếm. Tôi đã thử và nó vẫn không hoạt động.

Sau đó, tôi đóng cửa sổ Git Bash của mình và mở nó một lần nữa đi đến kho lưu trữ tương tự của tôi đã bị lỗi và bây giờ nó hoạt động.

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.