簡體   English   中英

Git 無法忽略子目錄中的文件

[英]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 B1aB0a中的所有文件。 在我的.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 幾個文件!

耶。 我的問題得到了回答——幾乎。

關於子子文件夾 B0a:

對於 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM