[英]Git failing to ignore files in subdirectory
My.gitignore 文件似乎並沒有忽略我想要的所有文件。
==================上下文==================
在我的 git 存儲庫中,我有幾個子目錄,類似於這個簡化的示例:
git base folder
> .gitignore
> Folder A
> Folder B
> Subfolder B0
>SubSubfolder B0a
> Files
> Subfolder B1
> SubSubfolder B1a
> Files
> File B1b.ft0
> File B1c.ft0
> File B1d.ft1
> File B1e.ft2
> Etc
我想忽略子文件夾B1
中的所有文件,除了(比如說)文件B1b.ft0
和文件B1e.ft2
。 我還想忽略 SubSubfolder B1a
和B0a
中的所有文件。 在我的.gitignore
文件(只有一個)中,我有以下幾行:
#Ignore:
B1/**
B1a/
B0a/
#Include
!B1/B1b.ft0
!B1/B1e.ft2
但是,子文件夾B1
中的所有文件都包括在內。 SubSubfolder B1a
中的文件被忽略,但是 SubSubfolder B0a
中的文件不是。
============== 嘗試的解決方案 ==============
我決定首先解決子文件夾B1
中未忽略文件的問題:
我在.gitignore
文件中嘗試了B1/
,但這忽略了那里的所有文件,包括我想要保留的文件。
我也嘗試過B1/*
和B1/*.*
,但它們都無法忽略文件夾B1
中的其他文件。
然后我嘗試手動列出我想忽略/保留在此文件夾中的所有文件。 這行得通,但是有很多文件,它們可能會改變。 我不想使用這個選項。
==================方法==================
在測試每個選項是否有效時,我使用git check-ignore -v <filename>
和git status --ignore
。 我還使用git rm --cached -r.
然后是git add -A
以清除忽略文件的存儲庫。 (子問題:我需要提交.gitignore
才能生效嗎?)
==================總結==================
我越來越對此感到困惑和煩惱,有人可以幫助我嗎? (我是否只需要在整個地方應用大量的 * 就可以自動開始工作, 就像在這個問題中一樣?)
還請解釋為什么以及如何,您的解決方案有效,而我的解決方案無效(如果您知道的話)。
經過大量測試、閱讀文檔(非常好)並詢問其他人,我終於找到了解決方案。 (是的,它確實涉及在各處噴灑大量*)。 我會盡力解釋我認為發生了什么,以及如何避免它。
Git 沒有忽略子文件夾B1
中的文件,因為它希望B1
位於根目錄中。 將 .gitignore 條目更改為**/B1/**
、 .**/B1/B1b.ft0
和.**/B1/B1e.ft2
解決了問題。
理解這個問題的關鍵是理解 .gitignore 語法的一些奇怪之處。 幸運的是,沒有太多要學習的東西,即使其中一些令人沮喪地晦澀難懂——例如,您可能知道 gitignore 文件是向下讀取的,這會導致這種行為:
foo 沒有被忽略 |
foo 被完全忽略 |
---|---|
富 |
!富 |
我的問題與 .gitignore 語法中另一個神秘的微妙之處有關:它如何解析文件路徑。 gitignore 目錄分隔符是/
,但是根據它在一行中的位置,或者有多少,它的行為方式完全不同:
對於只有一個/
的條目:
/ 在行尾,如foo/ |
/ 在行的中間,如foo/bar |
/ 在行首,如/foo |
---|---|---|
Git 忽略每個名為foo 的目錄,無論它有多深的子目錄。 |
Git 忽略文件路徑<.gitignore_directory>/foo/ 中名為bar 的任何文件夾和文件。 名為foo/bar 的文件夾(或文件)只有在具有特定文件路徑的情況下才會被忽略,即該路徑從與 .gitignore 文件相同的目錄開始。 |
Git 忽略任何名為foo 的文件和文件夾,但前提是它們與 .gitignore 文件位於同一目錄中。 |
對於有多個/
的條目,規則是上述規則的組合。 幾個例子說明:
/foo/ |
foo/bar/ |
/foo/bar |
---|---|---|
此模式僅匹配一項:與 .gitignore 位於同一文件夾中的子文件夾,名為foo 。 (當然,里面的所有東西也都被忽略了。) |
此模式也只匹配一個項目,即在文件夾foo 中找到的名為bar 的子子文件夾,它本身必須是也包含 .gitignore 文件的文件夾的子文件夾。 |
此模式與中間示例中的模式相同,除了它還可以忽略名為bar 的文件,而不僅僅是目錄。 |
在上述所有情況下,任何被忽略的目錄foo
中的文件和子目錄都不能被例如!foo/bar
忽略。
狡猾的微妙之處在於,像foo/
/
的行末尾的 / 將導致任何名為foo
的目錄被忽略,無論其深度如何,但在/
之后放置任何字符(包括通配符!),或放置任何其他/
在同一行中將意味着它僅與找到 .gitignore 的路徑相關。 那么,如何才能忽略子目錄中的文件呢?
解決方法是更好地使用通配符。 .gitignore 語法中有三個通配符:
?
- 匹配 1 個或多個字符,除了/
。 幾乎只用於文件名匹配。*
- 匹配 0 個或多個字符,除了/
**
- 匹配 0 個或多個字符,包括/
。 ?
或*
可用於忽略目錄中的所有文件,但不能忽略子文件夾。 如果foo
與 .gitignore 位於同一目錄中,則以下示例都將忽略子目錄foo
中的所有文件。
foo/*
foo/?
這不會忽略名稱為 0 字符的文件。 但是,請注意,這些不會忽略例如<.gitignore_directory>/filepath/foo
中的文件。
由於**
匹配目錄,它可以像這樣解決上述問題: **/foo/
。 即使/
之后有一個非空白字符,這也會忽略所有名為foo
的目錄和子目錄,因為**/
匹配所有文件路徑。
**/foo/?
忽略任何目錄foo
中的所有命名文件。foo/**/bar.txt
忽略名為foo
的文件夾中任意深度的每個名為bar.txt
的文件,其中foo
位於<.gitignore_directory>
中。**/foo/**
忽略每個目錄foo
中的所有內容,但不忽略目錄本身,因此我可以取消忽略其中的 select 幾個文件!耶。 我的問題得到了回答——幾乎。
對於 my.gitignore 中的條目忽略 SubSubfolder B0a
,我實際上有一些與我所要求的略有不同的東西。 在我的實際項目中, B0a
被稱為.generated_files
。 我不完全確定 git 會如何看待以點開頭的 .gitignore 條目,所以我在它前面加上了一個斜杠,如下所示: /.generated_files/
。 (我在寫問題時忘記了這一點。)正如我現在所知,這導致 git 只期望它在根目錄中,因此錯過了它。 我還了解到,如果條目以.
.
盡管在我的情況下它沒有引起問題,但我還發現 .gitignore 文件中的條目將同時匹配文件和文件夾。 因此,如果您有一個名為 foo 的文件和一個名為 foo 的文件夾,將foo
放入 .gitignore 會導致它們都被忽略。
希望這個答案對您有所幫助,恐怕閱讀官方文檔可能會更容易理解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.