Làm thế nào để quy tắc loại trừ .gitignore thực sự hoạt động?


146

Tôi đang cố gắng giải quyết vấn đề gitignore trên một cấu trúc thư mục lớn, nhưng để đơn giản hóa câu hỏi của tôi, tôi đã giảm nó xuống như sau.

Tôi có cấu trúc thư mục sau của hai tệp (foo, bar) trong kho git hoàn toàn mới (cho đến nay không có cam kết):

a/b/c/foo
a/b/c/bar

Rõ ràng, một 'trạng thái git -u' hiển thị:

# Untracked files:
...
#       a/b/c/bar
#       a/b/c/foo

Những gì tôi muốn làm là tạo một tệp .gitignore bỏ qua mọi thứ bên trong a / b / c nhưng không bỏ qua tệp 'foo'.

Nếu tôi tạo một .gitignore như vậy:

c/

Sau đó, một 'trạng thái git -u' hiển thị cả foo và thanh như bị bỏ qua:

# Untracked files:
...
#       .gitignore

Đó là như tôi mong đợi.

Bây giờ nếu tôi thêm quy tắc loại trừ cho foo, do đó:

c/
!foo

Theo trang web của gitignore, tôi hy vọng nó sẽ hoạt động. Nhưng nó không - nó vẫn bỏ qua foo:

# Untracked files:
...
#       .gitignore

Điều này cũng không hoạt động:

c/
!a/b/c/foo

Không làm điều này:

c/*
!foo

Cung cấp:

# Untracked files:
...
#       .gitignore
#       a/b/c/bar
#       a/b/c/foo

Trong trường hợp đó, mặc dù foo không còn bị bỏ qua, thanh cũng không được bỏ qua.

Thứ tự của các quy tắc trong .gitignore dường như cũng không quan trọng.

Điều này cũng không làm những gì tôi mong đợi:

a/b/c/
!a/b/c/foo

Cái đó bỏ qua cả foo và bar.

Một tình huống hoạt động là nếu tôi tạo tệp a / b / c / .gitignore và đặt vào đó:

*
!foo

Nhưng vấn đề với điều này là cuối cùng sẽ có các thư mục con khác theo a / b / c và tôi không muốn phải đặt một .gitignore riêng biệt cho mỗi một - tôi đã hy vọng tạo ra '.gitignore dựa trên dự án'. các tệp có thể nằm trong thư mục trên cùng của mỗi dự án và bao gồm tất cả cấu trúc thư mục con 'tiêu chuẩn'.

Điều này cũng có vẻ tương đương:

a/b/c/*
!a/b/c/foo

Đây có thể là điều gần nhất để "làm việc" mà tôi có thể đạt được, nhưng các đường dẫn tương đối đầy đủ và ngoại lệ rõ ràng cần được nêu rõ, sẽ là một nỗi đau nếu tôi có nhiều tệp tên 'foo' ở các cấp độ khác nhau của cây thư mục con.

Dù sao, tôi cũng không hiểu các quy tắc loại trừ hoạt động như thế nào hoặc chúng hoàn toàn không hoạt động khi các thư mục (chứ không phải ký tự đại diện) bị bỏ qua - bởi một quy tắc kết thúc bằng /

Bất cứ ai có thể xin vui lòng làm sáng tỏ về điều này?

Có cách nào để khiến gitignore sử dụng một cái gì đó hợp lý như các biểu thức thông thường thay vì cú pháp dựa trên vỏ vụng về này không?

Tôi đang sử dụng và quan sát điều này với git-1.6.6.1 trên Cygwin / bash3 và git-1.7.1 trên Ubuntu / bash3.



4
Câu hỏi tuyệt vời bằng văn bản! Số lượng các trường hợp bạn đã cố gắng thực sự giúp tôi hiểu những gì tôi đã làm sai trong trường hợp tương tự của tôi. Cảm ơn chúa, tôi đã tìm kiếm rất lâu ngày hôm nay.
Alex G

Câu trả lời:


153
/ a / b / c / *
!

Có vẻ như hoạt động với tôi (git 1.7.0.4 trên Linux). Điều *quan trọng là nếu không, bạn sẽ bỏ qua chính thư mục (vì vậy git sẽ không nhìn vào bên trong) thay vì các tệp trong thư mục (cho phép loại trừ).

Hãy nghĩ về các loại trừ như nói "nhưng không phải cái này" chứ không phải "nhưng bao gồm cái này" - "bỏ qua thư mục này ( /a/b/c/) nhưng không phải cái này ( foo)" không có ý nghĩa nhiều; "bỏ qua tất cả các tệp trong thư mục này ( /a/b/c/*) nhưng không phải tệp này ( foo)". Để trích dẫn trang người đàn ông:

Một tiền tố tùy chọn! trong đó phủ nhận mô hình; bất kỳ tệp phù hợp nào được loại trừ bởi một mẫu trước đó sẽ được đưa vào lại.

tức là, tệp phải được loại trừ để được đưa vào lại. Hy vọng rằng làm sáng tỏ một số.


Vâng, ví dụ bạn đưa ra cũng làm việc tốt cho tôi. Vấn đề là / a / b / * không hoạt động nếu foo ở c, có nghĩa là nếu tôi có nhiều tệp foo trong các thư mục con khác nhau trong c (ví dụ: d /, e /, f / g / h /, i / j /, v.v.) thì quy tắc phủ định '! foo' sẽ không bắt được chúng.
davidA

1
@meowsqueak Quả thực là không. Nếu bạn bỏ qua / a / b / * thì sẽ không có thư mục nào cho foo ở! Nếu bạn đang cố gắng bỏ qua toàn bộ cây thư mục bên dưới / a / b nhưng bao gồm bất kỳ tệp nào có tên "foo" có thể ở bất kỳ đâu trên cây, tôi không nghĩ rằng nó có thể thực hiện được với các mẫu .gitignore: \
Chris

Trên thực tế, điều này có thể giải thích tại sao điều này không hiệu quả với tôi - các quy tắc sau không hoạt động: "/ a / b / *", "! C / foo". Nếu điều đó làm việc, có thể không có vấn đề.
davidA

5
"Tôi không nghĩ rằng nó có thể thực hiện được với các mẫu .gitignore" - Thật không may, tôi nghĩ bạn đã đúng.
davidA

@meowsqueak Bạn có thể bỏ qua /a/b/cvà sau đó viết một hook vào git add --forcebất kỳ tập tin phù hợp nào trước khi cam kết hoặc một cái gì đó
Chris

24

Tôi có một tình huống tương tự, giải pháp của tôi là sử dụng:

/a/**/*
!/a/**/foo

Điều đó sẽ làm việc cho một số lượng thư mục trung gian tùy ý nếu tôi đọc **đúng.


6

điều này chắc chắn không rõ ràng từ trang người đàn ông .gitignore. Những công việc này:

*
!/a
!/a/b
!/a/b/c
!/a/b/c/foo

# don't forget this one
!.gitignore

Như Chris đã đề cập, một thư mục thậm chí không được mở nếu nó bị loại trừ. Vì vậy, nếu bạn muốn có thể bỏ qua * nhưng một số tệp, bạn phải xây dựng đường dẫn đến các tệp đó như trên. Đối với tôi điều này là thuận tiện, vì tôi muốn thực hiện đánh giá mã trên 1 tệp của thư viện và nếu tôi muốn làm khác sau tôi chỉ cần thêm nó và tất cả những thứ khác sẽ bị bỏ qua.


6

Đây là một lựa chọn khác:

*
!/a*
!/a/*
!/a/*/*
!/a/*/*/*

Điều đó sẽ bỏ qua mọi tệp và thư mục, ngoại trừ tệp / thư mục ba cấp độ sâu trong a.


5

Nói một cách tổng quát hơn, git1.8.2 sẽ bao gồm bản vá (cũng trong v4 của nó , được nhắc bởi một số câu hỏi về Stack Overflow ) từ Adam Spiers về việc xác định gitignorequy tắc nào thực sự bỏ qua tệp của bạn.

Xem ghi chú phát hành git1.8.2 và câu hỏi SO " quy tắc gitignore nào đang bỏ qua tệp của tôi ":
đó sẽ là lệnh git check-ignore.


1
Cảm ơn đã phát thông tin này. check-ignorecũng sẽ cho bạn biết quy tắc nào ngăn tập tin của bạn bị bỏ qua, nếu đó là trường hợp.
Adam Spiers

@AdamSpiers nghe hay đấy. Tôi chắc chắn sẽ phải chơi với nó.
VonC
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.