?
本文檔使用 php中文網(wǎng)手冊(cè) 發(fā)布
git-read-tree - 將樹信息讀入索引
git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--index-output=<file>] [--no-sparse-checkout] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])
將<tree-ish>給出的樹信息讀入索引,但實(shí)際上并不更新它“緩存”的任何文件。(請(qǐng)參閱:git-checkout-index [1])
可選地,它可以將一棵樹合并到索引中,用該-m
標(biāo)志執(zhí)行快進(jìn)(即2路)合并或3路合并。與-m
該-u
標(biāo)志一起使用時(shí),該標(biāo)志還會(huì)使用合并結(jié)果更新工作樹中的文件。
瑣碎的合并是由git read-tree
它自己完成的。git read-tree
返回時(shí),只有相互沖突的路徑處于未合并狀態(tài)。
-m
執(zhí)行合并,而不僅僅是讀取。如果您的索引文件中有未合并的條目,則該命令將拒絕運(yùn)行,表明您尚未完成之前的合并。
--reset
與-m相同,只是未合并的條目會(huì)被丟棄而不是失敗。
-u
合并成功后,使用合并結(jié)果更新工作樹中的文件。
-i
通常,合并需要索引文件以及工作樹中的文件與當(dāng)前頭提交保持同步,以避免丟失本地更改。該標(biāo)志禁止使用工作樹進(jìn)行檢查,并且用于創(chuàng)建與當(dāng)前工作樹狀態(tài)不直接相關(guān)的樹合并到臨時(shí)索引文件中時(shí)使用。
-n --dry-run
檢查命令是否會(huì)出錯(cuò),而不更新索引或工作樹中的文件是否真實(shí)。
-v
顯示檢查文件的進(jìn)度。
--trivial
git read-tree
只有在沒(méi)有文件級(jí)合并所需的情況下,才會(huì)限制三路合并,而不是解決合并的問(wèn)題,并在索引中留下沖突的文件。
--aggressive
通常是通過(guò)三種方式合并,通過(guò)git read-tree
解決真正微不足道案件的合并,并使其他案例在索引中未解決,從而使瓷器可以實(shí)施不同的合并策略。該標(biāo)志使命令可以在內(nèi)部解決更多的情況:
當(dāng)一方移除路徑而另一方離開(kāi)未修改的路徑時(shí)。決議是消除這條道路。
當(dāng)雙方都消除一條路徑時(shí)。決議是消除這條道路。
當(dāng)雙方相同地添加路徑時(shí)。決議是增加這條道路。
--prefix=<prefix>/
保持當(dāng)前的索引內(nèi)容,并讀取目錄at下的命名樹ish的內(nèi)容<prefix>
。該命令將拒絕覆蓋原始索引文件中已經(jīng)存在的條目。請(qǐng)注意,該<prefix>/
值必須以斜杠結(jié)尾。
--exclude-per-directory=<gitignore>
使用-u
和-m
選項(xiàng)運(yùn)行命令時(shí),合并結(jié)果可能需要覆蓋當(dāng)前分支中未跟蹤的路徑。該命令通常拒絕繼續(xù)合并以避免丟失這樣的路徑。但是這個(gè)安全閥有時(shí)會(huì)阻礙。例如,經(jīng)常會(huì)發(fā)生另一個(gè)分支添加了一個(gè)文件,該文件曾經(jīng)是分支中生成的文件,并且在您運(yùn)行后,make
但在運(yùn)行make clean
刪除生成的文件之前嘗試切換到該分支時(shí)觸發(fā)安全閥。該選項(xiàng)告訴命令讀取每個(gè)目錄的排除文件(通常.gitignore
),并允許覆蓋這樣一個(gè)未追蹤但明確忽略的文件。
--index-output=<file>
除了將結(jié)果$GIT_INDEX_FILE
寫入外,將結(jié)果索引寫入指定文件。在命令正在運(yùn)行時(shí),原始索引文件被鎖定,其機(jī)制與往常一樣。該文件必須允許從在通常索引文件旁邊創(chuàng)建的臨時(shí)文件重命名(2); 通常這意味著它需要與索引文件本身位于相同的文件系統(tǒng)上,并且您需要對(duì)索引文件和索引輸出文件所在目錄的寫入權(quán)限。
--no-recurse-submodules
使用--recurse子模塊將根據(jù)超級(jí)項(xiàng)目中記錄的提交,通過(guò)遞歸調(diào)用read-tree來(lái)更新所有已初始化的子模塊的內(nèi)容,同時(shí)還將子模塊HEAD設(shè)置為在該提交時(shí)分離。
--no-sparse-checkout
即使core.sparseCheckout
為真,也禁用稀疏結(jié)帳支持。
--empty
不要將樹對(duì)象讀入索引,只需將其清空即可。
<tree-ish#>
要讀取/合并的樹對(duì)象的ID。
如果-m
被指定,則git read-tree
可以執(zhí)行3種合并,如果僅給出1棵樹,則快速合并2棵樹,或者如果提供3棵或更多樹,則合并3種合并。
如果只指定了1棵樹,則git read-tree
操作就像用戶沒(méi)有指定一樣-m
,除非如果原始索引具有給定路徑名的條目,并且路徑的內(nèi)容與正在讀取的樹相匹配,則索引中的統(tǒng)計(jì)信息是用過(guò)的。(換句話說(shuō),索引的stat()優(yōu)先于合并樹的)。
這意味著如果你做了一個(gè)git read-tree -m <newtree>
跟隨git checkout-index -f -u -a
,git checkout-index
唯一的檢查出真正改變的東西。
這用于在git diff-files
運(yùn)行后避免不必要的錯(cuò)誤命中git read-tree
。
通常情況下,這被調(diào)用為git read-tree -m $H $M
,其中$ H是當(dāng)前存儲(chǔ)庫(kù)的頭部提交,而$ M是外部樹的頭部,它僅僅在$ H之前(即我們處于快進(jìn)狀態(tài))。
當(dāng)指定了兩棵樹時(shí),用戶告訴git read-tree
以下內(nèi)容:
當(dāng)前的索引和工作樹是從$ H派生的,但用戶可能會(huì)在$ H之后對(duì)其進(jìn)行本地更改。
用戶想要快進(jìn)到$ M。
在這種情況下,該git read-tree -m $H $M
命令確保本地更改不會(huì)因此“合并”而丟失。這里是“結(jié)轉(zhuǎn)”規(guī)則,其中“I”表示索引,“clean”表示索引和工作樹重合,“exists”/“nothing”表示指定提交中存在路徑:
I H M Result ------------------------------------------------------- 0 nothing nothing nothing (does not happen) 1 nothing nothing exists use M 2 nothing exists nothing remove path from index 3 nothing exists exists, use M if "initial checkout", H == M keep index otherwise exists, fail H != M clean I==H I==M ------------------ 4 yes N/A N/A nothing nothing keep index 5 no N/A N/A nothing nothing keep index 6 yes N/A yes nothing exists keep index 7 no N/A yes nothing exists keep index 8 yes N/A no nothing exists fail 9 no N/A no nothing exists fail 10 yes yes N/A exists nothing remove path from index 11 no yes N/A exists nothing fail 12 yes no N/A exists nothing fail 13 no no N/A exists nothing fail clean (H==M) ------ 14 yes exists exists keep index 15 no exists exists keep index clean I==H I==M (H!=M) ------------------ 16 yes no no exists exists fail 17 no no no exists exists fail 18 yes no yes exists exists keep index 19 no no yes exists exists keep index 20 yes yes no exists exists use M 21 no yes no exists exists fail
在所有“保持索引”的情況下,索引條目保持原來(lái)的索引文件。如果條目不是最新的,git read-tree
則在-u標(biāo)志下運(yùn)行時(shí),保持工作樹中的副本完好無(wú)損。
當(dāng)這種形式的git read-tree
回報(bào)成功時(shí),您可以看到您所做的“本地更改”是通過(guò)運(yùn)行結(jié)轉(zhuǎn)的git diff-index --cached $M
。請(qǐng)注意,這不一定與git diff-index --cached $H
在這樣的兩棵樹合并之前產(chǎn)生的結(jié)果相匹配。這是因?yàn)榍闆r18和19 ---如果你已經(jīng)有$ M的變化(例如,也許你通過(guò)電子郵件以補(bǔ)丁的形式提取它),git diff-index --cached $H
會(huì)在合并之前告訴你有關(guān)更改,但它git diff-index --cached $M
在兩棵樹合并后不會(huì)顯示在輸出中。
案例3有點(diǎn)棘手,需要解釋。從邏輯上來(lái)說(shuō),這條規(guī)則的結(jié)果應(yīng)該是在用戶暫停移除路徑然后切換到新的分支時(shí)刪除路徑。然而,這會(huì)阻止初始檢出的發(fā)生,所以只有當(dāng)索引的內(nèi)容為空時(shí),規(guī)則才會(huì)修改為使用M(新樹)。否則,只要$ H和$ M是相同的,路徑的移除將被保留。
每個(gè)“索引”條目具有兩個(gè)比特的“階段”狀態(tài)。第0階段是正常的階段,也是您在任何正常使用中都會(huì)看到的唯一階段。
但是,當(dāng)你git read-tree
使用三棵樹時(shí),“舞臺(tái)”從1開(kāi)始。
這意味著你可以做
$ git read-tree -m <tree1> <tree2> <tree3>
并且您將以“stage1”中的所有<tree1>條目,“stage2”中的所有<tree2>條目和“stage3”中的所有<tree3>條目結(jié)束索引。當(dāng)執(zhí)行另一個(gè)分支到當(dāng)前分支的合并時(shí),我們使用共同祖先樹作為<tree1>,當(dāng)前分支頭使用<tree2>,另一個(gè)分支頭使用<tree3>。
此外,git read-tree
還有一些特例邏輯:如果在下列狀態(tài)中看到所有方面都匹配的文件,它將“折疊”回“stage0”:
階段2和3是相同的; 采取一個(gè)或另一個(gè)(這沒(méi)有什么區(qū)別 - 第二階段我們的分支和第三階段的分支已經(jīng)完成了同樣的工作)
階段1和階段2是相同的,階段3是不同的; 進(jìn)入第3階段(我們?cè)诘?階段的分支自第1階段的祖先開(kāi)始沒(méi)有做任何事情,而第3階段的分支在第3階段進(jìn)行分析)
第一階段和第三階段是相同的,第二階段是不同的第二階段(我們做了什么,而他們什么也沒(méi)做)
該git write-tree
命令拒絕寫入一個(gè)無(wú)意義的樹,并且如果它看到一個(gè)不是0級(jí)的單個(gè)條目,它會(huì)抱怨未合并的條目。
好吧,這聽(tīng)起來(lái)像是一個(gè)完全沒(méi)有意義的規(guī)則集合,但它實(shí)際上正是你想要做的快速合并。不同的階段代表“結(jié)果樹”(階段0,又名“合并”),原始樹(階段1,又名“orig”)以及您嘗試合并的兩棵樹(分別為階段2和3)。
當(dāng)您使用已填充的索引文件開(kāi)始3路合并時(shí),階段1,2和3的順序(因此三個(gè)<tree-ish>命令行參數(shù)的順序)非常重要。以下是該算法的工作原理概述:
如果一個(gè)文件在所有三棵樹中都以相同的格式存在,它將自動(dòng)折疊為“合并”狀態(tài)git read-tree
。
any
在三棵樹中有差別的文件將作為單獨(dú)的條目保留在索引中。確定如何去除非0階段并插入合并版本取決于“瓷器政策”。
索引文件會(huì)保存并恢復(fù)所有這些信息,因此您可以逐步合并,但只要它具有1/2/3階段的條目(即“未合并條目”),則無(wú)法寫入結(jié)果。所以現(xiàn)在合并算法變得非常簡(jiǎn)單:
- you walk the index in order, and ignore all entries of stage 0, since they’ve already been done.
- if you find a "stage1", but no matching "stage2" or "stage3", you know it’s been removed from both trees (it only existed in the original tree), and you remove that entry.
- if you find a matching "stage2" and "stage3" tree, you remove one of them, and turn the other into a "stage0" entry. Remove any matching "stage1" entry if it exists too. .. all the normal trivial rules ..
您通常會(huì)使用git merge-index
提供的git merge-one-file
來(lái)完成最后一步。該腳本在合并每個(gè)路徑和成功合并結(jié)束時(shí)更新工作樹中的文件。
當(dāng)您使用已填充的索引文件開(kāi)始三向合并時(shí),假定它表示工作樹中文件的狀態(tài),并且甚至可以在索引文件中包含未記錄更改的文件。進(jìn)一步假定這個(gè)狀態(tài)是從階段2樹“派生”的。如果在原始索引文件中找到與第2階段不匹配的條目,則三向合并將拒絕運(yùn)行。
這樣做是為了防止您丟失正在進(jìn)行的工作更改,并在不相關(guān)的合并提交中混合您的隨機(jī)更改。為了說(shuō)明,假設(shè)您從最后一次提交到您的存儲(chǔ)庫(kù)開(kāi)始:
$ JC=`git rev-parse --verify "HEAD^0"`$ git checkout-index -f -u -a $JC
你做了隨機(jī)編輯,沒(méi)有運(yùn)行git update-index
。然后你注意到,從你拉下來(lái)之后,你的“上游”樹的尖端已經(jīng)提前:
$ git fetch git://.... linus $ LT=`git rev-parse FETCH_HEAD`
您的工作樹仍然基于您的HEAD($ JC),但您自此進(jìn)行了一些修改。三向合并可以確保你從$ JC開(kāi)始就沒(méi)有添加或修改過(guò)索引條目,如果你沒(méi)有,就做正確的事情。所以按照以下順序:
$ git read-tree -m -u `git merge-base $JC $LT` $JC $LT $ git merge-index git-merge-one-file -a $ echo "Merge with Linus" | \ git commit-tree `git write-tree` -p $JC -p $LT
你會(huì)承諾在$ JC和$ LT之間進(jìn)行純粹的合并,而無(wú)需進(jìn)行正在進(jìn)行的更改,并且您的工作樹將更新為合并結(jié)果。
但是,如果工作樹中的本地更改會(huì)被此合并覆蓋,git read-tree
將拒絕運(yùn)行以防止更改丟失。
換句話說(shuō),沒(méi)有必要擔(dān)心只存在于工作樹中的東西。如果在項(xiàng)目中沒(méi)有涉及合并的部分進(jìn)行本地更改,則更改不會(huì)影響合并,并且保持不變。當(dāng)他們不干預(yù),合并甚至不啟動(dòng)(git read-tree
大聲抱怨和失敗不進(jìn)行任何修改)。在這種情況下,你可以簡(jiǎn)單地繼續(xù)做你正在做的事情,當(dāng)你的工作樹準(zhǔn)備好時(shí)(即你已經(jīng)完成了正在進(jìn)行的工作),再次嘗試合并。
“稀疏結(jié)帳”允許稀疏地填充工作目錄。它使用skip-worktree位(請(qǐng)參閱git-update-index [1])來(lái)告訴Git工作目錄中的文件是否值得關(guān)注。
git read-tree
和其他基于合并的命令(git merge
,git checkout
...)可以幫助維護(hù)skip-worktree位圖和工作目錄更新。$GIT_DIR/info/sparse-checkout
用于定義跳轉(zhuǎn)工作樹引用位圖。當(dāng)git read-tree
需要更新工作目錄時(shí),它會(huì)根據(jù)此文件重置索引中的skip-worktree位,該文件使用與.gitignore文件相同的語(yǔ)法。如果條目與該文件中的模式匹配,則不會(huì)在該條目上設(shè)置skip-worktree。否則,將設(shè)置skip-worktree。
然后它將新的skip-worktree值與前一個(gè)值進(jìn)行比較。如果skip-worktree從設(shè)置變?yōu)槲丛O(shè)置,它將添加相應(yīng)的文件。如果從未設(shè)置變?yōu)樵O(shè)置,該文件將被刪除。
雖然$GIT_DIR/info/sparse-checkout
通常用于指定文件所在的位置,但也可以not
使用取反模式來(lái)指定所處的文件。例如,要?jiǎng)h除文件unwanted
:
/* !unwanted
另一個(gè)棘手的事情是,當(dāng)你不再需要稀疏結(jié)賬時(shí),完全重新填充工作目錄。您不能僅禁用“稀疏檢出”,因?yàn)閟kip-worktree位仍在索引中,并且您的工作目錄仍是稀疏填充的。您應(yīng)該使用$GIT_DIR/info/sparse-checkout
文件內(nèi)容重新填充工作目錄,如下所示:
/*
然后你可以禁用稀疏結(jié)帳。git read-tree
默認(rèn)情況下,禁用和類似命令中的稀疏檢出支持被禁用。您需要打開(kāi)core.sparseCheckout
才能擁有稀疏結(jié)帳支持。