[英]Git sparse checkout with exclusion
根據這個線程,Git 的sparse-checkout
功能中的排除應該被實現。 是嗎?
假設我有以下結構:
papers/
papers/...
presentations/
presentations/heavy_presentation
presentations/...
現在我想從結帳中排除presentations/heavy_presentation
,同時將 rest 留在結帳中。 我還沒有設法讓它運行。 正確的語法是什么?
遺憾的是,上述方法都不適合我,所以我花了很長時間嘗試不同的sparse-checkout
文件組合。
就我而言,我想跳過帶有 IntelliJ IDEA 配置的文件夾。
這是我所做的:
運行git clone https://github.com/myaccount/myrepo.git --no-checkout
運行git config core.sparsecheckout true
使用以下內容創建.git\info\sparse-checkout
!.idea/*
!.idea_modules/*
/*
運行 'git checkout --' 以獲取所有文件。
使其工作的關鍵是在文件夾名稱之后添加/*
。
我有 git 1.9
我本來希望像下面這樣的工作:
/*
!presentations/heavy_presentation
但事實並非如此。 我確實嘗試了許多其他組合。 我認為排除沒有正確實施,並且周圍存在錯誤(仍然)
就像是:
presentations/*
!presentations/heavy_presentation
確實有效,您將獲得沒有heavy_presentation文件夾的演示文件夾。
因此,解決方法是明確包含其他所有內容。
在 Git 2.25(2020 年第一季度)中,稀疏簽出工作樹的管理獲得了專用的“ sparse-checkout
出”命令。
Git 2.37(2022 年第三季度)將錐形模式設為默認模式。 請參閱此答案的最后一部分。
首先,這是一個擴展示例,從使用--filter
選項的快速克隆開始:
git clone --filter=blob:none --no-checkout https://github.com/git/git
cd git
git sparse-checkout init --cone
# that sets git config core.sparseCheckoutCone true
git read-tree -mu HEAD
使用錐形選項(詳細/記錄在下面)意味着您的.git\info\sparse-checkout
將包含以下開頭的模式:
/*
!/*/
含義:只有頂級文件,沒有子文件夾。
如果你不想要top file,你需要避免cone模式:
# Disablecone mode in .git/config.worktree
git config core.sparseCheckoutCone false
# remove .git\info\sparse-checkout
git sparse-checkout disable
# Add the expected pattern, to include just a subfolder without top files:
git sparse-checkout set /mySubFolder/
# populate working-tree with only the right files:
git read-tree -mu HEAD
詳細說明:
(請參閱Derrick Stolee的“ 使用sparse-checkout
將您的 monorepo 縮小到大小”中的更多信息)
因此,不僅排除子文件夾確實有效,而且使用稀疏結帳的“錐形”模式(使用 Git 2.25)可以更快地工作。
請參閱Ed Maste ( emaste
)的提交 761e3d2 (2019 年 12 月 20 日)。
請參閱提交 190a65f (2019 年 12 月 13 日),並提交 cff4e91 、 提交 416adc8 、 提交 f75a69f 、 提交 fb10ca5 、 提交 99dfa6f 、 提交 e091228 、 提交 e9de487 、 提交4dcd4de 、 提交 eb42fec 、 提交 af09ce2 、 提交 79321e 8 、 提交 7 、 提交7 7bffca9 , 提交 f6039a9 , 提交 d89f09c , 提交 bab3c35 , 提交 94c0956 (2019 年 11 月 21 日),作者Derrick Stolee ( derrickstolee
) 。
請參閱Jeff Hostetler ( Jeff-Hostetler
)的提交 e6152e3 (2019 年 11 月 21 日)。
(由Junio C Hamano -- gitster
--在提交 bd72a08中合並,2019 年 12 月 25 日)
sparse-checkout
: 添加“錐形”模式簽字人:Derrick Stolee
隨着索引中模式數量和條目數量的增長,稀疏簽出功能可以具有二次性能。
如果有 1,000 個模式和 1,000,000 個條目,那么這個時間可能非常重要。創建一個新的布爾配置選項core.sparseCheckoutCone ,以指示我們希望稀疏結帳文件包含一組更有限的模式。
這是一個與core.sparseCheckout
分開的配置設置,以避免通過引入三態選項來破壞舊客戶端。
config
手冊頁包括:
`core.sparseCheckoutCone`:
啟用稀疏結帳功能的“錐形模式”。
當 sparse-checkout 文件包含一組有限的模式時,這種模式提供了顯着的性能優勢。
錐形圖案套裝
完整的模式集允許任意模式匹配和復雜的包含/排除規則。
在更新索引時,這些可能會導致O(N*M)
模式匹配,其中N
是模式數,M
是索引中的路徑數。 為了解決這個性能問題,啟用core.spareCheckoutCone
時允許使用更受限制的模式集。錐形模式集中接受的模式是:
- 遞歸:包含目錄內的所有路徑。
- 父級:包含一個目錄中的所有文件。
除了上述兩種模式外,我們還期望根目錄下的所有文件都包括在內。 如果添加了遞歸模式,則所有前導目錄都將添加為父模式。
默認情況下,當運行
git sparse-checkout init
時,根目錄被添加為父模式。 此時,sparse-checkout 文件包含以下模式:/* !/*/
這表示“在根目錄中包含所有內容,但在根目錄下沒有兩層”。
如果我們隨后將文件夾A/B/C
添加為遞歸模式,則文件夾A
和A/B
將添加為父模式。
生成的稀疏簽出文件現在是/* !/*/ /A/ !/A/*/ /A/B/ !/A/B/*/ /A/B/C/
在這里,順序很重要,因此負面模式會被文件中較低的正面模式覆蓋。
如果
core.sparseCheckoutCone=true
,那么 Git 將解析期望這些類型的模式的稀疏檢出文件。
如果模式不匹配,Git 會發出警告。
如果模式確實符合預期的格式,那么 Git 將使用更快的基於散列的算法來計算包含在sparse-checkout
中。
所以:
sparse-checkout
:初始化並設置為錐形模式幫助人:Eric Wong
幫助者:約翰內斯辛德林
簽字人:Derrick Stolee
為了使錐形模式集易於使用,請更新“
git sparse-checkout (init|set)
”的行為。將“
--cone
”標志添加到“git sparse-checkout init
”以設置配置選項“core.sparseCheckoutCone=true
”。在錐形模式下運行“
git sparse-checkout set
”時,用戶只需要提供遞歸文件夾匹配的列表。 Git 將自動為前導目錄添加必要的父匹配項。
請注意, --cone
選項僅記錄在 Git 2.26(2020 年第一季度)中
(由Junio C Hamano -- gitster
--在提交 ea46d90中合並,2020 年 2 月 5 日)
doc
:sparse-checkout
: 提到--cone
選項簽字人:Matheus Tavares
委托方:Derrick Stolee
在af09ce2 ("
sparse-checkout
: init and set in cone mode", 2019-11-21, Git v2.25.0-rc0 -- merge ) 中,'----cone
' 選項被添加到'git sparse-checkout
init' .在
git sparse-checkout
中記錄它:
那包含着:
當提供
--cone
時,還設置了core.sparseCheckoutCone
設置,允許使用有限的模式集獲得更好的性能。
(上面介紹的“一組模式”,在這個答案的“ CONE PATTERN SET
”部分)
這種新的“錐形”模式會快多少?
sparse-checkout
: 使用 hashmaps 進行錐形模式幫助人:Eric Wong
幫助者:約翰內斯辛德林
簽字人:Derrick Stolee
sparse-checkout 中的“錐形模式”選項允許的父模式和遞歸模式具有足夠的限制性,我們可以避免使用正則表達式解析。 一切都基於前綴匹配,因此我們可以使用哈希集來存儲稀疏簽出文件中的前綴。 檢查路徑時,我們可以從路徑中刪除路徑條目並檢查哈希集是否完全匹配。
作為測試,我為 Linux 存儲庫創建了一個錐形模式稀疏簽出文件,該文件實際上包含每個文件。 這是通過獲取 Linux 存儲庫中的每個文件夾並在此處創建模式對來構建的:
/$folder/ !/$folder/*/
這導致了一個稀疏的簽出文件 sith 8,296 個模式。
在此文件上運行“git read-tree -mu HEAD”具有以下性能:core.sparseCheckout=false: 0.21 s (0.00 s) core.sparseCheckout=true : 3.75 s (3.50 s) core.sparseCheckoutCone=true : 0.23 s (0.01 s)
根據
trace2
性能跟蹤,上面括號中的時間對應於第一次clear_ce_flags()
調用所花費的時間。雖然此示例是人為設計的,但它演示了這些模式如何減慢稀疏結帳功能。
和:
sparse-checkout
:在錐形模式下尊重 core.ignoreCase簽字人:Derrick Stolee
當用戶在錐形模式下使用 sparse-checkout 功能時,他們使用“
git sparse-checkout set <dir1> <dir2> ...
”添加模式或使用“--stdin
”逐行提供目錄在標准輸入上。
這種行為自然看起來很像用戶鍵入“git add <dir1> <dir2> ...
”的方式如果啟用
core.ignoreCase
,那么“git add
”將使用不區分大小寫的匹配來匹配輸入。
對sparse-checkout
功能執行相同的操作。在
unpack_trees()
期間更新 skip-worktree 位時執行不區分大小寫的檢查。 這是通過更改散列算法和散列映射比較方法以可選地使用不區分大小寫的方法來完成的。啟用此選項后,散列算法的性能成本會很小。
為了梳理出最壞的情況,以下是在具有深層目錄結構的 repo 上運行的:git ls-tree -d -r --name-only HEAD | git sparse-checkout set --stdin
'set' 命令在禁用或啟用
core.ignoreCase
的情況下進行計時。
對於歷史悠久的回購,數字是core.ignoreCase=false: 62s core.ignoreCase=true: 74s (+19.3%)
為了重現性,Linux 內核存儲庫上的等效測試具有以下數字:
core.ignoreCase=false: 3.1s core.ignoreCase=true: 3.6s (+16%)
現在,這並不是一個完全公平的比較,因為大多數用戶將使用更淺的目錄來定義他們的稀疏錐體,以及eb42feca97的性能改進(“unpack-trees: hashless in cone mode”2019-11-21,Git 2.25- rc0) 可以消除大部分哈希成本。 要進行更實際的測試,請從
ls-tree
命令中刪除“-r
”以僅存儲第一級目錄。
在這種情況下,Linux 內核存儲庫在每種情況下都需要 0.2-0.25 秒,而深層存儲庫在每種情況下都需要 1 秒,正負 0.05 秒。因此,我們可以證明這種變化的成本,但它對任何合理的稀疏結賬錐都不重要。
在 Git 2.25(2020 年第一季度)中,“ git sparse-checkout
list”子命令學會了在“錐形”模式生效時以更簡潔的形式給出其輸出。
請參閱Derrick Stolee ( derrickstolee
) 的commit 4fd683b和commit de11951 (2019 年 12 月 30 日)。
(由Junio C Hamano -- gitster
--在提交 c20d4fd中合並,2020 年 1 月 6 日)
sparse-checkout
:以錐形模式列出目錄簽字人:Derrick Stolee
當
core.sparseCheckoutCone
啟用時,“git sparse-checkout set
”命令將目錄列表作為輸入,然后創建稀疏簽出模式的有序列表,以便遞歸包含這些目錄,並且父目錄中的所有同級條目都是也包括在內。
列出模式不如目錄本身對用戶友好。在錐形模式下,只要模式與預期的錐形模式類型匹配,將“
git sparse-checkout list
”的輸出更改為僅顯示創建模式的目錄。通過此更改,以下管道命令不會更改工作目錄:
git sparse-checkout list | git sparse-checkout set --stdin
唯一不起作用的情況是
core.sparseCheckoutCone
為true
,但 sparse-checkout 文件包含與錐形模式的預期模式類型不匹配的模式。
最近在此版本中添加的代碼以在稀疏錐模式下移動到索引中同一目錄中的條目之外的條目,沒有計算錯誤跳過的條目數,已在 Git 2.25.1 中更正(2020 年 2 月)。
請參閱Junio C Hamano ( gitster
)的提交 7210ca4 (2020 年 1 月 27 日)。
請參閱Derrick Stolee 通過 GitGitGadget (``) 提交的 4c6c797 (2020 年 1 月 10 日)。
(由Junio C Hamano -- gitster
--在提交 043426c中合並,2020 年 1 月 30 日)
unpack-trees
: 正確計算結果計數報告人:約翰內斯·辛德林
簽字人:Derrick Stolee
clear_ce_flags_dir()
方法處理公共目錄中的緩存條目。 返回的int
是該目錄處理的緩存條目數。
在錐模式下使用稀疏簽出功能時,我們可以跳過完全包含或完全排除的目錄中的條目的模式匹配。eb42feca ("
unpack-trees
: hashless in cone mode", 2019-11-21, Git v2.25.0-rc0 -- merge列在第 #0 批中) 引入了這個性能特性。 舊機制依賴於調用clear_ce_flags_1()
返回的計數,但新機制通過從“cache
”中減去“cache_end
”來計算行數,以找到范圍的大小。
然而,等式是錯誤的,因為它除以sizeof(struct cache_entry *)
。 這不是指針算術的工作原理!為 2.25.0 版本做准備的適用於 Windows 的 Git 的覆蓋構建發現此問題並帶有警告:
Pointer differences, such as `cache_end` - cache, are automatically scaled down by the size (8 bytes) of the pointed-to type (struct `cache_entry` *). Most likely, the division by sizeof(struct `cache_entry` *) is extraneous and should be eliminated.
這個警告是正確的。
在 Git 2.26(2020 年第一季度)中,稀疏結賬功能中的一些粗糙邊緣,尤其是在錐形模式周圍,已被清理干凈。
參見提交F998A3F , 提交D2E65F4 , 提交E53FFE2 , 提交E55682E , COMMAR BD64DE4 , 提交D585F0E , 提交4F52C2C , 提交9ABC60F (2020年1月31日)和提案9E6D3E , 提交41DE0C6 , 提交47DC6 ,dist 47DC11, dist 47DC11 , dist 32 , 2020 年 1 月),由Derrick Stolee ( derrickstolee
) 撰寫。
請參閱Jeff King ( peff
)的commit 7aa9ef2 (2020 年 1 月 24 日)。
(由Junio C Hamano -- gitster
--在提交 433b8aa中合並,2020 年 2 月 14 日)
sparse-checkout
:修復錐模式行為不匹配報告人:芬恩·布萊恩特
簽字人:Derrick Stolee
稀疏檢出功能中特殊的“錐形模式”的目的是始終匹配與禁用錐形模式時相同的稀疏檢出文件匹配的相同模式。
當在錐形模式下將文件路徑提供給“
git sparse-checkout
set”時,錐形模式會不正確地將文件匹配為遞歸路徑。
設置跳過工作樹位時,文件不期望MATCHED_RECURSIVE
響應,因此這些被排除在匹配錐之外。通過在
MATCHED
之外檢查MATCHED_RECURSIVE
並添加防止回歸的測試來修復此錯誤。
該文檔現在包括:
啟用
core.sparseCheckoutCone
時,輸入列表被視為目錄列表,而不是稀疏檢出模式。
該命令將模式寫入 sparse-checkout 文件以包括包含在這些目錄中的所有文件(遞歸地)以及作為祖先目錄的兄弟的文件。
輸入格式與git ls-tree --name-only
的輸出相匹配。 這包括將以雙引號 ("
) 開頭的路徑名解釋為 C 風格的帶引號的字符串。
在 Git 2.26(2020 年第一季度)中,“ git sparse-checkout
”學習了一個新的“ add
”子命令。
請參閱 Derrick Stolee (derrickstolee) 的提交 6c11c6a (2020 年 2 月 20 日)和提交 ef07659 、 提交 2631dc8 、 提交 4bf0c06 、 提交 6fb705a (2020 年 2 月 11 日derrickstolee
。
(由Junio C Hamano -- gitster
--在提交 f4d7dfc中合並,2020 年 3 月 5 日)
sparse-checkout
:創建“添加”子命令簽字人:Derrick Stolee
使用稀疏結賬功能時,用戶可能希望逐步增長其稀疏結賬模式集。
允許使用新的“添加”子命令添加模式。這與“set”子命令沒有太大區別,因為我們仍然希望允許“
--stdin
”選項並將輸入解釋為在錐模式下的目錄和模式,否則。在圓錐模式下,我們正在增長圓錐。
當A/B
已經是錐體中的目錄時,這實際上可能會減少添加目錄A
時的模式集。 測試不同的案例:兄弟姐妹、父母、祖先。當不處於錐形模式時,我們只能假設模式應該附加到 sparse-checkout 文件中。
和:
sparse-checkout
:使用 Windows 路徑簽字人:Derrick Stolee
使用 Windows 時,用戶可以運行 '
git sparse-checkout
set A\B\C' to add the Unix-style path
A/B/C` 添加到他們的稀疏檢出模式中。在我們將字符串“
A/B/C
”添加到遞歸哈希集之前,規范化輸入路徑會將反斜杠轉換為斜杠。
稀疏簽出模式長期以來一直被禁止排除所有路徑,留下一棵空的工作樹。
在 Git 2.27(2020 年第二季度)中,這一限制已被解除。
請參閱Derrick Stolee ( derrickstolee
) 的提交 ace224a (2020 年 5 月 4 日)。
(由Junio C Hamano -- gitster
--在提交 e9acbd6中合並,2020 年 5 月 8 日)
sparse-checkout
:停止阻止空工作目錄報告人:Lars Schneider
簽字人:Derrick Stolee
刪除更新稀疏結帳時的錯誤條件會留下一個空的工作目錄。
此行為是在9e1afb167中添加的(“稀疏結帳:禁止空工作樹”,2009-08-20,Git v1.7.0-rc0 -- 合並)。
該評論已添加到a7bc906f2中(“添加解釋為什么我們不允許稀疏結帳到空工作樹”,2011-09-22,Git v1.7.8-rc0 -- 合並)以響應84563a624中的“可疑”評論(“
[
unpack-trees.c](https
):外觀修復”,2010-12-22,Git v1.7.5-rc0 - - 合並)。使用最近的“錐形模式”和“
git sparse-checkout init [--cone]
”命令,通常設置一個合理的sparse-checkout模式集/* !/*/
僅匹配根目錄下的文件。 如果存儲庫沒有這樣的文件,那么他們的“
git sparse-checkout init
”命令將會失敗。現在我們希望這是一種常見的模式,我們不應該讓命令在空工作目錄上失敗。
如果結果令人困惑,則用戶可以使用“git sparse-checkout disable
”或“git sparse-checkout set
”來恢復。 這在使用錐形模式時尤其簡單。
使用 Git 2.37(2022 年第三季度),棄用稀疏結帳功能的非錐形模式。
請參閱Elijah Newren ( newren
)的提交5d4b293 、提交a8defed 、 提交 72fa58e 、 提交 5d295dc 、 提交 0d86f59 、 提交 71ceb81 、 提交 f69dfef 、 提交 2d95707 、 提交 dde1358 (2022 年 4 月 22 日)。
(由Junio C Hamano -- gitster
--在提交 377d347中合並,2022 年 6 月 3 日)
sparse-checkout
: 將 --cone 設為默認值簽字人:以利亞·紐倫
將錐形模式設為默認模式,並相應地更新文檔。
git config
現在包含在其手冊頁中:
通過將此變量設置為“假”,可以請求“非錐形模式”以允許指定更靈活的模式。
git sparse-checkout
現在包含在其手冊頁中:
除非
core.sparseCheckoutCone
明確設置為false
,否則 Git 將解析期望這些類型的模式的 sparse-checkout 文件。 如果模式不匹配,Git 會發出警告。 如果模式確實與預期的格式匹配,那么 Git 將使用更快的基於哈希的算法來計算稀疏結賬中的包含。
和:
git-sparse-checkout.txt
:錐形模式默認的措辭更新簽字人:以利亞·紐倫
既然錐形模式是默認設置,我們希望關注設置/添加的參數是目錄而不是模式,並且提供一個更早的提示可能是有意義的,即來自前導目錄的文件也被包含在內。
git sparse-checkout
現在包含在其手冊頁中:
默認情況下,輸入列表被視為目錄列表,與
git ls-tree -d --name-only
的輸出匹配。
這包括將以雙引號 ("
) 開頭的路徑名解釋為 C 風格的帶引號的字符串。請注意,指定目錄下的所有文件(任何深度)都將包含在稀疏檢出中,以及作為給定目錄或其任何祖先的兄弟文件的文件(有關更多詳細信息,請參見下面的“CONE PATTERN SET”) .
過去,這不是默認設置,需要指定
--cone
或啟用core.sparseCheckoutCone
。
我有同樣的問題。 我用類似的東西修復了它:
!presentations/heavy_presentation
presentations/*
我如何理解它的工作原理:它逐條讀取文件規則。 如果包含某些內容,它將包含包含該單詞的所有路徑,並且在稀疏結帳結束之前它不會再更改其狀態。 如果您在包含之前添加排除規則,我認為它將首先刪除文件,然后將所有文件標記為包含。
我不完全確定,這是我根據我的經驗所設想的並且一直在為我工作。 我希望它會幫助某人。
簡短的回答:
git sparse-checkout set /* !/presentations/heavy_presentation/
git sparse-checkout init [--cone]
--cone
選項:僅與少數模式/小型 repo 無關,但通常用於加速。 需要特定規范的模式順序,如sparse-checkout
/ CONE PATTERN SET
文檔所述)。 稍后也可以通過以下方式介紹:
git config core.sparseCheckoutCone true
使用 Git 2.37(2022 年 6 月發布)就容易多了。 要排除一個文件夾和一些與掩碼匹配的文件(只是為了提供比問題要求更通用/有用的示例),我這樣做了:
git sparse-checkout set --no-cone "/*" "!/folder/" "!/path/to/dist/*.map"
這非常直觀(好吧,在花了幾個小時找到這個公式之后)。 該folder
完全消失, path/to/dist
文件夾中的所有*.map
文件也消失了。 沒有其他東西被觸及。
幾個重要的位:
如果它有任何未暫存/忽略的文件,我強烈建議在開始之前備份您的本地存儲庫。 我的第一次嘗試(沒有“/*”等)很可怕——好像我的大部分數據都消失了。 下面的#5 似乎有助於恢復一切,但你永遠無法確定是否有大回購...
"/*"
是神奇的一塊。 它要求 GIT 包括以后未排除的所有內容。 沒有它就無法工作(刪除大量回購內容)。 它必須在列表中排在第一位!
您可能需要set +H
才能使命令通過(bash 將!
視為特殊命令)。 然后set -H
以恢復默認的 bash 行為。
我建議通過鍵入以下內容來檢查 GIT 對您使用的路徑的解釋:
cat.git/info/sparse-checkout
在為我的案例找到“公式”之前,我多次對結果感到驚訝(例如,參見#6)。
運行命令后執行ls
一些回購路徑。 如果 go 錯誤,那么git sparse-checkout disable
應該可以恢復所有丟失的文件。 至少這對我來說效果很好。
最好為所有路徑使用引號。 在 "/*" 中尤為重要。 這是我在不帶引號的情況下使用 git/info/sparse-checkout 時得到的內容(每個都來自新行:由於某種原因,stackoverflow 的格式不太好):
/bin /dev /etc /home /lib /lib64 /opt /proc /root /run /sbin /tmp /usr /var.folder/ !path/to/dist/*.map
你可以想象這些模式不是我想說的......
注意到處都是斜杠( "!/folder/"
)。 如果省略 ( "!folder/"
),那么具有這樣名稱的文件夾將在層次結構中的所有位置被刪除,而不僅僅是在頂層。
--no-cone
現在很重要。 這是過去的默認模式,當通過 inte.net 查看舊建議時,這可能會引起很多混亂! 如果您想更好地理解事物, GIT 文檔對此進行了詳細說明。
希望這對某人有幫助。
更新:在排除的路徑中添加了前導斜杠,如上面#7 中所述。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.