簡體   English   中英

如何排除除了所有頂級點文件和子目錄之外的所有內容?

[英]How can I exclude everything but all top-level dot files and a subdirectory?

在使用Git跟蹤我的基本配置文件時,我在編寫.gitignore文件時遇到問題。

我的目標是在我的存儲庫中包含兩件事:

  1. 我的用戶目錄中的所有dotfiles ~/ ,這是我的gitroot。
  2. 隱藏文件夾~/.vim/bundle

到目前為止,我嘗試了以下方法,但無濟於事。

的.gitignore:

# Ignore everything
*

# Include top-level dot files.
!/.*

# Include vim plugins
!/.vim/bundle/*

這只會在我的gitroot中處理dotfiles。

注意。

我的gitroot是我的用戶目錄~/

更新

在以下表格中, ~/.vim文件夾暫存:

# Ignore everything
*

# Include top-level dot files.
!/.*

# Include vim plugins
!/.vim

所以,我猜我應該以某種方式表達路徑名/.vim/bundle

TL; DR

你正在遇到一個破壞你的用例的優化:一旦Git決定不查看目錄,它就永遠不會該目錄中找到它將添加的文件。 要修復它,您至少還需要一個規則:

!/.vim/bundle/

您可以使用其他規則來阻止所有優化:

!*/

這也應該使問題消失(以更深入的搜索為代價,導致很多緩慢)。

你有一個良好的開端,但你遇到了一個有問題的優化(我想,Git人員試圖修復)。 我們還必須假設索引中當前的內容(也就是暫存區域),因為索引內容會影響Git掃描目錄的方式。 讓我們假設你的索引真的是空的,因為它會在git init a new repository之后。 這樣,由於沒有現有的索引條目,它們不會影響Git的正常目錄掃描過程。

假設這里的工作樹有名為README.profile文件,以及目錄d/.vim/ 你的.gitignore有三條規則。 第一個是正規則(“忽略”),第二個和第三個是否定規則(“不要忽略”)。 規則本身,減去! , 是:

*
/.*
/.vim/bundle/*

現在當Git正在使用README它首先檢查* ,匹配,然后是/.* ,它們不匹配,然后是/.vim/bundle/* ,它們也不匹配。 最后一個匹配規則生效:那個*表示“忽略”,因此README將被忽略。 另一方面,文件.profile是前兩個規則,所以第二個規則適用,它說! 所以.profile是未跟蹤但未被忽略的: git status會對此抱怨,並且git add . 將它添加到索引。

現在讓我們考慮如何處理d/.vim/ 這些目錄,而不是文件:Git是救不了他們,但它可能會或可能不會是保存其中的文件。 為此,它必須閱讀並檢查其中的所有文件名。 這是非常昂貴的,所以Git將首先嘗試完全跳過該目錄。 這是我提到的有問題的優化。

無論如何, d/匹配第一條規則但不匹配其他兩條規則。 這意味着Git的獲取跳過讀d/完全 git status不會抱怨它, git add也不會掃描它。

到目前為止,我們都很好。 .vim/匹配第二條規則(但不是第三條規則),所以Git會查看.vim

讓我們說.vim/包含.netrwhistafter/bundle/ ,也許還有其他一些目錄。 .netrwhist匹配* ,與/.*不匹配,與/.vim/bundle/*不匹配,因此*匹配適用並被忽略。 after/目錄匹配* ,與/.*不匹配,與/.vim/bundle/*不匹配,因此未讀。

現在我們遇到了問題: .vim/bundle/是一個目錄。 Git根據.gitignore指令檢查此路徑名。 bundle/匹配* .vim/bundle/.*不匹配,因為這意味着頂級文件 ; .vim/bundle/是一個目錄,不在頂層。 路徑也不符第三指令/.vim/bundle/* ,這就要求這是的文件或目錄.vim/bundle/ 所以唯一匹配的指令是第一個,而.vim/bundle就像d/ did一樣未讀

這意味着Git永遠不會 .vim/bundle/找到任何文件或目錄。 它永遠不會檢查任何文件(如果有的話),它從不掃描子目錄中的更多文件。 你需要強制Git查看.vim/bundle/

索引中的條目變化很大

如果索引中的某個文件的路徑名是.vim/bundle/a/b ,則Git將必須掃描目錄.vim/bundle/a 所以放在那里的任何文件都會出現! 我不確定Git是否會在這種情況下跳過.vim/bundle/本身(理論上它可以,但我不認為它在實踐中有效)。 一旦索引中有文件路徑,就會跟蹤該文件,並且它在任何.gitignore存在都變得無關緊要。

但是,請注意,索引中的文件現在不一定在明天的索引中,如果您刪除它們,或者如果您檢查其他提交文件不存在的那些文件。 整件事情有點棘手。

前導斜杠表示相對於gitroot的絕對路徑; 刪除它以選擇所有dotfiles。

# Ignore everything
*

# Include all dot files.
!.*

# Include vim plugins
!/.vim/bundle/*

這是一個方便,簡潔的參考示例。

您需要.gitignore然后提交.gitignore才能使更改生效。 令人高興的是,您可以反復git commit --amend並進行進一步更改,以保持歷史記錄清潔,直到您擁有所需內容。

作為一個模糊相關的旁邊,我經常看到有人試圖將“項目中任意位置的文件folder ”與/folder匹配,它應該是**/folder

我從這個答案中受到啟發,寫下以下適當的.gitignore文件。 :)

# We use a whitelisting approach to track certain configuration files.
# Apparently, this needs to be done recursively because git can't see past a directory that is not
# included. Hence, if we want to include a subdirectory, we first need to include its upper
# directory, by the whitelisting procedure as shown below.

# Exclude all files and non-hidden directories.
/*

# Include all dotfiles.
!.*

# Exclude all hidden directories.
.*/

# Include the upper directory.
!/.vim

# Exclude all files and non-hidden directories.
/.vim/*

# Include the vim plugins.
!/.vim/bundle

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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