[英]How can I exclude everything but all top-level dot files and a subdirectory?
在使用Git跟蹤我的基本配置文件時,我在編寫.gitignore文件時遇到問題。
我的目標是在我的存儲庫中包含兩件事:
~/
,這是我的gitroot。 ~/.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
。
你正在遇到一個破壞你的用例的優化:一旦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/
包含.netrwhist
, after/
, 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.