Lệnh Git để hiển thị các tệp cụ thể bị bỏ qua bởi .gitignore


645

Tôi đang bị ướt chân với Git và có vấn đề sau:

Cây nguồn dự án của tôi:

/
|
+--src/
+----refs/
+----...
|
+--vendor/
+----...

Tôi có mã (hiện là MEF) trong chi nhánh nhà cung cấp của mình mà tôi sẽ biên dịch ở đó và sau đó di chuyển các tham chiếu vào /src/refsđó là nơi mà dự án chọn chúng từ đó.

Vấn đề của tôi là tôi có .gitignorethiết lập của tôi để bỏ qua *.dll*.pdb. Tôi có thể thực hiện git add -f bar.dllđể buộc thêm tệp bị bỏ qua, điều này không ổn, vấn đề là tôi không thể tìm ra danh sách những tệp tồn tại bị bỏ qua.

Tôi muốn liệt kê các tệp bị bỏ qua để đảm bảo rằng tôi không quên thêm chúng.

Tôi đã đọc trang người đàn ông trên git ls-filesvà không thể làm cho nó hoạt động. Dường như với tôi rằng git ls-files --exclude-standard -inên làm những gì tôi muốn. Tôi đang thiếu gì?


12
Ngày nay, bạn sẽ không sử dụng git-ls-files mà thay vào đó là 'git ls-files'
wojo

7
Tôi nài nỉ bạn kiểm tra câu trả lời của riyad là chính xác vì đó là cách duy nhất thừa nhận không có cách nào đảm bảo để làm điều này bằng cách chỉ sử dụng các lệnh git (bao gồm cả git cleanmẹo) như được trình bày ở đây . Ngoài ra, tôi khuyên bạn nên chống lại ví dụ "loại trừ khỏi" trong bản tóm tắt của bạn vì thực tế điều đó không chú ý đến bất kỳ tệp .gitignore nào. Tôi yêu cầu điều này đặc biệt bởi vì trang này là phản hồi hàng đầu của Google.
Alexander Bird

Điểm nhanh về "Tóm tắt nội dung hoạt động": trang man "Git ls-files" giải thích rằng "-i" có nghĩa là bao gồm các tệp bị loại trừ cho đầu ra ls. Tôi đã có sự hiểu lầm tương tự, cho đến khi tôi đọc 'nó chậm'. ;-)
sẽ

2
Câu trả lời nên đi trong một bài trả lời và không phải là một chỉnh sửa cho câu hỏi.
Flimm

Tôi có git config --global alias.ls ls-files --exclude-standard, và điều đó làm cho câu trả lời cho câu hỏi này git ls -i.
jthill

Câu trả lời:


662

Ghi chú:


Cũng thú vị (được đề cập trong câu trả lời của qwertymk ), bạn cũng có thể sử dụng lệnh, ít nhất là trên Unix ( không hoạt động trong phiên Windows Windows )git check-ignore -v

git check-ignore *
git check-ignore -v *

Cái thứ hai hiển thị quy tắc thực tế .gitignorelàm cho một tập tin bị bỏ qua trong repo git của bạn.
Trên Unix, sử dụng " Điều gì mở rộng cho tất cả các tệp trong thư mục hiện tại theo cách đệ quy? " Và bash4 +:

git check-ignore **/*

(hoặc một find -execlệnh)

Lưu ý: https://stackoverflow.com/users3531947/Rafi B. đề xuất trong các nhận xét để tránh sao (rủi ro) :

git check-ignore -v $(find . -type f -print)

Đảm bảo loại trừ các tệp khỏi .git/ thư mục con mặc dù.


Câu trả lời gốc 42009)

git ls-files -i

nên hoạt động, ngoại trừ mã nguồn của nó chỉ ra:

if (show_ignored && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);

exc_given ?

Hóa ra nó cần thêm một tham số sau -i thực sự liệt kê bất cứ thứ gì:

Thử:

git ls-files -i --exclude-from=[Path_To_Your_Global].gitignore

(nhưng điều đó sẽ chỉ liệt kê bộ nhớ cache của bạn đối tượng được (không bị bỏ qua) của bạn, với một bộ lọc, vì vậy đó không hoàn toàn là những gì bạn muốn)


Thí dụ:

$ cat .git/ignore
# ignore objects and archives, anywhere in the tree.
*.[oa]
$ cat Documentation/.gitignore
# ignore generated html files,
*.html
# except foo.html which is maintained by hand
!foo.html
$ git ls-files --ignored \
    --exclude='Documentation/*.[0-9]' \
    --exclude-from=.git/ignore \
    --exclude-per-directory=.gitignore

Trên thực tế, trong tệp 'gitignore' của tôi (được gọi là 'loại trừ'), tôi tìm thấy một dòng lệnh có thể giúp bạn:

F:\prog\git\test\.git\info>type exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

Vì thế....

git ls-files --others --ignored --exclude-from=.git/info/exclude
git ls-files -o -i --exclude-from=.git/info/exclude

git ls-files --others --ignored --exclude-standard
git ls-files -o -i --exclude-standard

nên làm thủ thuật.

Như đã đề cập trong trang man ls-files ,--others là phần quan trọng, để hiển thị cho bạn các tệp không được lưu trong bộ nhớ cache, không cam kết, thường bị bỏ qua.

--exclude_standardkhông chỉ là một phím tắt, mà là một cách để bao gồm tất cả các cài đặt "mẫu bị bỏ qua" tiêu chuẩn.

exclude-standard
Thêm các loại trừ git tiêu chuẩn : .git/info/exclude, .gitignoretrong mỗi thư mục và user's global exclusion file.


@VocC, từ sự hiểu biết của tôi về các bài kiểm tra này , Câu trả lời bạn đề xuất ở đầu đơn giản có thể có những sai sót lớn. Đó là lý do tại sao tôi thường đề nghị câu trả lời của riyad thay thế.
Alexander Bird

2
Kể từ khi Git v2.13.2 phát hành: git status --ignoreddường như nó cũng hiển thị các tệp chưa được theo dõi: github.com/git/git/blob/master/Documentation/RelNotes/ Lỗi
Pau

1
wow, git check-ignore -v *hoạt động rất tốt, vì nó cho thấy cấu hình được áp dụng. Cảm ơn bạn.
Hoàng Trần

@MikeD Để thực hiện * / công việc (hoặc thực tế, bạn chỉ có thể làm **), bạn cần phải cài đặt sao shopt -s globstarsau khi nó hoạt động.
Veda

Không kích hoạt (rủi ro) toàn cầu:git check-ignore -v $(find . -type f -print)
rafi

483

Có một cách đơn giản hơn nhiều để làm điều đó (git 1.7.6+):

git status --ignored

Xem Có cách nào để nói trạng thái git để bỏ qua ảnh hưởng của các tệp .gitignore không?


3
Phiên bản nào của git bạn đang sử dụng? Của tôi (1.7.0.4) nói error: unknown option 'ignored'. Ngay cả việc thêm -snhư đề xuất trong bài đăng được liên kết cũng không hoạt động.
Alexander Bird

3
Phiên bản của tôi là 1.7.6. Một phiên bản khác 1.7.5.1 là phiên bản yêu cầu -s. Bạn có thể thử git status -hxem nếu --ignoredđược hỗ trợ
Penghe Geng

1
Tôi đoán rằng đơn giản là chưa được hỗ trợ trong 1.7.0.4. Máy tính khác của tôi có 1.7.9 và cờ - được đặt ở đó
Alexander Bird

4
Tôi đã thử mọi giải pháp trên trang này. Đây là điều tốt nhất. Nó hiển thị cả tập tin và thư mục. Tính năng này có lẽ không có sẵn khi câu hỏi này ban đầu được hỏi. (Nhân tiện, tất cả các giải pháp sẽ không hoạt động đúng với một "git init" hoàn toàn mới cho đến khi bạn ít nhất thay đổi theo giai đoạn.)
wvducky

12
Điều này chắc chắn tốt hơn nhiều so với câu trả lời được chấp nhận. Nó cũng an toàn hơn nhiều so với git clean -ndXgiải pháp, bởi vì tình huống hiếm khi người ta quên nhầm cờ sẽ có tác dụng không thể hủy bỏ trên kho lưu trữ, vì các tệp không được theo dõi bị xóa. Vì vậy, nó là nguy hiểm. Trái lại git status --ignoredluôn luôn an toàn, ngay cả khi gõ sai và đó là điều tự nhiên cần nhớ.
Ioannis Filippidis

400

Một tùy chọn khác khá sạch sẽ (Không có ý định chơi chữ.):

git clean -ndX

Giải trình:

$ git help clean

git-clean - Remove untracked files from the working tree
-n, --dry-run - Don't actually remove anything, just show what would be done.
-d - Remove untracked directories in addition to untracked files.
-X - Remove only files ignored by Git.

Lưu ý: Giải pháp này sẽ không hiển thị các tệp bị bỏ qua đã bị xóa.


Tiện lợi ... tuy nhiên lý do tôi hỏi câu hỏi ban đầu là để tôi có thể chắc chắn rằng các tập tin của nhà cung cấp (* đậm) được cho là có ... vì vậy việc xóa chúng sẽ không phải là kết quả mong muốn. TUY NHIÊN: điều này là tốt để biết vì tôi đã thay đổi chiến lược của mình từ bỏ qua * .t sang bỏ qua thư mục đầu ra xây dựng của tôi (nhưng không phải là thư mục nhà cung cấp của tôi). Đây sẽ là một thay thế tốt make cleanvà rất hữu ích trên một máy chủ xây dựng.
Andrew Burns

2
Tôi đang sử dụng phiên bản git 1.7.0.4 và hai lệnh ('git ls-files -o -i --exclude-standard', 'git clean -dXn') không tương đương. Cái đầu tiên cho tôi xem 4 tập tin, và cái thứ hai chỉ có hai. (.gitignore ~, index.php ~, sql / create_users.sql ~, www / index.php ~) (Sẽ xóa .gitignore ~, Sẽ xóa index.php ~). Tôi có nhớ cái gì ở đây không?
Cesar

@VonC, ngọt ngào! Cảm ơn! @Cesar, tôi không chắc. Tôi không quen thuộc lắm git ls-files -o -i --exclude-standard. git clean -dXnluôn luôn là những gì tôi muốn nhưng không hiển thị các tập tin bị bỏ qua đã bị xóa. git ls-files -o -i --exclude-standardcó thể làm điều đó Vì vậy, đó có thể là những gì gây ra sự khác biệt.
ma11hew28

3
Một điều nhỏ bé - có thể là một ý tưởng tốt để gõ nđầu tiên, ít cơ hội vô tình xóa theo cách đó; git clean -ndX
Tobias Cohen

1
@TobiasCohen tốt đẹp! Tôi cập nhật câu trả lời với đề nghị của bạn. An toàn hơn. Mặc dù, nếu bạn rời khỏi n, Git mặc định fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean. Vẫn khá an toàn, nhưng gõ nđầu tiên thậm chí còn an toàn hơn! :)
ma11hew28

39

Trong khi nói chung, giải pháp của bạn không hoạt động trong mọi trường hợp. Giả sử một thư mục repo như thế này:

# ls **/*                                                                                                       
doc/index.html  README.txt  tmp/dir0/file0  tmp/file1  tmp/file2

doc:
index.html

tmp:
dir0  file1  file2

tmp/dir0:
file0

và một .gitignore như thế này:

# cat .gitignore
doc
tmp/*

Điều này bỏ qua docthư mục và tất cả các tập tin dưới đây tmp. Git hoạt động như mong đợi, nhưng lệnh đã cho để liệt kê các tệp bị bỏ qua thì không. Hãy xem git nói gì:

# git ls-files --others --ignored --exclude-standard                                                            
tmp/file1
tmp/file2

Lưu ý rằng docthiếu từ danh sách. Bạn có thể lấy nó với:

# git ls-files --others --ignored --exclude-standard --directory                                                
doc/

Lưu ý các --directorytùy chọn bổ sung .

Theo hiểu biết của tôi, không có một lệnh nào để liệt kê tất cả các tệp bị bỏ qua cùng một lúc. Nhưng tôi không biết tại sao tmp/dir0lại không xuất hiện.


2
Điều này mang lại cho tôi những gì tôi muốn, trong khi những người khác thì không (đối với trường hợp cụ thể của tôi) ... cảm ơn! Thật khó chịu khi phải chạy hai lệnh, nhưng với một thư mục bị bỏ qua, tùy chọn --directory ít nhất tìm thấy tôi và tôi có thể chuyển lệnh đó thành lệnh find để tìm tệp. Cảm ơn!
lindes

Điều này thực hiện tất cả cùng một lúc và mở rộng các thư mục:(git ls-files -oi --exclude-standard; git ls-files -oi --exclude-standard --directory) | perl -nle '$seen{$_}++||next;if(-d){system"find",$_,"-type","f"}else{print}'
Dee Newcum

17

Git hiện có chức năng này được tích hợp sẵn

git check-ignore *

Tất nhiên bạn có thể thay đổi toàn cầu thành một cái gì đó như **/*.dll trong trường hợp của bạn

Tham khảo Git


7
git check-ignore **/*để bao gồm các tệp trong thư mục con
mzimmer 17/03/2015

Điều này chỉ liệt kê các dicrectories cấp cao nhất.
Radon8472

13

Nó là đủ để sử dụng

git ls-files --others -i --exclude-standard

vì nó bao gồm mọi thứ được bao phủ bởi

git ls-files --others -i --exclude-from=.git/info/exclude

do đó, cái sau là dư thừa.


Bạn có thể làm điều này dễ dàng hơn bằng cách thêm bí danh vào ~/.gitconfigtệp của mình :

git config --global alias.ignored "ls-files --others -i --exclude-standard"

Bây giờ bạn có thể chỉ cần gõ git ignored để xem danh sách. Dễ nhớ hơn nhiều, và gõ nhanh hơn.

Nếu bạn thích hiển thị ngắn gọn hơn về giải pháp của Jason Geng, bạn có thể thêm bí danh cho điều đó như thế này:

git config --global alias.ignored "status --ignored -s"

Tuy nhiên, đầu ra dài dòng hơn sẽ hữu ích hơn trong việc khắc phục sự cố với các tệp .gitignore của bạn, vì nó liệt kê mọi tệp bông chọn lọc bị bỏ qua. Thông thường bạn sẽ dẫn các kết quả qua grepđể xem liệu một tệp bạn muốn bỏ qua có ở đó không, hoặc nếu một tệp bạn không muốn bỏ qua có trong đó không.

git ignored | grep some-file-that-isnt-being-ignored-properly

Sau đó, khi bạn chỉ muốn xem một màn hình ngắn, đủ dễ nhớ và gõ

git status --ignored

(Thông -sthường có thể được bỏ đi.)


Điều này không bao giờ làm việc cho tôi, bởi vì bạn phải liệt kê thủ công các tệp đó. git status --ignoredhoạt động trên sid Debian nhưng có thể rất mới, nhưng rõ ràng nó đã được thêm vào do nhu cầu phổ biến ;-)
mirabilos

1
Bởi "hoạt động trên Debian sid" Tôi giả sử bạn có nghĩa là "hoạt động với phiên bản Git được cài đặt theo mặc định trên sid sid Debian"? Bạn thực sự nên tránh để mình bị bắt làm con tin bởi các phiên bản tiện ích có trong bản phân phối của bạn. Bạn có thể nâng cấp chúng độc lập với bản phân phối.
iconoclast

12

Dưới đây là cách in danh sách đầy đủ các tệp trong cây làm việc khớp với các mẫu nằm ở bất kỳ đâu trong nhiều nguồn gitignore của Git (nếu bạn đang sử dụng GNU find):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose

Nó sẽ kiểm tra tất cả các tệp trong nhánh hiện tại của kho lưu trữ (trừ khi bạn đã xóa chúng cục bộ).

Và nó cũng xác định các dòng nguồn gitignore cụ thể.

Git tiếp tục theo dõi các thay đổi trong một số tệp khớp với các mẫu của gitignore, đơn giản vì các tệp đó đã được thêm vào. Sử dụng, lệnh trên cũng hiển thị các tệp đó.

Mô hình gitignore tiêu cực cũng được kết hợp. Tuy nhiên, đây là những dễ dàng phân biệt trong danh sách, bởi vì chúng bắt đầu bằng !.

Nếu bạn đang sử dụng Windows, Git Bash bao gồm GNU find(như được tiết lộ bởi find --version).

Nếu danh sách dài (và bạn có rev), bạn cũng có thể hiển thị chúng theo phần mở rộng (phần nào):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose \
| rev | sort | rev

Để biết thêm chi tiết, xem man find, man git-check-ignore, man rev, vàman sort .

Điểm của toàn bộ cách tiếp cận này là Git (phần mềm) đang thay đổi nhanh chóng và rất phức tạp. Ngược lại, GNU findcực kỳ ổn định (ít nhất, trong các tính năng của nó sử dụng ở đây). Vì vậy, bất cứ ai muốn cạnh tranh bằng cách hiển thị kiến ​​thức chuyên sâu về Git của họ sẽ trả lời câu hỏi theo một cách khác.

Câu trả lời tốt nhất là gì? Câu trả lời này cố tình giảm thiểu sự phụ thuộc vào kiến ​​thức Git, hướng tới đạt được mục tiêu ổn định và đơn giản thông qua mô đun (cách ly thông tin) và được thiết kế để tồn tại lâu dài .


Cảm ơn rất nhiều! Tôi đã đấu tranh để tìm ra lý do tại sao một số tệp nguồn mới của tôi thỉnh thoảng bị thiếu trong các cam kết của tôi. Hóa ra tôi có một mẫu: bin *, mà tôi nghĩ sẽ chỉ khớp với tên của các tệp / thư mục bắt đầu bằng bin nhưng thay vào đó, nó khớp với bất kỳ thứ gì có chứa bin trong đường dẫn đầy đủ của tệp / thư mục! Tôi đoán, vấn đề của tôi xuất phát từ sự hiểu lầm về ngữ nghĩa chính xác của khớp mẫu trong .gitignore. Kịch bản 2 dòng của bạn đã giúp tôi tìm ra lỗi này!
Nicolas Rouquette

1

(mở rộng các câu trả lời khác)

Lưu ý, git check-ignoresử dụng cam kết .gitignorevà không phải là một trong cây làm việc của bạn! Để chơi với nó mà không làm ô nhiễm lịch sử git của bạn, bạn có thể tự do cố gắng chỉnh sửa nó, và sau đó cam kết với mộtgit commit --amend .

Vấn đề này xảy ra chủ yếu nếu bạn cần một cách giải quyết vấn đề, git đó không tuân theo các thư mục. Nhập vào .gitignore:

dirtokeep/**
!dirtokeep/.keep

.keepnên là một tập tin có độ dài bằng không dirtokeep.

Kết quả sẽ là mọi thứ trong đó dirtokeepsẽ bị bỏ qua, ngoại trừ dirtokeep/.keep , kết quả là dirtokeepthư mục cũng sẽ được xây dựng trên bản sao / thanh toán.


0

Giả sử có một vài thư mục bỏ qua, tại sao không sử dụng "nút trạng thái git / log /" sẽ cho bạn biết những tập tin nào sẽ được thêm vào? Trong thư mục tôi có một tệp văn bản không phải là một phần của đầu ra trạng thái, ví dụ:

Trên nhánh chính Chi nhánh
của bạn được cập nhật với 'origin / master'.
Các tệp không bị theo dõi:
(sử dụng "git add ..." để đưa vào những gì sẽ được cam kết)

    node/logs/.gitignore 

.gitignore là:

*

! .gignignore

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.