Bỏ qua thư mục con của các thư mục bị bỏ qua trong Git


99

Giả sử tôi đã bỏ qua một thư mục, nhưng tôi muốn hủy bỏ qua các thư mục con cụ thể trong đó. Vì vậy, tôi có thiết lập:

/uploads/
/uploads/rubbish/
/uploads/rubbish/stuff/KEEP_ME/
/uploads/foo/
/uploads/foo/bar/lose/

Và tôi muốn bỏ qua tất cả mọi thứ trừ KEEP_MEthư mục. Tôi hy vọng cái bỏ qua sẽ trông giống như sau:

/uploads/*
!/uploads/rubbish/stuff/KEEP_ME/

Nhưng điều đó không hoạt động và cũng không phải là một số hoán vị trên cùng một chủ đề.

Một trong đó hoạt động là

/uploads/**/**/**/
!/uploads/rubbish/stuff/KEEP_ME/

Nhưng điều đó cảm thấy hơi hạn chế và dài dòng?


1
Mã bạn cung cấp không hoạt động đối với tôi (sử dụng git phiên bản 1.9.1). Một cách hoạt động là / uploads / *! / Uploads / rubbish / / uploads / rubbish / *! / Uploads / rubbish / things / uploads / rubbish / things / *! / Uploads / rubbish / things / keep (tương tự như ví dụ trong git-scm.com/docs/gitignore ). Cấu trúc thư mục của tôi; └ README.md └ uploads / foo / bar / mất / lose.txt └ uploads / rác / stuff / giữ / keep.txt
gihanchanuka

Câu trả lời:


119

Theo phần định dạng mẫu của tài liệu gitignore :

Tiền tố tùy chọn "!" mà phủ định mẫu; bất kỳ tệp phù hợp nào bị loại trừ bởi mẫu trước đó sẽ được đưa vào lại. Không thể bao gồm lại tệp nếu thư mục mẹ của tệp đó bị loại trừ. Git không liệt kê các thư mục bị loại trừ vì lý do hiệu suất, vì vậy bất kỳ mẫu nào trên các tệp được chứa đều không có hiệu lực, bất kể chúng được xác định ở đâu. Đặt dấu gạch chéo ngược ("\") trước dấu "!" Đầu tiên đối với các mẫu bắt đầu bằng chữ "!", ví dụ: "! important! .txt".

Do đó, /uploads/rubbish/stuff/keep/mẫu thư mục mẹ đã bị loại trừ trước đây phải được phủ định hoàn toàn trước khi phủ định nội dung của nó:

#ignore everything within /uploads/ 
/uploads/*

#include everything within /uploads/rubbish/stuff/keep
!/uploads/rubbish/stuff/keep/  
!/uploads/rubbish/stuff/keep/*

Để bao gồm các thư mục con bên trong, hãy /uploads/rubbish/stuff/keep/thêm dòng thứ ba:

!/uploads/rubbish/stuff/keep/**/*

1
Bạn đang sử dụng phiên bản git nào? Có thể đó là thứ chỉ có trong một số phiên bản nhất định.

Xấu hổ. Tôi quên tôi đã đăng bình luận này. Tôi đã làm cho nó hoạt động, mặc dù. FWIW, tôi không sử dụng dấu gạch chéo ở đầu. Tôi không nhớ nếu đó là vấn đề. Tôi đang sử dụng 1.7.2.5.

Tôi có một tệp gitignore chung mà tôi đã bỏ qua tất cả tệp * .zip. Tuy nhiên, đối với một dự án cụ thể, tôi muốn bao gồm các tệp zip. Tôi đã thêm dòng này vào dự án đó .gitignorevà nó hoạt động rất tốt !:!*.zip
Jinghao Shi

Tôi thấy cần phải chỉ định rõ ràng các thư mục tùy ý cả trước và sau thư mục nhất định trong khi loại trừ thư mục và trong khi bao gồm cả thư mục con . ( Đáp án đầy đủ ).
Josiah Yoder

Phương thức này không hoạt động (kể từ git 2,25 - có thể một cái gì đó trong git đã thay đổi). Tôi đã đăng stackoverflow.com/a/60288435/295691 bên dưới để sửa lỗi.
user295691

34

Ngay cả khi bạn thêm thứ gì đó vào .gitignore, bạn có thể buộc git thêm nó vào chỉ mục

git add --force uploads/rubbish/stuff/KEEP_ME/

Tuy nhiên, "KEEP_ME" dường như là một thư mục và git thường không thích thư mục trống, vì vậy bạn có thể thêm tệp trình giữ chỗ "trình giữ chỗ" thay thế, nếu thư mục trống

git add --force uploads/rubbish/stuff/KEEP_ME/.keep_me

Vấn đề duy nhất với điều đó là ví dụ cụ thể này đề cập đến một gitignore toàn cầu mà tôi nên đề cập đến. Tôi biết tôi có thể buộc thêm các mục, nhưng tôi sẽ phải làm điều đó nếu bất kỳ mục mới nào được thêm vào, cũng như ban đầu cho mỗi kho lưu trữ mới. .Keep có đảm bảo nội dung không bị bỏ qua không?
Wil

1
Đã làm một bài kiểm tra nhỏ. Có, bạn phải sử dụng git add --forcecho mọi mục hoặc thư mục mới trong KEEP_ME. nhưng sau đó, các bản cập nhật chỉ được thêm vào (khi làm một git add -uví dụ) như thể các tệp được 'hủy bỏ qua'. Nó .keep_mekhông có tác dụng gì, nó chỉ là một tệp để git hoạt động trên thư mục.
commonpike

1
git add --forcelà giải pháp sai cho điều này. Nếu bạn di chuyển một thư mục hoặc di chuyển tệp sang một thư mục khác, theo dõi của git sẽ xóa tệp nhưng không thêm nó vào vị trí mới và bạn phải làm git add --forcelại. bằng cách bỏ qua trên một mẫu chung, git sẽ theo dõi chuyển động của tệp trong kho lưu trữ.
Merlin

Đây là giải pháp duy nhất làm việc cho tôi. Thư mục của tôi KHÔNG bị bỏ qua, nhưng tôi không thể thêm nó bằng bất kỳ cách nào. Cách này đã giải quyết nó cho tôi.
Akito

6

Đang cố gắng tìm ra cách bao gồm một thư mục cụ thể khi loại trừ tất cả các thư mục bằng loại trừ chung

**/build

nếu bạn thêm /*vào cuối loại trừ chung chung, bạn tiếp tục loại trừ tất cả các tệp bản dựng**/build/*

Sau đó, bạn thêm một dòng khác để sửa lại đường dẫn mà bạn muốn đưa vào để trông giống

!**/folder/build/* 

để lại cho chúng tôi một gitignore đọc

**/build/* 
!**/folder/build/* 

2

Câu trả lời của Buo-Ren LinJohn khá hữu ích, nhưng tôi cần kết hợp cả hai.

Khi muốn loại trừ các thư mục con khác cũng như các tệp trong các tệp tải lên, tôi thấy cần phải chỉ định rõ ràng các thư mục tùy ý trước thư mục nhất định trong khi loại trừ thư mục và trong khi bao gồm cả thư mục con

**/uploads/*
!**/uploads/rubbish/
!**/uploads/rubbish/*

Tôi cũng thấy cần phải bao gồm lại cả thư mục con và nội dung của nó một cách rõ ràng để hiển thị cả hai mục trong thư mục và các thư mục con.


Thở dài. Không có may mắn ở đây. Tại đây trong nhiều giờ. Git 2.20.1
RichieHH

@ HörmannHH Rất tiếc khi biết điều đó. Có lẽ đã đến lúc đặt một câu hỏi mới?
Josiah Yoder

2

Giải pháp được trình bày dưới dạng câu trả lời được ủng hộ nhiều nhất là không chính xác và có thể dễ dàng chứng minh như vậy.

Bắt đầu với việc bỏ qua mọi thứ trong video tải lên / *:

mkdir -p uploads/rubbish/stuff/KEEP_ME
touch uploads/a uploads/rubbish/a uploads/rubbish/stuff/a uploads/rubbish/stuff/KEEP_ME/a
echo '/uploads/*' >> .gitignore
git init
git add .
git commit -m "Initial commit"

Bây giờ bỏ qua thư mục mẹ của những thứ bị bỏ qua như trên:

echo 'uploads/rubbish/stuff/KEEP_ME/' >> .gitignore
echo 'uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Không hiển thị tệp chưa được theo dõi.

Để làm cho nó hoạt động, bạn cần bỏ qua tất cả các tệp dưới uploads/cây ( uploads/**/*, không chỉ cấp cao nhất, uploads/*) và sau đó thêm tất cả các thư mục mẹ của cây mà bạn muốn giữ

echo '/uploads/**/*' > .gitignore
echo '!/uploads/rubbish/' >> .gitignore
echo '!/uploads/rubbish/stuff' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Cái nào mang lại:

On branch master
...
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        uploads/rubbish/stuff/KEEP_ME/a

Nếu chúng ta đã sử dụng uploads/*.gitignoretrên, thì tất cả các tệp trung gian cũng sẽ được bao gồm, vì vậy, ví dụ: uploads/rubbish/asẽ hiển thị trong lệnh trạng thái ở trên.

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.