Tôi có thể sử dụng git diff trên các tệp không bị theo dõi không?


270

Có thể yêu cầu git diff đưa các tệp không bị theo dõi vào đầu ra khác của nó không? Hoặc là đặt cược tốt nhất của tôi để git thêm các tệp mới tôi đã tạo và các tệp hiện có mà tôi đã chỉnh sửa và sử dụng

git diff --cached

?

Câu trả lời:


267

Với các phiên bản git gần đây, bạn có thể git add -Ntệp (hoặc --intent-to-add), bổ sung một blob có độ dài bằng không vào chỉ mục tại vị trí đó. Kết quả cuối cùng là tệp "không bị theo dõi" của bạn bây giờ trở thành một sửa đổi để thêm tất cả nội dung vào tệp có độ dài bằng không này và hiển thị trong đầu ra "git diff".

git diff

echo "this is a new file" > new.txt
git diff

git add -N new.txt
git diff
diff --git a/new.txt b/new.txt
index e69de29..3b2aed8 100644
--- a/new.txt
+++ b/new.txt
@@ -0,0 +1 @@
+this is a new file

Đáng buồn thay, như đã chỉ ra, bạn không thể git stashtrong khi bạn có một --intent-to-addtệp đang chờ xử lý như thế này. Mặc dù nếu bạn cần stash, bạn chỉ cần thêm các tệp mới và sau đó stash chúng. Hoặc bạn có thể sử dụng cách giải quyết thi đua:

git update-index --add --cacheinfo \
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt

(thiết lập bí danh là bạn của bạn ở đây).


Hóa ra bản sao Git của tôi không đủ gần đây để thêm -N, nhưng điều này trả lời câu hỏi của tôi.
Andrew Grimm

1
Bạn có thể bắt chước "git add new.txt -N" với "git update-index --add --cacheinfo 100.644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt" (làm sao tôi quản lý để đặt này trên câu trả lời sai?)
araqnid


1
Điều gì nếu bạn có nhiều tệp mới, có cách nào dễ dàng để thêm tất cả chúng và sau đó khác không?
Vic

1
@Vicgit add -N .
Nathan

92

Tôi tin rằng bạn có thể khác với các tệp trong chỉ mục của mình và các tệp không bị theo dõi chỉ bằng cách cung cấp đường dẫn đến cả hai tệp.

git diff --no-index tracked_file untracked_file

3
Điều đó có hiệu quả không nếu bạn có nhiều hơn một tệp chưa được mã hóa mà bạn đã tạo kể từ lần xác nhận cuối cùng?
Andrew Grimm

12
Vâng, câu trả lời hoàn hảo! Sau đó tôi có thể sử dụng git diff --no-index untracked_file_1 untracked_file_2để có được git diffmàu cú pháp, vv trên diffs ... đẹp.
Colin D Bennett

40
Tôi không hiểu tại sao bạn lại so sánh một tệp được theo dõi với một tệp không bị theo dõi . Nếu bạn chỉ muốn nhận đầu ra khác cho tệp không bị theo dõi, bạn chỉ có thể sử dụng /dev/nullthay thế : git diff --no-index -- /dev/null <untracked_file>.

4
Hoặc chỉ cat untracked_file_1, hoặc có lẽ printf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"nếu bạn thực sự cần đầu ra xanh. :) (Mặc dù trên một ghi chú nghiêm túc hơn, xin lưu ý rằng việc thay thế lệnh sẽ xóa các dòng mới trong tệp của bạn.)
Wildcard

8
Đây phải là câu trả lời được chấp nhận - nó không yêu cầu thay đổi chỉ số của git; như tác giả ban đầu nói, có nhược điểm của nó
DIMMSum

38

Đối với việc gặm nhấm hàng ngày tương tác của tôi (nơi tôi khác biệt cây làm việc chống lại TRƯỚC và muốn có các tệp không bị theo dõi trong diff), add -N/--intent-to-addkhông thể sử dụng được, vì nó bị hỏng git stash .

Vì vậy, đây là sự git diffthay thế của tôi . Đây không phải là một giải pháp đặc biệt sạch sẽ, nhưng vì tôi thực sự chỉ sử dụng nó một cách tương tác, tôi ổn với một bản hack:

d() {
    if test "$#" = 0; then
        (
            git diff --color
            git ls-files --others --exclude-standard |
                while read -r i; do git diff --color -- /dev/null "$i"; done
        ) | `git config --get core.pager`
    else
        git diff "$@"
    fi
}

Việc nhập chỉ dsẽ bao gồm các tệp không bị theo dõi trong diff (đó là điều tôi quan tâm trong quy trình làm việc của mình) và d args...sẽ hoạt động như bình thường git diff.

Ghi chú:

  • Chúng tôi đang sử dụng thực tế ở đây git diffthực sự chỉ là các khác biệt riêng lẻ được ghép nối, do đó không thể nói dđầu ra từ một "khác biệt thực" - ngoại trừ thực tế là tất cả các tệp không được theo dõi được sắp xếp cuối cùng.
  • Vấn đề duy nhất với chức năng này là đầu ra được tô màu ngay cả khi được chuyển hướng; nhưng tôi không thể bận tâm để thêm logic cho điều đó.
  • Tôi không thể tìm thấy bất kỳ cách nào để có được các tệp không bị theo dõi bằng cách chỉ tập hợp một danh sách đối số khéo léo cho git diff. Nếu ai đó tìm ra cách để làm điều này, hoặc nếu có thể một tính năng được thêm gitvào một lúc nào đó trong tương lai, vui lòng để lại một ghi chú ở đây!

4
Trớ trêu thay, tôi git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txtworkaround tôi đã gợi ý cho GITS cũ không làm việc với git stash, giả sử bạn đã có e69de29bb trong db của bạn, ví dụ như bằng cách cố gắng sử dụng add -Ntrước đó. Vì vậy, rõ ràng nó không hoàn toàn tương đương với git add -Nmột cách nào đó: tbh Tôi không chắc làm thế nào.
araqnid

2
Nhân tiện, bạn đang thực hiện so sánh chuỗi thay vì kiểm tra đẳng thức số bằng testlệnh của bạn . Không nên ảnh hưởng đến bất cứ điều gì, nhưng test "$#" -eq 0chính xác hơn là những gì dự định.
tự đại diện

1
Vâng, vẫn có vẻ như bạn cần phải thực hiện theo cặp ... nhưng có thể giả mạo thành một lessđể bạn không phải nhấn qcho từng tệp và cảm giác chính xác như thế git diff, bằng cách xóa phân trang trên mỗi tệp ( -P), thêm lại vào sau ( | less), giữ màu ( --color=always) và diễn giải nó thành màu ( less -rhoặc less -R). Vì vậy, hoàn toàn đó là:do git -P diff --color=always -- /dev/null "$i"; done | less -r
hyperpallium

Trong trường hợp bạn muốn bị làm phiền trong tương lai, test -t 1(ví dụ if [ -t 1 ]; then color_arg=--color; fihoặc một cái gì đó) là một cách để shell kiểm tra xem đầu ra của nó có phải là một thiết bị đầu cuối hay không, đây là một cách hữu ích để quyết định màu. Và xargscó thể đưa ra một cách để thoát khỏi vòng lặp while. Bạn vẫn sẽ cần -n 1điều đó, vì vậy nó vẫn sẽ khởi động git rất nhiều lần, và vẫn cần phải được ghép theo cách đó, nhưng ... nó được loại bỏ whilereadvì vậy có lẽ tốt hơn?!? Tôi để lại cho người đọc.
lindes

28

Không phải 100%, nhưng nếu vì lý do nào đó bạn không muốn thêm các tệp của mình vào chỉ mục theo đề xuất của câu trả lời được chấp nhận, thì đây là một tùy chọn khác:

Nếu các tệp không bị theo dõi, rõ ràng diff là toàn bộ tệp, vì vậy bạn chỉ có thể xem chúng với ít hơn:

less $(git ls-files --others --exclude-standard)

Điều hướng giữa chúng với :n:pcho tiếp theo và trước đó ..

Cập nhật từ các bình luận: Nếu bạn cần một định dạng vá, bạn cũng có thể kết hợp nó với git diff:

git ls-files --others --exclude-standard | xargs -n 1 git --no-pager diff /dev/null | less

Bạn cũng có thể chuyển hướng đầu ra sang một tệp hoặc sử dụng lệnh diff khác trong trường hợp này.


6
bạn cũng có thể chạy git diff /dev/null <untracked_tile>và lấy bản vá ở định dạng bản vá thay vì "chỉ" một tệp
SimSimY

2
Câu trả lời này kết hợp với git diff là giải pháp hoàn hảo.
iwind

22
git add -A
git diff HEAD

Tạo bản vá nếu được yêu cầu và sau đó:

git reset HEAD

Điều này có khả năng mất công việc trước (trước), bằng cách thêm mọi thứ. Đặc biệt là trường hợp nếu một người sử dụng git add -prất thường xuyên (mà tôi thường khuyên dùng, nhân tiện) ... Điều này mang lại một cách làm cơ bản, chỉ là ... nên lưu ý rằng nó có khả năng cho phía không mong muốn Các hiệu ứng.
lindes

13

cái này hiệu quả với tôi

git add my_file.txt
git diff --cached my_file.txt
git reset my_file.txt

Bước cuối cùng là tùy chọn, nó sẽ để tập tin ở trạng thái trước đó (không bị theo dõi)

hữu ích nếu bạn đang tạo một bản vá quá:

  git diff --cached my_file.txt > my_file-patch.patch

Tính đặc hiệu của cặp add / reset này là một sự tương phản tốt với cách tiếp cận shotgun của stackoverflow.com/a/50486906/313756 ... cảm ơn vì điều đó.
lindes

9

Thay đổi hoạt động khi được dàn dựng và không dàn dựng với lệnh này. Các tệp mới hoạt động khi được dàn dựng:

$ git diff HEAD

Nếu chúng không được dàn dựng, bạn sẽ chỉ thấy sự khác biệt của tập tin.


26
HEADgiá trị mặc định , vì vậy điều này giống như git diffkhông giải quyết được vấn đề.
Iulian Onofrei

4
Điều này đòi hỏi git addtừ mọi tệp không được theo dõi
SilvioQ

Nếu bạn chỉnh sửa câu trả lời này để đưa ra câu trả lời git addđơn giản nhất nếu trường hợp sử dụng của bạn là kiểm tra những gì bạn vừa thêm / muốn thêm
KCD

8

Đối với một tệp:

git diff --no-index /dev/null new_file

Đối với tất cả các tệp mới:

for next in $( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null $next; done;

Như bí danh:

alias gdnew="for next in \$( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null \$next; done;"

Đối với tất cả các tệp sửa đổi và mới được kết hợp dưới dạng một lệnh:

{ git --no-pager diff; gdnew }

2

thông thường khi tôi làm việc với các nhóm vị trí từ xa, điều quan trọng đối với tôi là tôi có kiến ​​thức trước về những thay đổi được thực hiện bởi các nhóm khác trong cùng một tệp, trước khi tôi thực hiện các giai đoạn git không theo dõi -> dàn dựng -> cam kết rằng tôi đã viết một tập lệnh bash giúp tôi tránh giải quyết xung đột hợp nhất với nhóm từ xa hoặc tạo chi nhánh địa phương mới và so sánh và hợp nhất trên nhánh chính

#set -x 
branchname=`git branch | grep -F '*' |  awk '{print $2}'`
echo $branchname
git fetch origin ${branchname}
for file in `git status | grep "modified" | awk "{print $2}" `
do
echo "PLEASE CHECK OUT GIT DIFF FOR "$file 
git difftool FETCH_HEAD $file ;
done

trong tập lệnh trên, tôi tìm nạp nhánh chính từ xa (không cần đến nhánh chính của nó) để FETCH_HEAD họ tạo một danh sách các tệp đã sửa đổi của tôi và so sánh các tệp đã sửa đổi với git Difftool

Ở đây có nhiều điều khác nhau được hỗ trợ bởi git, tôi định cấu hình 'Meld Diff Viewer' để so sánh GUI tốt.


-9

Giả sử bạn không có cam kết địa phương,

git diff origin/master

8
Câu hỏi yêu cầu một git difflệnh bao gồm các tệp không bị theo dõi. Lệnh này không bao gồm chúng. Ngoài ra, có hay không các cam kết cục bộ tồn tại hoàn toàn không liên quan gì đến câu hỏi.
toon81

JFTR, tôi git merge --squash mybranchgit diff masterchỉ cho tôi những thay đổi trong các tệp không được theo dõi.
Muammar

2
Không thể nào. Bạn dường như bối rối về những gì "không theo dõi" có nghĩa là. Không bị theo dõi không có nghĩa là một tệp được theo dõi trong một nhánh chứ không phải một nhánh khác, điều đó có nghĩa là nó không "ở trong Git" ở bất kỳ đâu. Cho dù bạn bí hay không làm cho không có sự khác biệt. git diffkhông thể hiện sự khác biệt trong các tệp không được theo dõi: bởi vì chúng không bị theo dõi, theo định nghĩa, không bao giờ có sự khác biệt nào. Đó chỉ là cách Git hoạt động. :)
toon81
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.