2017-05-24 37 views
4

如果我從一個乾淨的工作樹開始並運行git checkout <branch> <file>,其中<branch>具有此文件的不同版本,那麼我最終將得到一個staged而不是unstaged的更改。爲什麼`git結帳<branch><file>`變更階段?

這是什麼原因?這只是爲了與其他命令(如git mv)保持一致,您可以期待這些命令進行更改嗎?使用git checkout解決合併衝突時是否方便?還是有其他一些基本原理?

對我來說這似乎有點奇怪,因爲只是使用git checkout <branch> <file>並沒有提供我是否計劃實施更改的任何指示。

+0

在'git checkout '中,分支被解析爲一棵樹,分支的頭部提交樹。該命令首先更新給定文件的索引,然後更新工作樹中的文件以匹配索引中的版本。所以現在工作樹和索引中的文件更新爲相同的。它就像'git add '一樣。 'git checkout --help'獲取更多信息。 – ElpieKay

+0

可能的重複[爲什麼結帳有時會暫存文件?](https://stackoverflow.com/questions/28837246/why-does-checkout-sometimes-stage-a-file) –

回答

4

這實際上是Git作者選擇通過展示的實現細節。

Git不能 - 或者更確切地說,在一個點上,可能不會將文件直接從存儲庫讀取到工作樹中。它已經(或已經)首先通過中間人傳遞它們:它必須複製它們,或者至少複製它們的重要統計數據,在其他地方。只有這樣Git才能將數據複製到工作樹文件中。 「其他地方」是索引條目。該指數也被稱爲臨時區域。

當你git checkout整個提交,這就是你想要的。所以內部限制,首先複製到索引,然後複製到工作樹上,實際上是一個優點。所以這個機制,首先複製到索引中,然後才進入工作樹,嵌入到實現中。然後,最終,面向用戶的git checkout前端獲得了簽出一個單獨文件或一小部分文件的能力......並且它繼續這樣做索引。實現細節成爲記錄的功能。

請注意,有時,索引在衝突合併期間被用作輔助區域。在這種情況下,對於一些文件F,在編號的時隙1(基),2(--ours)和3(--theirs)中有多達三個條目,而不是正常時隙零中的一個條目。如果是這樣,您可以將三個索引時隙條目中的任何一個提取到工作樹,而不會干擾索引。但是,如果您使用git checkout從其他提交或樹中提取文件,Git會將該文件複製到索引中,並將其寫入到零插槽。這有刪除的副作用,解決合併衝突!


的主要原因之一是散列ID。作爲ElpieKay noted in a comment,Git必須將提交哈希解析爲樹形哈希,然後搜索各種樹以找出哪個或哪些文件感興趣,以便它可以獲得blob哈希。儘管如此,索引條目本身也包含更多的數據,包括工作樹文件的stat結構數據,以使Git走得更快。

您還可以使用這個工作流程,通過使用git read-tree到樹複製到索引,然後使用git checkout-index複製指數的工作樹。最初,Git由一些shell腳本組成,如git-checkout,它們圍繞着一些基本的C編碼片段,如git-read-tree。(這些名字都是這樣的連字號,並且沒有前端git命令。)